前言
本文介绍线性表链式存储时基本操作的实现,包括链表的结构定义、初始化、创建、插入、删除、销毁、显示、判空、求长度、取元素,以及链表的合并。
主要参考:严蔚敏“数据结构及应用算法教程”教材
代码如下
#include<stdio.h>
#include<stdlib.h>
#define TRUE 1 //代码中出现True相当于出现1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -1
typedef int Status; //表示Status与int作用相同
typedef int ElemType; //表示ElemType与int作用相同
typedef struct LNode //定义
{
ElemType data; //数据域
struct LNode *next; //指针域
}LNode,*LinkList;
Status InitList_L(LinkList L) //初始化
{
L=(LinkList)malloc(sizeof(LNode)); //开辟存储空间
if(!L) //若开辟空间失败
exit(OVERFLOW); //返回OVERFLOW
L->next = NULL; //指针域赋值为空,创建一个空的头结点
printf("创建成功\n");
return OK;
}
void CreateList_L(LinkList L,int n) //创建
{
printf("please input %d number:\n",n);
L->next=NULL;
for (int I=n;I>0;--I)
{
LNode *p=(LNode *)malloc(sizeof(LNode));
scanf("%d",&(p->data));
p->next=L->next;
L->next=p;
}
printf("Create success!\n");
}
Status DestroyList_L(LinkList L) //销毁
{
if(!L) //线性表不存在的情况
{
printf("线性表不存在\n");
return ERROR;
}
LinkList p=L->next; //p指向首结点
while(p!=NULL) //若p结点不为空
{
free(L); //释放结点
L=p; //p结点赋值给L结点
p=L->next; //L的下一个结点赋给p
}
free(L); //释放之前动态分配给L的内存空间,但结点L仍存在
L=NULL; //将L赋值为空
printf("销毁成功\n");
}
Status ListEmpty_L(LinkList L) //判空
{
if(L) //若头结点不存在,则无法判断
{
if(L->next==NULL) //若首元结点为空,则链表为空
printf("线性表为空表\n");
else //若存在首元结点,则证明链表不是空表
printf("线性表不是空表\n");
}
else
{
printf("线性表不存在\n");
printf("\n");
}
return OK;
}
Status ListLength_L(LinkList L) //求长度
{
LinkList p=L->next; //p指向首元结点
int count=0;
while(p) //从第一个元素开始计数
{
p=p->next;
count++;
}
printf("线性表的长度为:%d\n",count);
printf("\n");
return count;
}
Status GetElem_L(LinkList L,int Loc) //取元素操作,Loc为取元素的位置
{
LinkList p;
p=L->next; //令p指向第一个元素
int count=1; //count从第一个元素开始计数
while(p&&count<Loc) //若没到要取元素的位置
{
p=p->next; //p指针像向一个节点移动
count++; //计数器加1
} //定位取元素的位置
if(!p||count>Loc) //若在循环过程中Loc大于链表长度,则p指针为空,则!p为true,执行if语句
{
printf("当前位置没有元素\n");
return ERROR;
}
printf("第%d个元素的值是:%d\n",Loc,p->data);
return OK;
}
Status ListInsert_L(LinkList L,int i,ElemType e) //插入,在链表L中第i个位置插入元素e
{
LinkList p,q;
p=L->next;
int count = 0;
while(p&&count<i-1)
{
p=p->next;
count++;
} //查找插入位置
if(!p||count>i-1)
{
printf("无法插入元素\n");
return ERROR;
}
q=(LinkList)malloc(sizeof(LNode)); //生成结点
q->data=e;
q->next=p->next;
p->next=q; //结点入链
return OK;
}
Status DeleteList_L(LinkList L,int i,ElemType *e) //删除链表L中的第i个元素,并利用e带回
{
LinkList p,q;
p=L->next;
int count = 0;
while(p&&count<i-1)
{
p=p->next;
count++;
} //查找要删除元素的位置
if(!p||count>i-1)
{
printf("无法删除元素\n");
return ERROR;
}
q=p->next;
p->next=q->next;
*e=q->data; //前驱与后继链接
free(q); //释放空间
q=NULL;
return OK;
}
Status ShowList_L(LinkList L) //打印
{
LinkList p;
p=L->next; //将链表的首元结点赋值给p
while(p!=NULL) //依次输出链表中的元素
{
printf("%d",p->data); //输出当前结点的数据域
p=p->next;
}
printf("\n");
return OK;
}
LNode *LocateElem_L(LinkList L, ElemType e) //定位
{
LNode *p=L;
while(p&&p->data!=e)
p=p->next; //依次查找
return p; //返回查找的结果,如果空表示没找到
}
void UnionList_L(LinkList La,LinkList Lb) //合并
{
LinkList pa,pb,p,q;
p=La;
pa=La->next;
pb=Lb->next;
while(pa&&pb)
{
if(pa->data > pb->data)
{
q=pb;
pb=pb->next;
p->next=q;
p=q;
q->next=pa;
}
else
{
p=pa;
pa=pa->next;
}
}
while(pa&&!pb) //如果pb为空
{
p->next=pa;
p=p->next;
pa=pa->next;
}
while(!pa&&pb) //如果pa为空
{
q=pb;
p->next=q;
pb=pb->next;
p=q;
}
}
int main()
{
LNode L,La,Lb;
InitList_L(&L);
InitList_L(&La);
InitList_L(&Lb);
CreateList_L(&L,4);
printf("创建的线性表L为:\n");
ShowList_L(&L);
ListLength_L(&L);
ListEmpty_L(&L);
GetElem_L(&L,2);
ListInsert_L(&L,1,9);
printf("插入,在1位置插入9:\n");
ShowList_L(&L);
int e;
DeleteList_L(&L,2,&e);
printf("删除,把位置2删除:\n");
printf("删除的元素为:%d\n",e);
ShowList_L(&L);
printf("%d\n",LocateElem_L(&L,9));
DestroyList_L(&L);
CreateList_L(&La,4);
printf("创建的线性表La为:\n");
ShowList_L(&La);
CreateList_L(&Lb,4);
printf("创建的线性表Lb为:\n");
ShowList_L(&Lb);
UnionList_L(&La,&Lb);
printf("合并后的线性表为:\n");
ShowList_L(&La);
return 0;
}