链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,操作复杂。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn)和O(1)。
使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。链表最明显的好处就是,常规数组排列关联项目的方式可能不同于这些数据项目在记忆体或磁盘上顺序,数据的存取往往要在不同的排列顺序中转换。链表允许插入和移除表上任意位置上的节点,但是不允许随机存取。链表有很多种不同的类型:单向链表,双向链表以及循环链表。链表可以在多种编程语言中实现。像Lisp和Scheme这样的语言的内建数据类型中就包含了链表的存取和操作。程序语言或面向对象语言,如C,C++和Java依靠易变工具来生成链表。
#include
#include
#include
typedef struct LNode//链表结构体
{
int data;
struct LNode *next;
}LNode,*LinkList;
int CreateList_L(LinkList &L,int n)
{//逆序位输入n个值,建立带表头结点的单链表L
int i;
LinkList p;
L=(LinkList)malloc(sizeof(LNode));//建立空链表
L->next=NULL;
for(i=n;i>0;i--)
{
printf("正在输入第%d个元素",i);
p=(LinkList)malloc(sizeof(LNode));//开辟空间,生成新结点
scanf("%d",&p->data);//输入元素
p->next=L->next;
L->next=p;//插入到表头
}
return 1;
}
int ListInset_L(LinkList &L,int i,int e)//链表的插入
{//在带头的结点的单链表L中第i个位置前插入元素e
LinkList p,s;
int j=0;
p=L;
while(p&&j<i-1)
{
p=p->next;
++j;
}//寻找第i-1个结点
if(!p||j>i-1)
return 0;//i<1或者大于表长+1
s=(LinkList)malloc(sizeof(LNode));//生成新结点
s->data=e;
s->next=p->next;
p->next=s;//插入l中
return 1;
}
int ListDelete_L(LinkList &L,int i,int &e)//删除链表元素
{//在带头结点的单链表L中,删除第i个元素,并由e返回其值
LinkList p,q;
p=L;
int j=0;
while(p->next&&j<i-1)
{
p=p->next;
++j;
}//寻找第i个结点,并令p指向其前趋
if(!(p->next)||j>i-1)
return 0;//删除位置不合理
q=p->next;
p->next=q->next;//删除并释放结点
e=q->data;
free(q);
return 1;
}
int GetElem_L(LinkList L,int i,int &e)//按位置查找元素
{//L为带头结点的单链表的头指针
//当第i个元素存在时,其值给e并由e返回
LinkList p;
p=L->next;
int j=1;//初始化p,j为计数器
while(p&&j<i)
{
p=p->next;
++j;
}//顺时针向后查找,直到p指向第i个元素或为空
if(!p||j>i)
return 0;//第i个元素不存在
e=p->data;//取第i个元素
return 1;
}
void MergeList_L(LinkList &La,LinkList &Lb,LinkList &Lc)
{//已知单链表La和Lb元素按非递减排列
//归并La和Lb得到新链表Lc,Lc的元素也按非递减排列
LinkList pa,pb,pc;
pa=La->next;
pb=Lb->next;
Lc=pc=La;//用La的头结点作为Lc的头结点
while(pa&&pb)
{
if(pa->data<=pb->data)
{
pc->next=pa;
pc=pa;
pa=pa->next;
}
else
{
pc->next=pb;
pc=pb;
pb=pb->next;
}
}
pc->next=pa?pa:pb;//插入剩余段
free(Lb);//释放Lb的头结点
}
int Disp(LinkList L)//输出链表
{
LinkList p;
p=L->next;
if(p==NULL)
{
printf("此为空表\n");
}
else
{
printf("输出链表:\n");
while(p!=NULL)
{
printf("%d",p->data);
printf("\t");
p=p->next;
}
}
printf("\n");
return 1;
}
void show()
{
int n;
printf("请输入想选择的指令:\n");
printf("1.建立链表\n");
printf("2.插入元素\n");
printf("3.删除元素\n");
printf("4.查找元素\n");
printf("5.合并链表\n");
printf("0.退出\n");
printf("-------------------\n");
}
int main()
{
LinkList p1,p2,p3;
int i,j,k,e;
int n;
show();
scanf("%d", &n);
while (n != 0)
{
switch (n)
{
case 1:
printf("请输入你想建立一号链表内元素的个数:\n");
scanf("%d", &k);
CreateList_L(p1, k);
Disp(p1);
printf("请输入你想建立二号链表内元素的个数:\n");
scanf("%d", &k);
CreateList_L(p2, k);
Disp(p2);break;
case 2:
printf("请输入你想插入在一号链表内的元素和插入的位置:\n");
scanf("%d %d", &e, &i);
ListInset_L(p1, i, e);
Disp(p1);
printf("请输入你想插入在二号链表内的元素和插入的位置:\n");
scanf("%d %d", &e, &i);
ListInset_L(p2, i, e);
Disp(p2); break;
case 3:
printf("请输入你想删除的一号链表的位置:\n");
scanf("%d", &i);
ListDelete_L(p1, i, e);
Disp(p1);
printf("请输入你想删除的二号链表的位置:\n");
scanf("%d", &i);
ListDelete_L(p2, i, e);
Disp(p2); break;
case 4:
printf("请输入你想查看一号链表的位置:\n");
scanf("%d", &i);
GetElem_L(p1, i, e);
printf("该位置元素为:%d\n", e);
printf("请输入你想查看二号链表的位置:\n");
scanf("%d", &i);
GetElem_L(p2, i, e);
printf("该位置元素为:%d\n", e); break;
case 5:
MergeList_L(p1, p2, p3);
printf("合并后链表:\n");
Disp(p3); break;
}
printf("\n");
show();
scanf("%d", &n);
}
return 0;
}
希望对你有所帮助