(数据结构)单链表的相关操作

news2024/11/14 11:01:07
//1.预编译部分

#define _CRT_SECURE_NO_WARNINGS

#include<stdio.h>

#include<stdlib.h>

//2.单链表的结构体

typedef struct LNode

{

	int data;

	struct LNode* next;   //因为next指针指向的为结构体类型,所以类型为struct LNode*

}LNode, * LinkList;         //代码没执行到最后一步之前,定义结构体还是要把类型名写全,之后才能简化为LNode

//3.单链表的初始化

void InitLinkList(LinkList L)  //给头结点赋值

{

	L->data = 0;     //头结点的data域用作给链表长度计数

	L->next = NULL;  //头结点的next域用来指向链表的另一个节点

}

//4.单链表的打印

void PrintLinkList(LinkList L)

{

	LNode* p;    //定义一个结构体指针

	p = L;       //将它指向头指针的位置

	while (p->next)     //如果其下一个节点不为NULL

	{

		p = p->next;    //则把这个指针往后一位,从而输出下一节点的值

		printf("%d-->", p->data);

	}

	printf("NULL\n");  //如果其下一个节点为NULL,则输出NULL

}

//5.单链表的头插法

void HeadInsertLinkList(LinkList L)

{

	LNode* NewNode;   //新节点的地址

	int data;    //新节点中data的值

	printf("请输入一个数,输入9999结束循环\n");

	scanf("%d", &data);

	//malloc()函数的作用为动态分配内存,分配内存的大小有内部参数sizeof()计算可得

	//给静态地址赋值时要将其强制类型转换为相应指针类型

	while (data != 9999)

	{

		//进行插入操作

		//每次调用malloc函数,就重新在内存中开辟一块指定大小的内存空间给链表节点

		NewNode = (LNode*)malloc(sizeof(LNode));	//相当于每次创建一个新的链表节点

		NewNode->next = L->next;	//将头指针中的next赋值给新创建的节点的next

		L->next = NewNode;	  //将新建节点的地址赋值给头结点的next

		NewNode->data = data;   //将要输入的数赋值给新创建节点的data

		L->data++;		//头节点中的data+1,用来计数链表长度

		//printf("请输入一个数,输入9999结束循环\n");

		scanf("%d", &data);

	}

}

//6.单链表的尾插法创建链表

void  TailInsertLinkList(LinkList L)

{

	LNode* NewNode; //新节点的地址

	LNode* TailNode = L;   //为了不改变头节点的位置,故定义一个尾节点来进行相关操作

	int data;  //新节点中data的值

	while (TailNode->next != NULL)   //当指向节点的下一个节点不为空时,尾节点一直向后走

	{

		TailNode = TailNode->next;

	}

	printf("请输入一个数,输入9999结束循环\n");

	scanf("%d", &data);

	while (data != 9999)

	{

		//进行插入操作

		//每次调用malloc函数,就重新在内存中开辟一块指定大小的内存空间给链表节点

		NewNode = (LNode*)malloc(sizeof(LNode));  //相当于每次创建一个新的链表节点

		NewNode->data = data;   //将数值插入新建节点的data

		TailNode->next = NewNode;  //将新建的节点连接在尾指节点之后

		NewNode->next = NULL;   //将新建节点的next赋值为空

		TailNode = NewNode;  //将尾节点向后一个节点

		L->data++;		//头节点中的data+1,用来计数链表长度

		//printf("请输入一个数,输入9999结束循环\n");

		scanf("%d", &data);      //若输出9999跳出循环结束链表的创建

	}

}

//7.按位查找数据元素

LNode* GetElem(LinkList L, int i)

{

	//(1)判断i的合法性

	if (i == 0)  //链表为空

	{

		printf("你寻找的元素不存在,将返回头结点\n");

	}

	if (i<1 || i>L->data)  //当i的位置小于1或大于表长,数据非法

	{

		printf("你寻找的元素不存在,将返回NULL\n");

	}

	//2.查找数据元素

	LNode* p = L;   //为了不改变头节点的位置,故定义一个查询节点来进行相关操作

	for (int j = 1; j <= i; j++)  //移动次数相应位数的次数

	{

		p = p->next;    //查询节点后移,第一位是头结点

	}

	return p;  //找到目标节点后返回这个节点

}

//8.按值查找数据元素

int* LocatElem(LinkList L, int e, int* count)

{

	if (!L->next)  //链表为空则返回头结点

	{

		printf("这个链表为空\n");

		return 0;

	}

	LNode* p = L;   //为了不改变头节点的位置,故定义一个查询节点来进行相关操作

	while (p->next)  //如果查询节点的下一个节点不为空

	{

		(*count)++;  //计数器+1

		p = p->next;  //第一个节点为头结点,需要往后一个节点再判断

		if (p->data == e)

		{

			return count;

		}

	}

	printf("你寻找的元素不存在\n");

	return 0;

}

