【 声明:版权所有,转载请标明出处,请勿用于商业用途。 联系信箱:[email protected]】
前言:
终于讲到书中的最后一个链表了,前面我们一步一步的介绍了顺序表,单链表,静态单链表,循环链表,双向链表,这次总算是进入了最后的链表学习了,那就是带头结点的线性链表,按照书本所说,这个是比前面几个更具有实用意义的链表。那么我也不多说了,让我们开始进入学习吧。
注:
本文仅代表博主本人的一些浅显的见解,欢迎大家评论学习,共同创造出一个良好的环境
对于一些问题,博主会尽量为大家解答,但是如果有疑问没有及时回答的,也希望其他热心人心帮忙解决,鄙人不胜感激
带头结点的线性链表
1.存储结构
在这里我们除了像之前的链表那样定义一个结点类型之外,我们还需要定义一个链表类型,结点类型还是记录着结点的数据data与其直接后继的指针next,而链表类型则是记录着整个链表的头指针head,尾指针tail和长度len
typedef struct LNode //结点类型
{
ElemType data;
struct LNode *next;
} LNode,*Link,*Position;
typedef struct //链表类型
{
Link head,tail; //分别指向线性链表中的头结点和最后一个结点
int len; //指示线性链表中数据元素的个数
} LinkList;
2.基本操作
以下给出的都是书本上定义的基本操作,相信在之前链表的学习中,大家对于链表的指针操作已经不会陌生了,通过所添加的注释应该能够很好的理解每个操作的原理,如果还有不懂的,也欢迎大家一起和我探讨。
Status MakeNode(Link *p,ElemType e)
{
// 操作结果:分配由p指向的值为e的结点,并返回OK;若分配失败。则返回ERROR
(*p) = (Link)malloc(sizeof(LNode)); //分配新结点
if(!(*p)) return ERROR; //分配失败
(*p)->data = e;
return OK;
}
void FreeNode(Link *p)
{
// 操作结果:释放p所指结点
free(*p);
(*p) = NULL;
}
Status InitList(LinkList *L)
{
// 操作结果:构造一个空的线性链表
Link p;
p = (Link)malloc(sizeof(LNode)); //生成头结点
if(p)
{
p->next = NULL;
(*L).head = (*L).tail = p;
(*L).len = 0;
return OK;
}
else
return ERROR;
}
Status ClearList(LinkList *L)
{
// 操作结果:将线性链表L重置为空表,并释放原链表的结点空间
Link p,q;
if((*L).head!=(*L).tail) //不是空表
{
p = q = (*L).head->next; //指向第一个结点
(*L).head->next = NULL;
while(p!=(*L).tail) //释放所有结点
{
p = q->next;
free(q);
q = p;
}
free(q);
(*L).tail = (*L).head;
(*L).len = 0;
}
return OK;
}
Status DestroyList(LinkList *L)
{
// 操作结果:销毁线性链表L,L不再存在
ClearList(L); //清空链表
FreeNode(&(*L).head); //释放头结点
(*L).tail = NULL;
(*L).len = 0;
return OK;
}
Status InsFirst(LinkList *L,Link h,Link s) //形参增加L,因为需修改L
{
// 操作结果:h指向L的一个结点,把h当做头结点,将s所指结点插入在第一个结点之前
s->next = h->next;
h->next = s;
if(h==(*L).tail) //h指向尾结点
(*L).tail = h->next; //修改尾指针
(*L).len++;
return OK;
}
Status DelFirst(LinkList *L,Link h,Link *q) //形参增加L,因为需修改L
{
// 操作结果:h指向L的一个结点,把h当做头结点,删除链表中的第一个结点并以q返回。若链表为空(h指向尾结点),q=NULL,返回FALSE
*q = h->next;
if(*q) //链表非空
{
h->next = (*q)->next;
if(!h->next) //删除尾结点
(*L).tail = h; //修改尾指针
(*L).len--;
return OK;
}
else
return FALSE; //链表空
}
Status Append(LinkList *L,Link s)
{
// 操作结果:将指针s(s->data为第一个数据元素)所指(彼此以指针相链,以NULL结尾)的一串结点链接在线性链表L的最后一个结点之后,并改变链表L的尾指针指向新的尾结点
int i=1;
(*L).tail->next = s; //s接到L的尾部
while(s->next) //计算s的长度
{
i++;
s = s->next;
}
(*L).tail = s; //L的尾指针变成s的尾指针
(*L).len+=i; //增加长度
return OK;
}
Position PriorPos(LinkList L,Link p)
{
// 操作结果:已知p指向线性链表L中的一个结点,返回p所指结点的直接前驱的位置,若无前驱,则返回NULL
Link q;
q = L.head->next;
if(q==p) return NULL; //无前驱
while(q->next!=p) //q不是p的直接前驱
q = q->next;
return q;
}
Status Remove(LinkList *L,Link *q)
{
// 操作结果:删除线性链表L中的尾结点并以q返回,改变链表L的尾指针指向新的尾结点
Link p = (*L).head;
if((*L).len==0) //空表
{
*q = NULL;
return FALSE;
}
while(p->next!=(*L).tail) //寻找尾结点
p = p->next;
*q = (*L).tail; //返回原来的尾结点
p->next = NULL; //尾结点变成NULL
(*L).tail = p; //修改尾结点地址
(*L).len--;
return OK;
}
Status InsBefore(LinkList *L,Link *p,Link s)
{
// 操作结果:已知p指向线性链表L中的一个结点,将s所指结点插入在p所指结点之前,并修改指针p指向新插入的结点
Link q;
q = PriorPos(*L,*p); //q是p的前驱
if(!q) //p无前驱
q = (*L).head;
s->next = *p; //插入操作
q->next = s;
*p = s;
(*L).len++;
return OK;
}
Status InsAfter(LinkList *L,Link *p,Link s)
{
// 操作结果:已知p指向线性链表L中的一个结点,将s所指结点插入在p所指结点之后,并修改指针p指向新插入的结点
if(*p==(*L).tail) //修改尾指针
(*L).tail = s;
s->next = (*p)->next; //插入操作
(*p)->next = s;
*p = s;
(*L).len++;
return OK;
}
Status SetCurElem(Link p,ElemType e)
{
// 操作结果:已知p指向线性链表中的一个结点,用e更新p所指结点中数据元素的值
p->data = e;
return OK;
}
ElemType GetCurElem(Link p)
{
// 操作结果:已知p指向线性链表中的一个结点,返回p所指结点中数据元素的值
return p->data;
}
Status ListEmpty(LinkList L)
{
// 操作结果:若线性链表L为空表,则返回TRUE,否则返回FALSE
return L.len==0;
}
int ListLength(LinkList L)
{
// 操作结果:返回线性链表L中元素个数
return L.len;
}
Position GetHead(LinkList L)
{
// 操作结果:返回线性链表L中头结点的位置
return L.head;
}
Position GetLast(LinkList L)
{
// 操作结果:返回线性链表L中最后一个结点的位置
return L.tail;
}
Position NextPos(Link p)
{
// 操作结果:已知p指向线性链表L中的一个结点,返回p所指结点的直接后继的位置
// 若无后继,则返回NULL
return p->next;
}
Status LocatePos(LinkList L,int i,Link *p)
{
// 操作结果:返回p指示线性链表L中第i个结点的位置,并返回OK,i值不合法时返回ERROR
// i=0为头结点
if(i<0 || i>L.len) return ERROR;
*p = L.head;
for(int j = 1; j<=i; j++)
*p=(*p)->next;
return OK;
}
Position LocateElem(LinkList L,ElemType e,Status (*compare)(ElemType,ElemType))
{
// 操作结果:返回线性链表L中第1个与e满足函数compare()判定关系的元素的位置,
// 若不存在这样的元素,则返回NULL
Link p;
int i = 1;
p = L.head;
do
{
p = p->next;
}
while(p && !compare(p->data,e));
return p;
}
Status ListTraverse(LinkList L,void(*visit)(ElemType))
{
// 操作结果:依次对L的每个数据元素调用函数visit()。一旦visit()失败,则操作失败
Link p = L.head->next;
for(int i = 1; i<=L.len; i++)
{
visit(p->data);
p = p->next;
}
printf("\n");
return OK;
}
Status OrderInsert(LinkList *L,ElemType e,int (*comp)(ElemType,ElemType))
{
// 操作结果:已知L为有序线性链表,将元素e按非降序插入在L中。(用于一元多项式) */
Link o,p,q;
q = (*L).head;
p = q->next;
while(p!=NULL && comp(p->data,e)<0) //p不是表尾且元素值小于e
{
q = p;
p = p->next;
}
o = (Link)malloc(sizeof(LNode)); //生成新结点
o->data = e; //赋值
q->next = o; //插入
o->next = p;
(*L).len++; //表长增加
if(!p) //插入表尾
(*L).tail = o; //修改尾结点
return OK;
}
Status LocateElemP(LinkList L,ElemType e,Position *q,int(*compare)(ElemType,ElemType))
{
// 操作结果:若升序链表L中存在与e满足判定函数compare()取值为0的元素,
// 则q指示L中第一个值为e的结点的位置,并返回TRUE;
// 否则q指示第一个与e满足判定函数 compare()取值>0的元素的前驱的位置。并返回FALSE。(用于一元多项式)
Link p=L.head,pp;
do
{
pp = p;
p = p->next;
}
while(p && compare(p->data,e)<0); //找到第一个大于等于e的位置
if(!p || compare(p->data,e)>0) //到表尾或者找到的位置的值并不相等
{
*q = pp;
return FALSE;
}
else //找到相等
{
*q = p;
return TRUE;
}
}
这正是书中的算法2.20与算法2.21,也是老知识点了,对于归并线性表的原理想必大家也早就烂熟于胸了吧。
Status ListInsert_L(LinkList *L,int i,ElemType e)
{
// 操作结果:在带头结点的单链线性表L的第i个元素之前插入元素e
Link h,s;
if(!LocatePos(*L,i-1,&h)) return ERROR; //i值不合法
if(!MakeNode(&s,e)) return ERROR; //结点分配失败
InsFirst(L,h,s); //对于从第i个结点开始的链表,第i-1个结点是它的头结点
return OK;
}
Status MergeList_L(LinkList La,LinkList Lb,LinkList *Lc,int(*compare)(ElemType,ElemType))
{
// 初始条件:已知单链线性表La和Lb的元素按值非递减排列。
// 操作结果:归并La和Lb得到新的单链,线性表Lc,Lc的元素也按值非递减排列。(不改变La、Lb)
Link ha,hb,pa,pb,q;
ElemType a,b;
if(!InitList(Lc)) return ERROR; //存储空间分配失败
ha = GetHead(La); //ha和hb分别指向La和Lb的头结点
hb = GetHead(Lb);
pa = NextPos(ha); //pa和pb分别指向La和Lb的第一个结点
pb = NextPos(hb);
while(!ListEmpty(La)&&!ListEmpty(Lb)) //La和Lb均非空
{
a = GetCurElem(pa); //a和b为两表中当前比较元素
b = GetCurElem(pb);
if(compare(a,b)<=0)
{
DelFirst(&La,ha,&q); //删除La的头结点并以q返回
InsFirst(Lc,(*Lc).tail,q); //把q插入作为Lc的尾结点
pa = NextPos(ha);
}
else
{
DelFirst(&Lb,hb,&q);
InsFirst(Lc,(*Lc).tail,q);
pb = NextPos(hb);
}
}
if(pa) Append(Lc,pa);
else Append(Lc,pb);
FreeNode(&ha);
FreeNode(&hb);
return OK;
}
#include "my.h"
typedef int ElemType;
typedef int Status;
typedef struct LNode //结点类型
{
ElemType data;
struct LNode *next;
} LNode,*Link,*Position;
typedef struct //链表类型
{
Link head,tail; //分别指向线性链表中的头结点和最后一个结点
int len; //指示线性链表中数据元素的个数
} LinkList;
Status MakeNode(Link *p,ElemType e)
{
// 操作结果:分配由p指向的值为e的结点,并返回OK;若分配失败。则返回ERROR
(*p) = (Link)malloc(sizeof(LNode)); //分配新结点
if(!(*p)) return ERROR; //分配失败
(*p)->data = e;
return OK;
}
void FreeNode(Link *p)
{
// 操作结果:释放p所指结点
free(*p);
(*p) = NULL;
}
Status InitList(LinkList *L)
{
// 操作结果:构造一个空的线性链表
Link p;
p = (Link)malloc(sizeof(LNode)); //生成头结点
if(p)
{
p->next = NULL;
(*L).head = (*L).tail = p;
(*L).len = 0;
return OK;
}
else
return ERROR;
}
Status ClearList(LinkList *L)
{
// 操作结果:将线性链表L重置为空表,并释放原链表的结点空间
Link p,q;
if((*L).head!=(*L).tail) //不是空表
{
p = q = (*L).head->next; //指向第一个结点
(*L).head->next = NULL;
while(p!=(*L).tail) //释放所有结点
{
p = q->next;
free(q);
q = p;
}
free(q);
(*L).tail = (*L).head;
(*L).len = 0;
}
return OK;
}
Status DestroyList(LinkList *L)
{
// 操作结果:销毁线性链表L,L不再存在
ClearList(L); //清空链表
FreeNode(&(*L).head); //释放头结点
(*L).tail = NULL;
(*L).len = 0;
return OK;
}
Status InsFirst(LinkList *L,Link h,Link s) //形参增加L,因为需修改L
{
// 操作结果:h指向L的一个结点,把h当做头结点,将s所指结点插入在第一个结点之前
s->next = h->next;
h->next = s;
if(h==(*L).tail) //h指向尾结点
(*L).tail = h->next; //修改尾指针
(*L).len++;
return OK;
}
Status DelFirst(LinkList *L,Link h,Link *q) //形参增加L,因为需修改L
{
// 操作结果:h指向L的一个结点,把h当做头结点,删除链表中的第一个结点并以q返回。若链表为空(h指向尾结点),q=NULL,返回FALSE
*q = h->next;
if(*q) //链表非空
{
h->next = (*q)->next;
if(!h->next) //删除尾结点
(*L).tail = h; //修改尾指针
(*L).len--;
return OK;
}
else
return FALSE; //链表空
}
Status Append(LinkList *L,Link s)
{
// 操作结果:将指针s(s->data为第一个数据元素)所指(彼此以指针相链,以NULL结尾)的一串结点链接在线性链表L的最后一个结点之后,并改变链表L的尾指针指向新的尾结点
int i=1;
(*L).tail->next = s; //s接到L的尾部
while(s->next) //计算s的长度
{
i++;
s = s->next;
}
(*L).tail = s; //L的尾指针变成s的尾指针
(*L).len+=i; //增加长度
return OK;
}
Position PriorPos(LinkList L,Link p)
{
// 操作结果:已知p指向线性链表L中的一个结点,返回p所指结点的直接前驱的位置,若无前驱,则返回NULL
Link q;
q = L.head->next;
if(q==p) return NULL; //无前驱
while(q->next!=p) //q不是p的直接前驱
q = q->next;
return q;
}
Status Remove(LinkList *L,Link *q)
{
// 操作结果:删除线性链表L中的尾结点并以q返回,改变链表L的尾指针指向新的尾结点
Link p = (*L).head;
if((*L).len==0) //空表
{
*q = NULL;
return FALSE;
}
while(p->next!=(*L).tail) //寻找尾结点
p = p->next;
*q = (*L).tail; //返回原来的尾结点
p->next = NULL; //尾结点变成NULL
(*L).tail = p; //修改尾结点地址
(*L).len--;
return OK;
}
Status InsBefore(LinkList *L,Link *p,Link s)
{
// 操作结果:已知p指向线性链表L中的一个结点,将s所指结点插入在p所指结点之前,并修改指针p指向新插入的结点
Link q;
q = PriorPos(*L,*p); //q是p的前驱
if(!q) //p无前驱
q = (*L).head;
s->next = *p; //插入操作
q->next = s;
*p = s;
(*L).len++;
return OK;
}
Status InsAfter(LinkList *L,Link *p,Link s)
{
// 操作结果:已知p指向线性链表L中的一个结点,将s所指结点插入在p所指结点之后,并修改指针p指向新插入的结点
if(*p==(*L).tail) //修改尾指针
(*L).tail = s;
s->next = (*p)->next; //插入操作
(*p)->next = s;
*p = s;
(*L).len++;
return OK;
}
Status SetCurElem(Link p,ElemType e)
{
// 操作结果:已知p指向线性链表中的一个结点,用e更新p所指结点中数据元素的值
p->data = e;
return OK;
}
ElemType GetCurElem(Link p)
{
// 操作结果:已知p指向线性链表中的一个结点,返回p所指结点中数据元素的值
return p->data;
}
Status ListEmpty(LinkList L)
{
// 操作结果:若线性链表L为空表,则返回TRUE,否则返回FALSE
return L.len==0;
}
int ListLength(LinkList L)
{
// 操作结果:返回线性链表L中元素个数
return L.len;
}
Position GetHead(LinkList L)
{
// 操作结果:返回线性链表L中头结点的位置
return L.head;
}
Position GetLast(LinkList L)
{
// 操作结果:返回线性链表L中最后一个结点的位置
return L.tail;
}
Position NextPos(Link p)
{
// 操作结果:已知p指向线性链表L中的一个结点,返回p所指结点的直接后继的位置
// 若无后继,则返回NULL
return p->next;
}
Status LocatePos(LinkList L,int i,Link *p)
{
// 操作结果:返回p指示线性链表L中第i个结点的位置,并返回OK,i值不合法时返回ERROR
// i=0为头结点
if(i<0 || i>L.len) return ERROR;
*p = L.head;
for(int j = 1; j<=i; j++)
*p=(*p)->next;
return OK;
}
Position LocateElem(LinkList L,ElemType e,Status (*compare)(ElemType,ElemType))
{
// 操作结果:返回线性链表L中第1个与e满足函数compare()判定关系的元素的位置,
// 若不存在这样的元素,则返回NULL
Link p;
int i = 1;
p = L.head;
do
{
p = p->next;
}
while(p && !compare(p->data,e));
return p;
}
Status ListTraverse(LinkList L,void(*visit)(ElemType))
{
// 操作结果:依次对L的每个数据元素调用函数visit()。一旦visit()失败,则操作失败
Link p = L.head->next;
for(int i = 1; i<=L.len; i++)
{
visit(p->data);
p = p->next;
}
printf("\n");
return OK;
}
Status OrderInsert(LinkList *L,ElemType e,int (*comp)(ElemType,ElemType))
{
// 操作结果:已知L为有序线性链表,将元素e按非降序插入在L中。(用于一元多项式) */
Link o,p,q;
q = (*L).head;
p = q->next;
while(p!=NULL && comp(p->data,e)<0) //p不是表尾且元素值小于e
{
q = p;
p = p->next;
}
o = (Link)malloc(sizeof(LNode)); //生成新结点
o->data = e; //赋值
q->next = o; //插入
o->next = p;
(*L).len++; //表长增加
if(!p) //插入表尾
(*L).tail = o; //修改尾结点
return OK;
}
Status LocateElemP(LinkList L,ElemType e,Position *q,int(*compare)(ElemType,ElemType))
{
// 操作结果:若升序链表L中存在与e满足判定函数compare()取值为0的元素,
// 则q指示L中第一个值为e的结点的位置,并返回TRUE;
// 否则q指示第一个与e满足判定函数 compare()取值>0的元素的前驱的位置。并返回FALSE。(用于一元多项式)
Link p=L.head,pp;
do
{
pp = p;
p = p->next;
}
while(p && compare(p->data,e)<0); //找到第一个大于等于e的位置
if(!p || compare(p->data,e)>0) //到表尾或者找到的位置的值并不相等
{
*q = pp;
return FALSE;
}
else //找到相等
{
*q = p;
return TRUE;
}
}
Status ListInsert_L(LinkList *L,int i,ElemType e)
{
// 操作结果:在带头结点的单链线性表L的第i个元素之前插入元素e
Link h,s;
if(!LocatePos(*L,i-1,&h)) return ERROR; //i值不合法
if(!MakeNode(&s,e)) return ERROR; //结点分配失败
InsFirst(L,h,s); //对于从第i个结点开始的链表,第i-1个结点是它的头结点
return OK;
}
Status MergeList_L(LinkList La,LinkList Lb,LinkList *Lc,int(*compare)(ElemType,ElemType))
{
// 初始条件:已知单链线性表La和Lb的元素按值非递减排列。
// 操作结果:归并La和Lb得到新的单链,线性表Lc,Lc的元素也按值非递减排列。(不改变La、Lb)
Link ha,hb,pa,pb,q;
ElemType a,b;
if(!InitList(Lc)) return ERROR; //存储空间分配失败
ha = GetHead(La); //ha和hb分别指向La和Lb的头结点
hb = GetHead(Lb);
pa = NextPos(ha); //pa和pb分别指向La和Lb的第一个结点
pb = NextPos(hb);
while(!ListEmpty(La)&&!ListEmpty(Lb)) //La和Lb均非空
{
a = GetCurElem(pa); //a和b为两表中当前比较元素
b = GetCurElem(pb);
if(compare(a,b)<=0)
{
DelFirst(&La,ha,&q); //删除La的头结点并以q返回
InsFirst(Lc,(*Lc).tail,q); //把q插入作为Lc的尾结点
pa = NextPos(ha);
}
else
{
DelFirst(&Lb,hb,&q);
InsFirst(Lc,(*Lc).tail,q);
pb = NextPos(hb);
}
}
if(pa) Append(Lc,pa);
else Append(Lc,pb);
FreeNode(&ha);
FreeNode(&hb);
return OK;
}
Status compare(ElemType c1,ElemType c2)
{
return c1==c2;
}
int cmp(ElemType a,ElemType b)
{
if(a==b)
return 0;
else if(adata);
else
printf("链表中没有值为%d的元素。\n",j);
}
printf("输出链表:");
ListTraverse(L,visit); //输出L
for(j=1; j<=4; j++)
{
printf("删除表头结点:");
DelFirst(&L,L.head,&p); //删除L的首结点,并以p返回
if(p)
printf("%d\n",GetCurElem(p));
else
printf("表空,无法删除 p=%u\n",p);
}
printf("L中结点个数=%d L是否空 %d(1:空 0:否)\n",ListLength(L),ListEmpty(L));
MakeNode(&p,10);
p->next=NULL; //尾结点
for(j=4; j>=1; j--)
{
MakeNode(&h,j*2);
h->next=p;
p=h;
} //h指向一串5个结点,其值依次是2 4 6 8 10
Append(&L,h); //把结点h链接在线性链表L的最后一个结点之后
OrderInsert(&L,12,cmp); //按升序插在有序表尾头
OrderInsert(&L,7,cmp); //按升序插在有序表中间
printf("输出链表:");
ListTraverse(L,visit); //输出L
for(j=1; j<=2; j++)
{
p=LocateElem(L,j*5,compare);
if(p)
printf("L中存在值为%d的结点。\n",j*5);
else
printf("L中不存在值为%d的结点。\n",j*5);
}
for(j=1; j<=2; j++)
{
LocatePos(L,j,&p); //p指向L的第j个结点
h=PriorPos(L,p); //h指向p的前驱
if(h)
printf("%d的前驱是%d。\n",p->data,h->data);
else
printf("%d没前驱。\n",p->data);
}
k=ListLength(L);
for(j=k-1; j<=k; j++)
{
LocatePos(L,j,&p); //p指向L的第j个结点
h=NextPos(p); //h指向p的后继
if(h)
printf("%d的后继是%d。\n",p->data,h->data);
else
printf("%d没后继。\n",p->data);
}
printf("L中结点个数=%d L是否空 %d(1:空 0:否)\n",ListLength(L),ListEmpty(L));
p=GetLast(L); //p指向最后一个结点
SetCurElem(p,15); //将最后一个结点的值变为15
printf("第1个元素为%d 最后1个元素为%d\n",GetCurElem(GetHead(L)->next),GetCurElem(p));
MakeNode(&h,10);
InsBefore(&L,&p,h); //将10插到尾结点之前,p指向新结点
p=p->next; //p恢复为尾结点
MakeNode(&h,20);
InsAfter(&L,&p,h); //将20插到尾结点之后
k=ListLength(L);
printf("依次删除表尾结点并输出其值:");
for(j=0; j<=k; j++)
{
i=Remove(&L,&p);
if(!i) //删除不成功
printf("删除不成功 p=%u\n",p);
else
printf("%d ",p->data);
}
MakeNode(&p,29); //重建具有1个结点(29)的链表
InsFirst(&L,L.head,p);
DestroyList(&L); //销毁线性链表L
printf("销毁线性链表L之后: L.head=%u L.tail=%u L.len=%d\n",L.head,L.tail,L.len);
// 归并操作
LinkList La,Lb,Lc;
InitList(&La);
for(j=1; j<=5; j++)
ListInsert_L(&La,j,j); //顺序插入 1 2 3 4 5
printf("La=");
ListTraverse(La,visit);
InitList(&Lb);
for(j=1; j<=5; j++)
ListInsert_L(&Lb,j,2*j); //顺序插入 2 4 6 8 10
printf("Lb=");
ListTraverse(Lb,visit);
InitList(&Lc);
MergeList_L(La,Lb,&Lc,comp); //归并La和Lb,产生Lc
printf("Lc=");
ListTraverse(Lc,visit);
DestroyList(&Lc);
return 0;
}
基本的链表学习到此应该就算是告一段落了,不知道大家是否有所收获呢?
下一次我会介绍以书本最后的一元多项式实现,然后便结束我们的第二章的学习。