本文是上一篇的续篇,所实现的功能与上一篇完全相同,不过本文的所有程序都采用C语言实现。
4.单链表编程实现----C语言
在C语言中函数和数据是分开的,每个函数都需要考虑链表的数据传递问题,这大大加大了编程的难度。
(1)链表的头文件 linklist.h
#ifndef LINKLIST_H
#define LINKLIST_H
typedef int ElemType;
typedef struct Node
{
ElemType data;
struct Node *Next;
}Node;
typedef Node* linklist;//给节点指针取别名
typedef enum Bool
{
FALSE,TRUE//枚举默认值从0开始,依次加1
}Bool;
Bool InitList(linklist* L);//初始化链表,给链表添加一个头结点
Bool GetElem(linklist L, int i, ElemType* e);//获得第i个位置的元素
Bool ListInsert(linklist* L,int i,ElemType e);//在第i个位置插入元素
Bool ListDelete(linklist* L,int i,ElemType* e);//删除第i个元素
Bool ListDeleteAll(linklist* L);//删除全部链表
void traverseList(linklist L);//遍历链表
void CreateListHead(linklist* L,int n);//头插法创建链表
void CreateListEnd(linklist* L,int n);//尾插法创建链表
void Reverse(linklist* L);//逆置链表
#endif // LINKLIST_H
(2)链表的源文件linklist.c
#include "linklist.h"
#include <stdio.h>
Bool GetElem(linklist L, int i, ElemType* e)
{
linklist p=L;
int j;
for(j=1;j<=i;j++)
{
p=p->Next;
if(p==NULL)
return FALSE;
}
*e=p->data;
return TRUE;
}
Bool ListInsert(linklist* L,int i,ElemType e)
{
linklist p=*L,s;
int j;
for(j=1;j<i;j++)
{
p=p->Next;
if(p==NULL)
return FALSE;
}
s=(linklist)malloc(sizeof(Node));
s->data=e;
s->Next=p->Next;
p->Next=s;
(*L)->data++;
return TRUE;
}
Bool ListDelete(linklist* L,int i,ElemType* e)
{
linklist p=*L,q;
int j;
for(j=1;j<i;j++)
{
p=p->Next;
if(p==NULL)
return FALSE;
}
q=p->Next;
p->Next=q->Next;
(*L)->data--;
*e=q->data;
free(q);
return TRUE;
}
Bool InitList(linklist* L)
{
*L=(linklist)malloc(sizeof(Node));
(*L)->data=0;
(*L)->Next=NULL;
return TRUE;
}
void traverseList(linklist L)
{
linklist p=L;
printf("链表总长度为:%d \n",p->data);
p=p->Next;
while(p)
{
printf("%d ",p->data);
p=p->Next;
}
printf("\n\n");
// printf("display ok!\n");
}
void CreateListHead(linklist* L,int n)
{
linklist p;
int i;
for(i=0;i<n;i++)
{
p=(linklist)malloc(sizeof(Node));
p->data=i;//rand()%100+1;
p->Next=(*L)->Next;
(*L)->Next=p;
(*L)->data++;
}
}
void CreateListEnd(linklist* L,int n)
{
linklist p,end=*L;
int i;
for(i=0;i<n;i++)
{
p=(linklist)malloc(sizeof(Node));
p->data=i;//rand()%100+1;
p->Next=NULL;
end->Next=p;
end=p;
(*L)->data++;
}
}
Bool ListDeleteAll(linklist* L)
{
linklist p=*L,q;
while(p->Next)
{
q=p->Next;
p->Next=q->Next;
(*L)->data--;
free(q);
}
free(p);
return TRUE;
}
void Reverse(linklist* L)//翻转链表
{
linklist cur, tmp;
//初始化新的头结点
cur=*L;
cur=cur->Next;//旧链表的头结点被删除(赋给了新的头结点)
(*L)->Next=NULL;//注意这一句和上一句不能颠倒,不然cur无法向后移
while (cur)
{
tmp=cur;
cur=cur->Next;//顺序删旧链表的元素
tmp->Next=(*L)->Next;//被删掉的元素用头插法插入新的头结点
(*L)->Next=tmp;
}
}
(3) 主程序main.c
#include <stdio.h>
#include "linklist.h"
int main()
{
int a;
linklist list;
printf(" 初始化\n");
InitList(&list);
traverseList(list);
InitList(&list);
printf(" 尾插法新建单链表\n");
CreateListEnd(&list,10);
traverseList(list);
ListDeleteAll(&list);
InitList(&list);
printf(" 头插法新建单链表\n");
CreateListHead(&list,10);
traverseList(list);
printf(" 元素插入\n");
ListInsert(&list,5,10);
traverseList(list);
printf(" 元素删除\n");
ListDelete(&list,5,&a);
printf("被删除的元素为:%d ",a);
traverseList(list);
printf(" 元素查找\n");
GetElem(list,3,&a);
printf("第3个元素为:%d \n\n\n",a);
printf(" 逆置链表\n");
printf("原链表----------");
traverseList(list);
Reverse(&list);
printf("逆置链表---------");
traverseList(list);
ListDeleteAll(&list);
return 0;
}