1、对于非空的线性表,有且仅有一个开始结点a1,它没有直接前趋,而仅有一个直接后继a2;有且仅有一个终端结点an,它没有直接后继,而仅有一个直接前趋an-1;其余的内部结点ai(2in-1)都有且有一个直接前趋ai-1和一个直接后继ai+1。常见的线性表的基本运算有如下六种:(1)InitList(L)构造一个空的线性表L,即表的初始化。(2)ListLength(L)求线性表L中的结点个数,即求表长。(3)GetNode(L,i) 取线性表L中的第i个结点,这里要求1iListLength(L)(4)LocateNode(L,x) 在L中查找值为X的结点,并返回该结点在L中的位置。若L中有多个结
2、点的值的X相同,则返回首次找到的结点位置;若L中没有结点的值为X,则返回一个特殊值表示查找失败。(5)InsertList(L,x,i)在线性表L的第I个位置上插入一个值为X的新结点,使得原编号为i,i+1,.,n的结点变为编号为i+1,i+2,.,n+1的结点。这里1in+1,而n是原表L的长度。插入后表L的长度加1.(6)DeleteList(L,i)删除线性表L的第i个结点,使得原编号为i+1,i+2,.,n的结点变成编号为i,i+1,.,n-1的结点。这里1in,而是原表L的长度。删除后表L的长度减1. 2.2线性表的顺序存储结构结点ai的存储地址Loc(ai)=Loc(a1)+(i-
3、1)*c 1in我们用结构类型来定义顺序表类型#define ListSine 100/表空间的大小可根据实际需要而定,这里假设为100Typedef DataType;/DataType的类型可根据实际情况而定,这里假设为intTypedef structDataType dataListSize;/向量Data用于存放表结点Int length;/当前的表长度Seqlist;在上述定义中线性表的开始结点a1和终端结点分别存储在L-data0和L-datal-length-1中。2.2.2顺序表上实现的基本运算1.插入 线性表的插入运算是指在表的第i个(1in+1)个位置上,插入一个新结点X
4、,使长度为n的线性表:(a1,ai-1,ai,an) 变为长度为n+1的线性表:(a1,ai-1, x,ai, an) 用顺序表作为线性表的存储结构时,由于结点的物理顺序必须将表中位置n,n-1,i上的结点,依次后移到位置n+1,n,i+1上,空出第i个位置,然后在该位置上插入新结点X.仅当插入位置i=n+1时,才无须移动结点,直接将X插入表的未尾.其插入过程如下见图,具体算法描述如下:a2.ai-1aiai+1an1i-1插入 XinListSize-1后移后a1an-1 X插入后插入前程序如下:Void InsertList (SeqList *L,DataType X,int i)/将新
5、结点x插入L所指的顺序表的第i个结点ai的位置上Int j;If(iLength+1)Error(position error);/非法位置,退出运行If(L-Length=ListSize)overflow/表空间溢出,退出运行for(j=L-Length-1;j=i-1;j-) L-dataj+1=L-dataj;/结点后移datai-1=x;/插入xLength+;/表长加1 2.删除线性表的删除运算是指将表的第i个(1in)个结点删去,使长度为n的线性表(a1,ai-1,ai,an)变成长度为 n-1的线性表(a1,ai-1,ai,an)和插入运算类似,在顺序表上实现删除运算也必须移动
6、结点,才能反映出结点间逻辑关系的变化.若i=n,则只要简单地删除终端结点,无须移动结点;若1in-1;则必须将表中位置i+1,i+2,n上的结点,依次前移到位置i,i+1,i+2,n-1上,以填补删除操作造成的空缺.具体算法如下:Void DeteList(Seqlist *L,int i)/Int i;1|L-length)position error /for(j=1;jlength-1;j+)dataj-1=L-Length-;/表长减少3.单链表的描述 单链表中每个结点的存储地址是存放在其前趋结点next域中,而开始结点无前趋,故应设头指针head指向开始点。同时,由于终端结点无后继,
7、故终端结点的指针域为空,即NULL(也可用表示)。单链表由头指针惟一确定,因此单链表可以用头指针(head)的名字来命名。例如,线性表(bat,cat,eat,fat,hat,jat,lat,mat)的单链表示意图可用箭头链接起来表示为: 单链表的一般图示法用C语言描述的单链表如下: typedef char DataTpye ; /假设结点的数据域类型是字符 typedef struct node /结点类型定义 DataType data; /结点的数据域 struct node * next; /结点的指针域 ListNode;Typedef ListNode * LinkList;Li
8、stNode * p;LinkList head;3.2单链表的插入(1) 头插法建表 从一个空表开始,重复读入数据,生成新结点,将读入数据存放到新结点的数据域中,然后将新结点插入到当前链表和表头上,直到读入结束标志为止。具体算法如下: LinkList CreateListF(void) /返回单链表的头指针 char ch; LinkList head; /头指针 ListNode * s; /工作指针 head = NULL; /链表开始为空 ch = getchar( ); /读第1个字符 while ( ch!=n) s=( ListNode * )malloc( sizeof( L
9、istNode );/生成新结点,对应图中的 s-data = ch; /将读入的数据放入新结点的数据域中,对应图中的next = head;/对应图中的 head = s; /对应图中的/读入下一字符 return head; /返回头指针(2)尾插法建表 该方法是将新结点插到当前链表的表尾上,为此必须增加一个尾指针r,使其始终指向当前链表的表尾。生成结点的顺序与输入顺序一致。建成表算法如下: LinkList CreateListR( void ) char ch; ListNode *s, *r;r = NULL; /链表初值为空,尾指针初值为空 while ( ch = getchar
10、 ( )! =n) s = ( ListNode * )malloc ( sizeof (ListNode);/对应下图 /对应下图 if ( head = NULL) /新结点插入空表 else r-next = s; /新结点插入非空表尾结点*r之后,对应下图 r = s; /尾指针指向新表尾,对应图 / end of while if ( r!= NULL)next = NULL; /对于非空表,将尾结点指针域置空在链表的开始结点之前附加一个结点(head),并称为头结点,将带来两个优点:1 由于开始结点的位置被存放在头结点的指针域中,所以在链表的第一个位置的操作就和在表的其它位置的操作
11、一样,无须进行特殊处理。2 无论表是否为空,其头指针是指向头结点的非空指针,因此,空表和非空表的处理也就统一了。引入头结点后,尾插法建链表的算法可简化为:LinkList CreateListR1( void ) LinkList head = (LinkList) malloc ( sizepof (ListNode) ); /生成头结点 ListNode *s,*r; r = head; /尾指针初值亦指向头结点 while ( ( ch = getchar( ) ) != n) s = ( ListNode * ) malloc (sizeof (ListNode ) ); /终端结点的
12、指针域置空,或空表的头结点指针域置空上述算法中申请新结点的处理应为: s = ( ListNode * ) malloc ( sizeof ( ListNode) ) if ( s = = NULL) /动态分配空间失败 Error ( “No space for node can be obtained”);/退出运行 /以下按正常情况处理2、 单链表的查找运算(1)按序号查找链表不是随机存取结构,所以在链表中,即使知道被访问结点的序号,也不能像顺序表那样直接按序访问,而只能从链表的头指针开始,顺链域逐个查找直到找到为止。如:单链表的长度为n,要查找表中第i个结点,仅当1in时,i值是合法的。当计数器j与
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1