//9.单链表的按位插入

void LocalInsertLinkList(LinkList L, int i, int e)

{

	//(1)判断i的合法性

	if (i<1 || i>(L->data + 1))

	{

		printf("要插入的元素的位置无效\n");

	}

	//插入新元素

	LNode* p = GetElem(L, i - 1);

	LNode* NewNode = (LNode*)malloc(sizeof(LNode));

	NewNode->data = e;

	NewNode->next = p->next;

	p->next = NewNode;

	L->data++;

}

//10.单链表的按位删除

void LocalDeletElem(LinkList L, int i, int* e)

{	

	//(1)检查i的合法性

	if (!L->next)

	{

		printf("这个链表为空\n");

		*e = 9999;

		goto x;

	}

	if (i<1 || i>(L->data))

	{

		printf("要删除的元素不存在\n");

		*e = 9999;

		goto x;

	}

	//(2)删除指定元素

	LNode* p = GetElem(L, i - 1);

	LNode* q = p->next;

	p->next = q->next;

	*e = q->data;

	free(q);

	L->data--;

	x:;

}

//11.销毁单链表

void DestoryLinkList(LinkList L)

{

	int o;

	while (L->data)

	{

		LocalDeletElem(L, 1, &o);

		PrintLinkList(L);

	}

	free(L);

}

//12.单链表的合并

LinkList mergeList(LinkList L1, LinkList L2)

{

	LinkList L3 = (LNode*)malloc(sizeof(LNode));

	LNode* P1 = L1->next;

	LNode* P2 = L2->next;

	LNode* P3 = L3;  //防止改变头结点的位置,新建一个节点和头结点指向同一位置,代替指针完成链表的链接

	while (P1 != NULL && P2 != NULL)

	{

		if (P1->data <= P2->data)

		{

			P3->next = P1;

			P1 = P1->next;

		}

		else

		{

			P3->next = P2;

			P2 = P2->next;

		}

		P3 = P3->next;

	}

	P3->next = P1 == NULL ? P2 : P1;

	return L3;

}

//合并两个单链表(相同元素保留一个)

LinkList Merge_List(LinkList La, LinkList Lb)/*合并以La,Lb为头结点的两个有序链表*/

{

	LNode* Lc, * pa, * pb, * ptr;

	LNode* pc = (LNode*)malloc(sizeof(LNode));

	Lc = La;

	pc = La;

	pa = La->next;

	pb = Lb->next;

	while (pa != NULL && pb != NULL)

	{

		if (pa->data < pb->data)

		{

			pc->next = pa;

			pc = pa;

			pa = pa->next;

		}

		if (pa->data > pb->data)

		{

			pc->next = pb;

			pc = pb;

			pb = pb->next;

		}

		if (pa->data == pb->data)

		{

			pc->next = pa;

			pc = pa;

			pa = pa->next;

			ptr = pb;

			pb = pb->next;

			free(ptr);

		}

	}

	if (pa != NULL)

		pc->next = pb;

	else

		pc->next = pb;

	free(Lb);

	return(Lc);

}

//单链表的逆置

LinkList converse(LinkList head)

{

	LinkList p,  q;

	p = head->next;

	head->next = NULL;

	while (p)

	{

		/*向后挪动一个位置*/

		q = p;

		p = p->next;



		/*头插*/

		q->next = head->next;

		head->next = q;

	}

}

int main()

