输出单链表c语言代码,用C语言实现单链表的各种操作

2013

本篇文章是对用C语言实现单链表的各种操作进行了详细的分析介绍,需要的朋友参考下

最近,从新复习了一下数据结构中比较重要的几个部分,现在把自己的成果记录下来,主要就是仿照严蔚敏的《数据结构》(C 语言版),中的例子和后面的习题进行改编的。首先,是单链表的各种实现,其中,包含了一些常考的知识点。例如,单链表的逆置,单链表的合并,找到单链表的中间节点等的算法实现。

下面这个是单链表的结构体的定义:

typedef struct LNode

{

ElemType data;

struct LNode *next;

}LinkList;

下面的基本的单链表的操作:其中,有一些宏,没有给出他们的一些定义,者可以通过,严蔚敏的《数据结构》(C 语言版),查看得到。

/* 功能:构建一个空的带头节点的单链表*/

Status InitList (struct LNode **L)

{

(*L) = (struct LNode *)malloc(sizeof(struct LNode)); //产生头节点

if(!*L)

exit(OVERFLOW);

(*L)->next = NULL;

return OK;

}

/*销毁线性表*/

Status DestroyList(struct LNode *L)

{

struct LNode *q;

while(L)

{

q = L->next;

free(L);

L = q;

}

return OK;

}

/*将L重置为空表*/

Status ClearList(struct LNode *L)

{

LinkList *p,*q;

p = L->next;

while(p)

{

q = p->next;

free(p);

p = q;

}

L->next = NULL;

return OK;

}

/*判断链表是否为空表*/

Status ListEmpty(LinkList *L)

{

if(L->next)

{

return FALSE;

}

else

{

return TRUE;

}

}

/*返回单链表中元素的个数*/

int ListLength(struct LNode *L)

{

int i=0;

LinkList *p = L->next;

while(p)

{

i++;

p = p->next;

}

return i;

}

/* L为带头节点的单链表的头指针,当第i个元素存在时,其值赋给e,并返回OK */

Status GetElem(struct LNode *L,int i,ElemType *e)

{

int j=1;

LinkList *p = L->next;

while(p && j

{

p = p->next;

j++;

}

if(!p || j>i)

return ERROR;

*e = p->data;

return OK;

}

/*返回L中第一个与e满足关系compare()的数据元素的位序,

若给存在返回值为0,compare()是数据元素的判定函数*/

int LocateElem(struct LNode *L,ElemType e,Status(*compare) (ElemType,ElemType))

{

int i =0;

LinkList *p = L->next;

while(p)

{

i++;

if(compare(p->data,e))

return i;

p=p->next;

}

return 0;

}

/*所cur_e是L中的数据元素,且给就第一个,则用pre_e返回它的前驱*/

Status PriorElem(struct LNode *L,ElemType cur_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;

return OK;

}

p = q;

}

return INFEASIBLE;

}

/* 若cur_e是L中的数据元素,且不是最后一个,则用next_e返回它的后继*/

Status NextElem(struct LNode *L,ElemType cur_e,ElemType *next_e)

{

LinkList *p;

p = L->next;

while(p->next)

{

if(p->data == cur_e)

{

* next_e = p->next->data;

return OK;

}

p = p->next;

}

return INFEASIBLE;

}

/* 在带头节点的单链表L中的第i个位置之前插入元素e*/

Status ListInsert(struct LNode *L,int i,ElemType e)

{

int j =0;

struct LNode *p=L,*s=NULL;

while(p && j

{

p=p->next;

j++;

}

if(!p || j>i-1)

return ERROR;

s = (struct LNode *)malloc(sizeof(struct LNode));

if(!s)

printf("malloc error~\n");

// p->next = s;

s->data = e;

// p->next = s;

s->next = p->next;

p->next = s;

//s->next = NULL;

// p = s;

return OK;

}

/*在带头节点的单链表中删除第i个元素,并有e返回其值*/

Status ListDelete(LinkList *L,int i,ElemType *e)

{

LinkList *p=L,*q;

int j=0;

while(p->next && j< i-1)

{

p = p->next;

j++;

}

if(!p->next || j>i-1)

return ERROR;

q = p->next;

p->next = q->next;

*e = q->data;

free(q);

return OK;

}

/* 依次对L的每个元素调用vi(),打印输出语句*/

Status ListTraverse(struct LNode *L,void (*vi)(ElemType))

{

LinkList *p = L->next;

while(p)

{

vi(p->data);

p = p->next;

}

printf("\n");

return OK;

}

/* 对单链表进行排序处理*/

struct LNode *sort(struct LNode *head)

{

LinkList *p;

int n,i,j;

int temp;

n = ListLength(head);

if(head == NULL || head->next == NULL)

return head;

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;

}

}

return head;

}

/*对单链表进行逆置*/

LinkList *reverse(LinkList *head)

{

LinkList *p1,*p2 = NULL,*p3 = NULL;

if(head == NULL || head->next == NULL)

return head;

p1 = head->next;

while(p1!=NULL)

{

p3 = p1->next;

p1->next = p2;

p2 = p1;

p1 = p3;

}

head->next = p2;

// head = p2;

return head;

}

Status equal(ElemType c1,ElemType c2)

{

if(c1== c2)

return TRUE;

else

return FALSE;

}

/*将所有在线性表Lb中但不在La中的数据元素插入到La 中*/

void Union(LinkList *La,LinkList *Lb)

{

ElemType *e;

int La_len,Lb_len;

int i;

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);

}

}

void print(ElemType c)

{

printf("%4d",c);

}

/* 合并两个单链表,La和Lb中的数据是按非递减排列,归并后的Lc还是安非递减排列*/

void MergeList(LinkList *La,LinkList *Lb,LinkList **Lc)

{

int i =1,j=1,k=0;

int La_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

{

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)

return NULL;

if(head->next == NULL)

return head;

if(head->next->next == NULL)

return head;

LinkList *mid= head;

LinkList *p = mid->next;

while((p != NULL) && (NULL !=p->next))

{

mid = mid->next;

p = p->next->next;

}

return mid;

}

下面主要是单链表的一个测试的程序。

Status comp(ElemType c1,ElemType c2)

{

if(c1==c2)

return TRUE;

else

return FALSE;

}

void visit(ElemType c)

{

printf("%4d",c);

}

void main()

{

LinkList *L;

LinkList *mid;

mid = (struct LNode *)malloc(sizeof(struct LNode));

ElemType *e,e0,*e1;

Status i;

int j,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("new La=");

ListTraverse(La,print);

printf("*************************************************\n");

LinkList *La_1,*Lb_1,*Lc_1;

int a[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= 6 5 4 3 2 1

L中间节点的值为mid=:4

L逆置后的输出:L= 1 2 3 4 5 6

L排序后依次为:L= 1 2 3 4 5 6

L 是否为空:i=0(1:是,0:否)

清空L后:L=

L是否为空:i=1

在L的表尾依次插入1~10后:L= 1 2 3 4 5 6 7 8 9 10

第5个元素的值为:5

没有值为0的元素

第1个元素的值为1

元素1无前驱

元素2的前驱为:1

元素9的后继为:10

元素10无后继

删除第11个数据失败

删除的元素为:10

依次输出L的元素: 1 2 3 4 5 6 7 8 9

销毁L后:L=7954544

*************************************************

La= 1 2 3 4 5

Lb = 2 4 6 8 10

new La= 1 2 3 4 5 6 8 10

*************************************************

La_1= 3 5 8 11

Lb_1= 2 6 8 9 11 15 20

Lc_1= 2 3 5 6 8 8 9 11 11 15 20

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值