总述
最后一位介绍的成员。
(附上单链表描述:http://blog.csdn.net/lliangw/article/details/50914976)
(附上双向链表描述:http://blog.csdn.net/lliangw/article/details/50915313)
概述
最灵活常用的链表。
实现
总体来说比较简单。
因为我们创建链表是构建了一个表头空结点,所以只要在一开始将其两个指针指向自己就行了。
这里引用一些非常实用的子函数。
创建一个空的双向循环链表
int InitList_L(LinkList &L)
{
if(L)DestroyList_L(L); //如果链表已存在,先销毁
L = (LinkList) malloc (sizeof (LNode));
if (!L) return 1; // 存储分配失败
L->num = MAXNUM; L->score = MAXSCORE;//表头空结点赋特殊值
memset(L->name,0,sizeof(L->name));
L->prior = L; // 双向循环链表只有表头空节点时,前向和后向
L->next = L; // 指针都是指向自己的
return 0;
}
测链表长度
int ListLength_L(LinkList L)
{
int i;
LinkList p = L->next;
for(i=0,p=L;p->next!=L;p=p->next,i++);//空循环,只计数 ;
return i;
}
销毁链表
void DestroyList_L(LinkList &L)
{
LinkList p = L->prior->prior;
for(L->prior==NULL;p;p=p->prior)//从后向前逐个销毁
free(p->next);
free(L);
}
回第pos个元素的地址
LinkList ListGetElem(LinkList L, int pos)
{
LinkList e = NULL; //定义结点指针
int len = ListLength_L(L);
if(pos<0 || pos>len)return 0; //位置不合法 ,思考为什么0也合法?
e = L;
for(int i=0;i<pos;i++,e=e->next); //空循环体,只是把e定位到pos-1
return e;
}
顺序输出链表
void PrintList_L(LinkList L)
{
LinkList p = L->next;
for(;p!=L;p=p->next)
cout << p->num << ' ' << p->name << ' ' << p->score << endl;
}
在链表中t指向的元素之后插入元素
int ListInsert_L(LinkList t, LNode e)
{
if(!t)return 1;//获取地址失败,返回
LinkList p = (LinkList) malloc (sizeof (LNode));
if (!p) return 1; // 存储分配失败
*p = e; //结构体是可以直接赋值的
p->next = t->next; t->next = p; //后向指针链接修改
p->next->prior = p; p->prior = t; //前向指针链接修改
return 0;
}
构造带数据的链表
int CreateList_L(LinkList &L)
{
if(L)DestroyList_L(L);//如果链表已存在,先销毁
InitList_L(L); //初始化链表
int i,n;
cin >> n;
while(n--)
{
LinkList p = (LinkList) malloc (sizeof (LNode));
if (!p) return 1; // 存储分配失败
cin >> p->num >> p->name >> p->score;
LinkList t = L->prior;
p->next = t->next; t->next = p; //后向指针链接修改
p->next->prior = p; p->prior = t; //前向指针链接修改
}
}
删除p指向的元素
int ListDelete_L(LinkList p)
{
if (p->num==MAXNUM || !p) return 1;//判定删除位置是否合法,表头能删吗?
p->prior->next = p->next; //后向指针链接修改
p->next->prior = p->prior; //前向指针链接修改
free(p); //销毁该元素
return 0;
}
学号相等判定函数
int CmpNum(LinkList pa, LinkList pb)
{
return pa->num == pb->num;
}
查找并返回地址,未找到返回表头空结点地址
利用外部函数判定
LinkList LocateElem_L(LinkList L, LNode e, int (*cmp)(LinkList,LinkList))
{
LinkList p=L->next; //p是查找指针
for(;p!=L;p=p->next)
if(cmp(p,&e))break;//循环查找,找到推出循环
return p; //返回找到元素的地址,或表头地址
}
有序合并链表
int Merg_L(LinkList La, LinkList Lb, LinkList &Lc)
{
if(Lc)DestroyList_L(Lc); //如果Lc不为空,销毁
if(InitList_L(Lc))return 1; //初始化Lc
LinkList pa,pb,pc,t; //定义指向三个链表元素的指针
LNode e; //定义一个结点变量,用于保存待插入学生数据
for(pa=La->next;pa!=La;pa=pa->next)
{
e = *pa; //待插入数据赋给e
t = LocateElem_L(Lc,e,cmp)->prior; //查找e插入的位置,找到插入点前驱结点地址
ListInsert_L(t,e); //插入e
}
for(pb=Lb->next;pb!=Lb;pb=pb->next)
{
e = *pb;
t = LocateElem_L(Lc,e,cmp)->prior;
ListInsert_L(t,e);
}
}
声明
如果文章中有错误,欢迎指出,我会及时改正!
此文章为原创,如需转载,请注明转载地址!
http://blog.csdn.net/lliangw