{

	LinkList L1;   //L是一个结构体指针——为头指针

	L1 = (LNode*)malloc(sizeof(LNode));  //申请内存只能在主函数中完成,放在(除结构体指针类型)的自定义函数中时会随着函数的调用结束内存释放而失效

	//给头结点赋值

	//InitLinkList(L1);

	//头插法创建链表

	//HeadInsertLinkList(L1);

	打印链表

	//PrintLinkList(L1);

//_______________________________________________________________________

	//给头结点赋值

	InitLinkList(L1);

	//尾插法创建链表

	TailInsertLinkList(L1);

	//打印链表

	PrintLinkList(L1);

	LinkList L2;

	L2 = (LNode*)malloc(sizeof(LNode));

	//给头结点赋值

	InitLinkList(L2);

	//尾插法创建链表

	TailInsertLinkList(L2);

	//打印链表

	PrintLinkList(L2);

	//_______________________________________________________________________

		//按位查找数据元素

	int i;

	printf("请输入需要查找的位数\n");

	scanf("%d", &i);

	printf("链表L1第%d位的data=%d\n", i, GetElem(L1, i)->data);

	//_______________________________________________________________________

		//按值查找数据元素

	int e;

	int count = 0;

	printf("请输入需要查找的数据\n");

	scanf("%d", &e);

	printf("%d在链表L1的第%d位\n", e, *(LocatElem(L1, e, &count)));

	//_______________________________________________________________________

		//单链表的按位插入

	int n = 0;

	int m = 0;

	printf("请输入要插入的位置\n");

	scanf("%d", &n);

	printf("请输入要插入的值\n");

	scanf("%d", &m);

	LocalInsertLinkList(L1, n, m);

	PrintLinkList(L1);

	//_______________________________________________________________________

		//单链表的按位删除

	int d;

	int q;

	printf("请输入需要删除的位数\n");

	scanf("%d", &q);

	LocalDeletElem(L1, q, &d);

	PrintLinkList(L1);

	//_______________________________________________________________________

		//销毁单链表

		/*DestoryLinkList(L1);*/

	//—————————————————————————————————————

		//合并单链表

		printf("合并后的单链表:\n");

		LinkList h;

		h = Merge_List(L1, L2);

		PrintLinkList(h);

		//单链表的逆置

	//打印链表

	printf("逆置后的链表\n");

	PrintLinkList(converse(h));

	return 0;

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1114204.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何保障Facebook账号登录稳定?跨境人必看

作为全球最大的社交媒体平台&#xff0c;Facebook已成为众多跨境人们拓展海外市场的重要渠道。然而&#xff0c;Facebook对跨境业务卖家的监管越来越严格&#xff0c;封号政策也日趋严厉。对于想要在Facebook上开展业务的跨境人们而言&#xff0c;大家是否被Facebook封号问题困…

如何对需求变更进行精准的风险评估?

1、明确需求变更背景和目的 首先需要了解需求变更的背景&#xff0c;即需求产生的原因和环境&#xff0c;如需求变更是由业务变化、用户需求变化、技术限制、资源限制等因素引起的。其次需要明确需求变更目的是为了解决问题还是满足需求。 明确需求变更背景和目的&#xff0c;有…

X32位汇编和X64位区别无参函数分析(一)

前言 一、X32汇编函数无参无返回分析 二、X64汇编函数无参无返回分析 总结 前言 提示&#xff1a;以下是个人学习总结&#xff1a;如有错误请大神指出来&#xff0c;只供学习参考&#xff0c;本内容使用使用VS2017开发工具&#xff1a;语言是C&#xff0c;需要一些常见的汇编指…

数据库管理-第112期 Oracle Exadata 03-网络与ILOM(20231020)

数据库管理-第112期 Oracle Exadata 03-网络与ILOM&#xff08;202301020&#xff09; 在Exadata中&#xff0c;除了对外网络以外&#xff0c;其余网络都是服务于一体机内部各组件的网络&#xff0c;本期对这些网络的具体情况和硬件管理相关做一个讲解。 1 网络分类 1.1 生产…

工业交换机选购标准,你知道多少?

工业交换机是专门针对灵活多变的工业应用需求而设计的&#xff0c;旨在为工业以太网通讯提供高性价比的解决方案。当我们选购工业交换机时&#xff0c;有哪些选购标准呢&#xff1f; 一、工业交换机选购标准&#xff1a; 1、考虑到工作环境的因素 这些内容包括温度范围、电磁…

前端 js 之 浏览器工作原理 和 v8引擎 01

嘿&#xff0c;老哥&#xff0c;来了就别跑 &#xff01;学完 &#xff0c;不亏 &#x1f602; 文章目录 一、输入url 之后做了什么二、简单了解下浏览器内核三、浏览器渲染过程 &#xff08;渲染引擎&#xff09;四、js 引擎五、chrome五、v8 引擎原理八、浏览器性能优化九、前…

学会C++之后,为什么学任何语言都会更加容易?

学会C之后&#xff0c;为什么学任何语言都会更加容易&#xff1f; 编程的本质是把自然语言翻译为机器语言&#xff0c;但机器没有联想力&#xff0c;所以它需要编写者事无巨细地告诉它怎么做。最近很多小伙伴找我&#xff0c;说想要一些c语言资料&#xff0c;然后我根据自己从业…

家电电器小程序商城的作用是什么

随着人们生活提升&#xff0c;各式家电类型非常多&#xff0c;优化了人们生活日常&#xff0c;入局的大中小品牌也非常多&#xff0c;人们可以在商场、商圈或线上电商平台找到自己所需的电器家电产品。 无论大件还是小件&#xff0c;消费者的选择性非常广&#xff0c;对品牌或…

第二证券:跌破3000点,热搜第一!

今天上午&#xff0c;“沪指开盘跌破3000点关口”冲上百度热搜榜榜首。 上午收盘&#xff0c;上证指数下跌0.27%&#xff0c;报2997.22点&#xff1b;深证成指下跌0.36%&#xff0c;创业板指下跌0.44%。 赛道股发力&#xff0c;光伏、风电、新能源轿车等板块盘中冲高。房地产…

【控制系统】PID(学习笔记)

一、PID概要 1、引入 流量稳定、调整流量 2、适用系统 二阶以内的线性系统 线性系统&#xff1a;满足齐次性和叠加性 齐次性&#xff1a; y f ( x ) yf(x) yf(x) 则 k y f ( k x ) kyf(kx) kyf(kx) 叠加性&#xff1a; y 1 f ( x 1 ) , y 2 f ( x 2 ) y_1f(x_1),y_2f(x…

[linux] 把txt文本文件分成10个子文件,并保存。 linux命令

您可以使用split命令将文件分割成多个子文件。以下是使用split命令将"zh_for_translate5k.txt"文件分割成10个子文件的示例命令&#xff1a; split -l $(( $(wc -l < zh_for_translate5k.txt) / 10 )) zh_for_translate5k.txt sub_file_

同城便民信息分类小程序H5开发

一款适合同城使用的便民信息服务发布小程序&#xff0c;程序经过多代版本更新以后&#xff0c;功能更丰富完善&#xff0c;使用体验更好。支持saas和独立部署。 核心能力&#xff1a;商户浏览、同城配置管理、商家管理设置、帖子管理设置、用户设置管理、会员卡管理、商品管理…

2023年全球及中国环球影城主题公园数量、游客人数及收入分析[图]

环球影城主题公园是以电影为核心的主题游乐园&#xff0c;目前全球共5家&#xff0c;分别位于美国洛杉矶、奥兰多&#xff0c;日本大阪&#xff0c;新加坡圣淘沙岛以及中国北京。 2022年全球环球影城主题公园游客总数为5927.5万人次&#xff1b;其中日本环球影城游客数为1235.0…

安全带、登山绳、登山扣标准认证以及模版标签讲解

安全带、登山绳、登山扣标准认证以及模版标签讲解 一、安全带 安全带是指作业人员在户外或高空等场景下配戴的安全保护装备。为分散坠落防护时产生的对于人体大腿上部、骨盆、胸部以及肩部的压力&#xff0c;常见的装备类型为腰带式安全带和背带式安全带两种。坠落防护安全装…

Spring framework :基于 jdk 动态代理实现连接池复用

前言 在数据库开发中&#xff0c;连接池是一种重要的技术手段&#xff0c;它可以提高数据库连接的复用性和性能。连接池的原理是在应用启动时创建一定数量的数据库连接&#xff0c;并将这些连接保存在一个池中&#xff0c;应用程序需要数据库连接时&#xff0c;从连接池中获取…

智能巡检系统有什么特点和功能?它是如何推动企业高效管理?

随着科技的快速发展&#xff0c;智能化管理逐渐成为各行各业的重要发展方向。巡检工作作为企业管理中的重要环节&#xff0c;智能巡检系统综合平台正逐渐成为关注的焦点。本文将从功能、特点和应用场景三个方面&#xff0c;详细解析“的修”工单管理系统的优势和价值。 一、智能…

什么是美颜sdk?直播实时美颜sdk的工作流程和架构分析

在现代社交媒体和娱乐行业中&#xff0c;直播已经成为了一种受欢迎的娱乐形式&#xff0c;同时实时美颜也变得越来越重要。直播实时美颜SDK的工作流程和架构在这一领域起到了关键作用。本文将深入探讨这些SDK的内部机制&#xff0c;从而理解它们如何为用户提供出色的美颜效果。…

推荐一种更高效的打字输入法——双拼输入法

简介 双拼&#xff08;也称双打&#xff09;是一种建立在拼音输入法基础之上的文字输入方法&#xff0c;可视为全拼的一种改进。它通过将每个汉字拼音的声母和韵母各自映射到某个按键上&#xff0c;使得每个汉字最多用两个按键表示&#xff0c;从而极大地提高了拼音输入法的输…

激光雷达反射率标定可提高自动驾驶道路安全

实现自动驾驶从辅助驾驶阶段到部分自动驾驶阶段&#xff0c;再到完全自动驾驶阶段&#xff0c;自动驾驶技术正在逐步实现。虽然完全自动驾驶技术仍需要时间来进一步发展和完善&#xff0c;但其所带来的可能性是无限的。激光雷达在自动驾驶中的应用非常广泛&#xff0c;它能够提…

请问嵌入式或迁移学习要学什么?

请问嵌入式或迁移学习要学什么&#xff1f; 学习嵌入式和迁移学习是一个很好的方向&#xff0c;尤其是在军I领域。以下是一些你可以提前学习的基本 知识和步骤: 嵌入式系统:最近很多小伙伴找我&#xff0c;说想要一些嵌入式资料&#xff0c;然后我根据自己从业十年经验&#…