单链表各种操作的C语言实现.docx
《单链表各种操作的C语言实现.docx》由会员分享,可在线阅读,更多相关《单链表各种操作的C语言实现.docx(16页珍藏版)》请在冰豆网上搜索。
![单链表各种操作的C语言实现.docx](https://file1.bdocx.com/fileroot1/2022-11/21/f4fb006d-c189-4a94-b18e-4c7689b1cbb5/f4fb006d-c189-4a94-b18e-4c7689b1cbb51.gif)
单链表各种操作的C语言实现
单链表各种操作的C语言实现
(一)2010-07-3113:
41:
43
分类:
C/C++
最近,从新复习了一下数据结构中比较重要的几个部分,现在把自己的成果记录下来,主要就是仿照严蔚敏的《数据结构》(C语言版),中的例子和后面的习题进行改编的。
首先,是单链表的各种实现,其中,包含了一些常考的知识点。
例如,单链表的逆置,单链表的合并,找到单链表的中间节点等的算法实现。
下面这个是单链表的结构体的定义:
typedefstructLNode
{
ElemTypedata;
structLNode*next;
}LinkList;
下面的基本的单链表的操作:
其中,有一些宏,没有给出他们的一些定义,者可以通过,严蔚敏的《数据结构》(C语言版),查看得到。
/*功能:
构建一个空的带头节点的单链表*/
StatusInitList(structLNode**L)
{
(*L)=(structLNode*)malloc(sizeof(structLNode));//产生头节点
if(!
*L)
exit(OVERFLOW);
(*L)->next=NULL;
returnOK;
}
/*销毁线性表*/
StatusDestroyList(structLNode*L)
{
structLNode*q;
while(L)
{
q=L->next;
free(L);
L=q;
}
returnOK;
}
/*将L重置为空表*/
StatusClearList(structLNode*L)
{
LinkList*p,*q;
p=L->next;
while(p)
{
q=p->next;
free(p);
p=q;
}
L->next=NULL;
returnOK;
}
/*判断链表是否为空表*/
StatusListEmpty(LinkList*L)
{
if(L->next)
{
returnFALSE;
}
else
{
returnTRUE;
}
}
/*返回单链表中元素的个数*/
intListLength(structLNode*L)
{
inti=0;
LinkList*p=L->next;
while(p)
{
i++;
p=p->next;
}
returni;
}
/*L为带头节点的单链表的头指针,当第i个元素存在时,其值赋给e,并返回OK*/
StatusGetElem(structLNode*L,inti,ElemType*e)
{
intj=1;
LinkList*p=L->next;
while(p&&j
{
p=p->next;
j++;
}
if(!
p||j>i)
returnERROR;
*e=p->data;
returnOK;
}
/*返回L中第一个与e满足关系compare()的数据元素的位序,
若给存在返回值为0,compare()是数据元素的判定函数*/
intLocateElem(structLNode*L,ElemTypee,Status(*compare)(ElemType,ElemType))
{
inti=0;
LinkList*p=L->next;
while(p)
{
i++;
if(compare(p->data,e))
returni;
p=p->next;
}
return0;
}
/*所cur_e是L中的数据元素,且给就第一个,则用pre_e返回它的前驱*/
StatusPriorElem(structLNode*L,ElemTypecur_e,ElemType*pre_e)
{
LinkList*q,*p=L->next;
while(p->next)
{
q=p->next;//q指向p的后继
if(q->data==cur_e)
{
*pre_e=p->data;
returnOK;
}
p=q;
}
returnINFEASIBLE;
}
/*若cur_e是L中的数据元素,且不是最后一个,则用next_e返回它的后继*/
StatusNextElem(structLNode*L,ElemTypecur_e,ElemType*next_e)
{
LinkList*p;
p=L->next;
while(p->next)
{
if(p->data==cur_e)
{
*next_e=p->next->data;
returnOK;
}
p=p->next;
}
returnINFEASIBLE;
}
/*在带头节点的单链表L中的第i个位置之前插入元素e*/
StatusListInsert(structLNode*L,inti,ElemTypee)
{
intj=0;
structLNode*p=L,*s=NULL;
while(p&&j {
p=p->next;
j++;
}
if(!
p||j>i-1)
returnERROR;
s=(structLNode*)malloc(sizeof(structLNode));
if(!
s)
printf("mallocerror~\n");
//p->next=s;
s->data=e;
//p->next=s;
s->next=p->next;
p->next=s;
//s->next=NULL;
//p=s;
returnOK;
}
/*在带头节点的单链表中删除第i个元素,并有e返回其值*/
StatusListDelete(LinkList*L,inti,ElemType*e)
{
LinkList*p=L,*q;
intj=0;
while(p->next&&j {
p=p->next;
j++;
}
if(!
p->next||j>i-1)
returnERROR;
q=p->next;
p->next=q->next;
*e=q->data;
free(q);
returnOK;
}
/*依次对L的每个元素调用vi(),打印输出语句*/
StatusListTraverse(structLNode*L,void(*vi)(ElemType))
{
LinkList*p=L->next;
while(p)
{
vi(p->data);
p=p->next;
}
printf("\n");
returnOK;
}
/*对单链表进行排序处理*/
structLNode*sort(structLNode*head)
{
LinkList*p;
intn,i,j;
inttemp;
n=ListLength(head);
if(head==NULL||head->next==NULL)
returnhead;
p=head->next;
for(j=1;j {
p=head->next;
for(i=0;i {
if(p->data>p->next->data)
{
temp=p->data;
p->data=p->next->data;
p->next->data=temp;
}
p=p->next;
}
}
returnhead;
}
/*对单链表进行逆置*/
LinkList*reverse(LinkList*head)
{
LinkList*p1,*p2=NULL,*p3=NULL;
if(head==NULL||head->next==NULL)
returnhead;
p1=head->next;
while(p1!
=NULL)
{
p3=p1->next;
p1->next=p2;
p2=p1;
p1=p3;
}
head->next=p2;
//head=p2;
returnhead;
}
Statusequal(ElemTypec1,ElemTypec2)
{
if(c1==c2)
returnTRUE;
else
returnFALSE;
}
/*将所有在线性表Lb中但不在La中的数据元素插入到La中*/
voidUnion(LinkList*La,LinkList*Lb)
{
ElemType*e;
intLa_len,Lb_len;
inti;
La_len=ListLength(La);
Lb_len=ListLength(Lb);
for(i=1;i<=Lb_len;i++)
{
GetElem(Lb,i,e);//取Lb中第i个元素赋给e
if(!
LocateElem(La,*e,equal))//La中不存在和e相同的元素,则插入
ListInsert(La,++La_len,*e);
}
}
voidprint(ElemTypec)
{
printf("%4d",c);
}
/*合并两个单链表,La和Lb中的数据是按非递减排列,归并后的Lc还是安非递减排列*/
voidMergeList(LinkList*La,LinkList*Lb,LinkList**Lc)
{
inti=1,j=1,k=0;
intLa_len,Lb_len;
ElemType*ai,*bj;
ai=(ElemType*)malloc(sizeof(ElemType));
bj=(ElemType*)malloc(sizeof(ElemType));
InitList(Lc);
La_len=ListLength(La);
Lb_len=ListLength(Lb);
while(i<=La_len&&j<=Lb_len)
{
GetElem(La,i,ai);
GetElem(Lb,j,bj);
if(*ai<*bj)
{
ListInsert(*Lc,++k,*ai);
++i;
}
else
{
ListInsert(*Lc,++k,*bj);
++j;
}
}
while(i<=La_len)
{
GetElem(La,i++,ai);
ListInsert(*Lc,++k,*ai);
}
while(j<=Lb_len)
{
GetElem(Lb,j++,bj);
ListInsert(*Lc,++k,*bj);
}
}
/*只遍历一次,找到单链表中的中间节点
1定义两个指针,一个指针每次移动两个步长(快指针),另一个指针每次移动一个数据(慢指针)
2.当快指针到达链表尾部的时候,慢指针就到了链表的中间节点
在程序中也可以判断一个单链表是否有环,如果快指针一定能够追赶上慢指针,否则就会以NULL结束*/
LinkList*Searchmid(LinkList*head)
{
if(NULL==head)
returnNULL;
if(head->next==NULL)
returnhead;
if(head->next->next==NULL)
returnhead;
LinkList*mid=head;
LinkList*p=mid->next;
while((p!
=NULL)&&(NULL!
=p->next))
{
mid=mid->next;
p=p->next->next;
}
returnmid;
}
下面主要是单链表的一个测试的程序。
Statuscomp(ElemTypec1,ElemTypec2)
{
if(c1==c2)
returnTRUE;
else
returnFALSE;
}
voidvisit(ElemTypec)
{
printf("%4d",c);
}
voidmain()
{
LinkList*L;
LinkList*mid;
mid=(structLNode*)malloc(sizeof(structLNode));
ElemType*e,e0,*e1;
Statusi;
intj,k;
e=(ElemType*)malloc(sizeof(ElemType));
e1=(ElemType*)malloc(sizeof(ElemType));
i=InitList(&L);
for(j=1;j<=6;j++)
{
i=ListInsert(L,1,j);
}
printf("在L的表头依次插入1~6后:
L=");
ListTraverse(L,visit);
printf("L中间节点的值为mid=:
");
mid=Searchmid(L);
printf("%d\n",mid->data);
printf("L逆置后的输出:
L=");
ListTraverse(reverse(L),visit);
printf("L排序后依次为:
L=");
ListTraverse(sort(L),visit);
i=ListEmpty(L);
printf("L是否为空:
i=%d(1:
是,0:
否)\n",i);
i=ClearList(L);
printf("清空L后:
L=");
ListTraverse(L,visit);
i=ListEmpty(L);
printf("L是否为空:
i=%d\n",i);
for(j=1;j<=10;j++)
{
ListInsert(L,j,j);
}
printf("在L的表尾依次插入1~10后:
L=");
ListTraverse(L,visit);
GetElem(L,5,e);
printf("第5个元素的值为:
%d\n",*e);
for(j=0;j<=1;j++)
{
k=LocateElem(L,j,comp);
if(k)
printf("第%d个元素的值为%d\n",k,j);
else
printf("没有值为%d的元素\n",j);
}
for(j=1;j<=2;j++)
{
GetElem(L,j,e1);
i=PriorElem(L,*e1,e);
if(i==INFEASIBLE)
printf("元素%d无前驱\n",*e1);
else
printf("元素%d的前驱为:
%d\n",*e1,*e);
}
for(j=ListLength(L)-1;j<=ListLength(L);j++)
{
GetElem(L,j,e1);
i=NextElem(L,*e1,e);
if(i==INFEASIBLE)
printf("元素%d无后继\n",*e1);
else
printf("元素%d的后继为:
%d\n",*e1,*e);
}
k=ListLength(L);
for(j=k+1;j>=k;j--)
{
i=ListDelete(L,j,e);
if(i==ERROR)
printf("删除第%d个数据失败\n",j);
else
printf("删除的元素为:
%d\n",*e);
}
printf("依次输出L的元素:
");
ListTraverse(L,visit);
DestroyList(L);
printf("销毁L后:
L=%u\n",L);
printf("*************************************************\n");
LinkList*La,*Lb;
i=InitList(&La);
if(i==1)
for(j=1;j<=5;j++)
i=ListInsert(La,j,j);
printf("La=");
ListTraverse(La,print);
InitList(&Lb);
for(j=1;j<=5;j++)
i=ListInsert(Lb,j,2*j);
printf("Lb=");
ListTraverse(Lb,print);
Union(La,Lb);
printf("newLa=");
ListTraverse(La,print);
printf("*************************************************\n");
LinkList*La_1,*Lb_1,*Lc_1;
inta[4]={3,5,8,11},b[7]={2,6,8,9,11,15,20};
InitList(&La_1);
for(j=1;j<=4;j++)
ListInsert(La_1,j,a[j-1]);
printf("La_1=");
ListTraverse(La_1,print);
InitList(&Lb_1);
for(j=1;j<=7;j++)
ListInsert(Lb_1,j,b[j-1]);
printf("Lb_1=");
ListTraverse(Lb_1,print);
MergeList(La_1,Lb_1,&Lc_1);
printf("Lc_1=");
ListTraverse(Lc_1,print);
}
下面是在Linux下的部分运行结果:
在L的表头依次插入1~6后:
L=654321
L中间节点的值为mid=:
4
L逆置后的输出:
L=123456
L排序后依次为:
L=123456
L是否为空:
i=0(1:
是,0:
否)
清空L后:
L=
L是否为空:
i=1
在L的表尾依次插入1~10后:
L=12345678910
第5个元素的值为:
5
没有值为0的元素
第1个元素的值为1
元素1无前驱
元素2的前驱为:
1
元素9的后继为:
10
元素10无后继
删除第11个数据失败
删除的元素为:
10
依次输出L的元素:
123456789
销毁L后:
L=7954544
*************************************************
La=12345
Lb=246810
newLa=123456810
*************************************************
La_1=35811
Lb_1=2689111520
Lc_1=235688911111520
/*功能:
构建一个空的带头节点的单链表*/
StatusInitList_CL(structLNode**L)
{
(*L)=(structLNode*)malloc(sizeof(structLNode));//产生头节点
if(!
*L)
exit(OVERFLOW);
(*L)->next=*L;
returnOK;
}
/*销毁线性表*/
StatusDestroyList_CL(structLNode*L)
{
structLNode*q=L->next,*p=(L)->next;
while(q!
=(L))
{
q=L->next;
free(L);
L=q;
}
free(L);
L=NULL;
returnOK;
}
/*将L重置为空表*/
StatusClearList_CL(structLNode*L)
{
LinkList*p,*q;
L=L->next;
p=L->next;
while(p!
=L)
{
q=p->next;
free(p);
p=q;
}
L->next=L;
returnOK;
}
/*判断链表是否为空表*/
StatusListEmpty_CL(LinkList*L)
{
if(L->next==L)
{
returnTRUE;
}
else
{
re