#include "stdio.h"
#include "malloc.h" //用于malloc、realloc函数
typedef int Type;
typedef struct lnode
{
Type data; //数据域
struct lnode* next;//指针域
}Lnode, * LinkList;//Lnode为结点类型 LinkList为指向Lnode型的指针变量
//函数说明
void CreateList_1(LinkList L, int n); //逆序建表函数
void CreateList_2(LinkList L, int n); //顺序建表函数
void OutPut(LinkList L);//遍历链表函数
Type ListLength(LinkList L); //求链表的长度函数
void GetElem(LinkList L, int i, Type* e); //取第i个数据元素函数
void ListInsert(LinkList L, int i, Type e);//插入
void ListDelete(LinkList L, int i, Type e);//删除
void ClearList(LinkList L); //清空算法
void MergerList(LinkList LA, LinkList LB, LinkList LC); //合并算法 LC=LA∪LB
void main()
{
int i = 1;//用于循环
Lnode L1, L2, L3;
Type n; //个数变量
Type pos; //位置变量
Type e; //结点数据域变量
while (i)
{
printf("该程序用于实现链表的基本操作\n");
printf("1---------------逆序赋值链表\n");
printf("2---------------顺序赋值链表\n");
printf("3---------------求链表的长度\n");
printf("4---------------取第某个数据\n");
printf("5---------------插入节点数据\n");
printf("6---------------删除节点数据\n");
printf("7---------------清空当前链表\n");
printf("8---------------合并链表算法\n");
printf("0---------------退出\n");
scanf_s("%d", &i);
switch (i)
{
case 1:
printf("请输入链表L1的长度(逆序建表):\n");
scanf_s("%d", &n);
CreateList_1(&L1, n);
OutPut(&L1);
break;
case 2:
printf("请输入链表L1的长度(顺序建表):\n");
scanf_s("%d", &n);
CreateList_2(&L1, n);
OutPut(&L1);
break;
case 3:
printf("L1链表的长度是 %d \n\n", ListLength(&L1));
break;
case 4:
printf("请输入要查找的位置");
scanf_s("%d", &pos);
GetElem(&L1, pos, &e);
printf("第%d个数据元素是%d\n", pos, e);
break;
case 5:
printf("请输入要插入的位置");
scanf_s("%d", &pos);
printf("请输入要插入的值");
scanf_s("%d", &e);
ListInsert(&L1, pos, e);
printf("插入后的链表:");
OutPut(&L1);
break;
case 6:
printf("请输入要删除的位置");
scanf_s("%d", &pos);
ListDelete(&L1, pos, &e);
printf("删除后的链表:");
OutPut(&L1);
printf("删除的节点数据:%d", e);
break;
case 7:
ClearList(&L1);
break;
case 8:
printf("请输入链表L2的长度(顺序建表):\n");
scanf_s("%d", &n);
CreateList_2(&L2, n);
printf("L1");
OutPut(&L1);
printf("L2");
OutPut(&L2);
MergerList(&L1, &L2, &L3);
printf("合并后的链表:\n");
OutPut(&L3);
break;
}
}
}
void CreateList_1(LinkList L, int n)//逆序建表函数
{
int i; //用于循环
Lnode* p;
L->next = NULL; //新建一个带头结点的单链表;头结点的next为NULL
for (i = n; i > 0; i--) //循环建立数据结点
{
printf("第 %d 个结点的数值:", i);
p = malloc(sizeof(Lnode)); //创建数据结点p
scanf_s("%d", &p->data); //给p的data赋值
p->next = L->next; //将p插在原开始结点之前,头结点后
L->next = p;
}
}
void CreateList_2(LinkList L, int n) //顺序建表函数
{
int i; //用于循环
Lnode* p, * q;
q = L; //q始终指向尾结点,开始时指向头结点
for (i = 1; i <= n; i++) //循环建立数据结点
{
p = malloc(sizeof(Lnode)); //创建数据结点p
printf("第 %d 个结点的数值:", i);
scanf_s("%d", &p->data); //给p的data赋值
q->next = p; //将p插入q之后
q = p;
}
q->next = NULL; //尾结点next为NULL
}
void OutPut(LinkList L) //遍历链表函数
{
Lnode* p;
p = L->next;//p变量为第一个结点
printf("链表的元素有:");
while (p) //判断链表数据是否为空
{
printf("%d ", p->data);//打印当前结点的data
p = p->next;//将结点移动至下一结点
}
printf("\n");
return;
}
Type ListLength(LinkList L) //求链表的长度
{
int n = 0; //n为计数累加器,初始值为0
Lnode* p;
p = L; //p指向头结点
while (p->next != NULL)
{
n++; //条件成立即执行累加器累加
p = p->next; //条件成立即指向下一个结点
}
return(n); //循环结束,p指向尾结点,结点个数为n个
}
void GetElem(LinkList L, int i, Type* e) //取第i个数据元素
{
int n = 0;//n为计数累加器,初始值为0
Lnode* p;
p = L; //p指向头结点
while (n < i && p->next != NULL)
{
n++; //条件成立即执行累加器累加
p = p->next; //条件成立即指向下一个结点
}
*e = p->data; //存在第i个数据元素 将第i个数据元素赋值给e
}
void ListInsert(LinkList L, int i, Type e)//插入
{
int n = 0;//n为计数器,初始值为0
Lnode* p, * q;
p = malloc(sizeof(Lnode)); //创建数据结点p
q = malloc(sizeof(Lnode)); //创建数据结点q
p = L;
while (n < i - 1 && p->next != NULL) //循环条件:计数器的值累加到插入的位置-1(即到达插入的位置)并且当前结点的指针域不等于空(等于空为要插入位置错误 超过或小于结点个数)
{
n++; //条件成立即执行累加器累加
p = p->next; //条件成立即指向下一个结点
}
q->data = e; //要插入的值e赋值给要插入的数据结点q
q->next = p->next;//要插入的结点q指向当前插入位置后一个结点
p->next = q;//插入的结点的指针域指向原位的结点
}
void ListDelete(LinkList L, int i, Type* e)//删除
{
int n = 0;//n为计数器,初始值为0
Lnode* p, * q;
p = malloc(sizeof(Lnode)); //创建数据结点p
q = malloc(sizeof(Lnode)); //创建数据结点q
p = L;
while (n < i - 1 && p->next != NULL) //循环条件:计数器的值累加到删除的位置-1(即到达删除的位置)并且当前结点的指针域不等于空(等于空为要删除位置错误 超过或小于结点个数)
{
n++; //条件成立即执行累加器累加
p = p->next; //条件成立即指向下一个结点
}
q = p->next; //临时结点q为要删除的接点
p->next = q->next; //将要删除结点的指针域给i-1个位置的结点 p指向q的下一个结点
*e = q->data; //将要清空的结点的数据域 赋值给e用于返回
free(q); //清空结点
}
void ClearList(LinkList L) //清空算法
{
Lnode* p;
while (L->next) //判断线性表是否为空
{ //将p设为下一结点 用于清空下一结点(因为头结点为空) L每次都指向p后一个结点
p = L->next; //p为下一个结点
L->next = p->next; //L指向p的下一个结点
free(p); //清空p结点
}
}
void MergerList(LinkList LA, LinkList LB, LinkList LC)//合并算法 LC=LA∪LB
{
Lnode* p1, * p2, * p3;
p1 = LA->next; //p1为LA的第一个结点
p2 = LB->next; //p2为LB的第一个结点
p3 = LC; //p3为LC的头结点
while (p1!=NULL && p2!=NULL) //LA LB其中一个结点全部赋值后 结束循环
{
if (p1->data < p2->data) //按大小排序,用if判断哪个的数据域值小
{
//如果p1(LA)的数据域比p2(LA)的小
p3->next = p1; //p3(LC)指向p1(LA) 作为p3(LC)的当前结点
p3 = p1; //p3(LC)由当前的结点赋值
p1 = p1->next;//移动变为下一结点
}
else
{
//如果p1(LA)的数据域比p2(LA)的大
p3->next = p2;//p3(LC)指向p2(LB) 作为p3(LC)的当前结点
p3 = p1; //p3(LC)由当前的结点赋值
p2 = p2->next;//移动变为下一结点
}
}
if (p1) //判断p1(LA)是否为空 将剩下长的线性表剩余结点 赋值给p3(LC)
{
//p1(LA)还有剩余结点
p3->next = p1; //p3(LC)由当前的结点赋值
p1 = p1->next; //移动变为下一结点
}
else
{
//p2(LB)还有剩余结点
p3->next = p2; //p3(LC)由当前的结点赋值
p2 = p2->next; //移动变为下一结点
}
}
数据结构——链表的基本操作(C语言实现)
最新推荐文章于 2023-10-22 20:24:23 发布