数据结构——链表的基本操作(C语言实现)

#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; //移动变为下一结点

	}
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值