数据结构——实验01-线性表的链式存储和操作

news2024/12/24 2:28:50

一、实验内容

二、算法思想与算法实现

1、解题思想

(1)逆序创建链表La就是使用头插法创建一个链表,所谓头插法就是在创建链表时始终将新元素插入到头结点之后,而正序创建链表Lb就是使用尾插法创建一个链表,所谓尾插法创建一个链表就是在创建链表时始终将新元素插入到表尾

(2)合并两个升序序列,这个算法很基础,这里不做叙述,需要注意的是由于在创建La时我们是逆序创建的,也就是说此时La是降序排列,所以在做两个链表的合并操作之前我们需要先将链表La逆置

(3)删除Lc中的多余元素:这里我们可以用一个指针p表示当前链表的结点,然后用一个指针t指向第一个结点元素值不等于当前结点元素值的结点,然后让结点p的next指针域指向t即可,如下图所示

(4)逆置一个链表,可以借助头插法创建链表的思想,即扫描当前需要逆置的链表不断将当前结点插入到表头

2、算法实现

(1)定义链表结点

//定义链表节点
typedef struct LNode {
	int data;                          //数据域
	struct LNode* next;                //指针域
}LNode,*LinkList;

(2)头插法创建链表

//使用头插法创建一个带头结点的链表,当用户输入666时表示链表创建结束
bool List_HeadInsert(LinkList& L) {

	//对链表进行初始化操作
	L = (LNode*)malloc(sizeof(LNode) * 1);
	if (L == NULL)
	{
		return false;
	}
	L->next = NULL;

	LNode* p = NULL;
	int inputs = 0;
	
	printf("请输入链表元素:\n");
	while (1)
	{
		scanf("%d", &inputs);
		if (inputs == 666)
			break;

		p = (LNode*)malloc(sizeof(LNode) * 1);
		if (p == NULL)
		{
			return false;
		}

		p->data = inputs;
		p->next = L->next;
		
		L->next = p;
	}

	return true;
}

 (3)尾插法创建链表


//使用尾插法创建一个带头结点的链表,当用户输入666时表示链表创建结束
bool List_TailInsert(LinkList& L)
{
	//对链表进行初始化操作
	L = (LNode*)malloc(sizeof(LNode) * 1);
	if (L == NULL)
		return false;
	L->next = NULL;

	LNode* p, * t;   //p指针用于建立新结点,t用于指向当前链表的尾结点
	int inputs;
	t = L;

	printf("请输入链表元素:\n");
	while (1)
	{
		scanf("%d", &inputs);
		if (inputs == 666)
			break;

		p = (LNode*)malloc(sizeof(LNode) * 1);
		if (p == NULL)
			return false;

		p->data = inputs;
		p->next = NULL;

		t->next = p;
		t = p;
	}

	return true;
}

(4)合并两个升序链表

//合并两个有序链表
bool Merge_SortedLinkList(LinkList La, LinkList Lb, LinkList& Lc)
{
	LNode* a, * b, * c, * t;
	a = La->next;
	b = Lb->next;

	//初始化链表Lc;
	Lc = (LNode*)malloc(sizeof(LNode) * 1);
	if (Lc == NULL)
		return false;
	Lc->next = NULL;
	t = Lc;          //t指针指向Lc的尾部结点

	while (a != NULL && b != NULL)
	{
		c = (LNode*)malloc(sizeof(LNode) * 1);
		if (c == NULL)
			return false;
		

		if (a->data <= b->data)
		{
			c->data = a->data;
			c->next = NULL;

			t->next = c;
			t = c;

			a = a->next;
		}
		else
		{
			c->data = b->data;
			c->next = NULL;

			t->next = c;
			t = c;

			b = b->next;
		}
	}

	while (a == NULL && b != NULL)
	{
		c = (LNode*)malloc(sizeof(LNode) * 1);
		c->data = b->data;
		c->next = NULL;
		t->next = c;
		t = c;
		b = b->next;
	}

	while (b == NULL && a != NULL)
	{
		c = (LNode*)malloc(sizeof(LNode) * 1);
		c->data = a->data;
		c->next = NULL;
		t->next = c;
		t = c;
		a = a->next;
	}

	return true;
}

(5)删除链表中的重复元素

//删除有序链表中的重复元素
bool DeleteRpeatElem(LinkList& L)
{
	//判断是否是空表
	if (L->next == NULL)
		return false;

	LNode* p, * e = NULL;   //p指针用于记录当前结点,e指针用于表示值等于当前结点的最后一个结点

	p = L->next;

	while (p != NULL)
	{
		e = p->next;
		if (e == NULL)
			break;
		while (p->data == e->data)
		{
			LNode* temp = e;
			e = e->next;
			free(temp);
		}

		p->next = e;
		p = p->next;	
	}
	return true;
}

(6)逆置一个链表

//逆置一个链表,从头开始扫描一个链表,不断将当前结点插入到链表的开始位置
bool ReverseLinkList(LinkList& L)
{
	if (L->next == NULL)
		return false;
	LNode* end = L->next;  //指向逆置以后的表尾元素
	LNode* p = end->next;  //指向当前元素

	while (p != NULL)
	{
		LNode* temp = p->next;

		p->next = L->next;
		L->next = p;

		p = temp;
	}
	
	end->next = NULL;

	return true;
}

三、代码测试

完整测试代码:

//用C语言编写程序,其中Lb={2,4,6,8,10} La={1,2,3,4,5,6,8},
//(1)逆序创建链表La, 正序创建链表Lb; .
//(2)将La与Lb有序合并,得到有序链表Lc:Lc = { 1,2,2,3,4,4,5,6,6,8,8,10 }
//(3)删除Lc中多余的重复元素,使得所有元素只保留一个;
//(4)将链表Lc倒置,并输出其内容。

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
using namespace std;


//定义链表节点
typedef struct LNode {
	int data;                          //数据域
	struct LNode* next;                //指针域
}LNode,*LinkList;

//使用头插法创建一个带头结点的链表,当用户输入666时表示链表创建结束
bool List_HeadInsert(LinkList& L) {

	//对链表进行初始化操作
	L = (LNode*)malloc(sizeof(LNode) * 1);
	if (L == NULL)
	{
		return false;
	}
	L->next = NULL;

	LNode* p = NULL;
	int inputs = 0;
	
	printf("请输入链表元素:\n");
	while (1)
	{
		scanf("%d", &inputs);
		if (inputs == 666)
			break;

		p = (LNode*)malloc(sizeof(LNode) * 1);
		if (p == NULL)
		{
			return false;
		}

		p->data = inputs;
		p->next = L->next;
		
		L->next = p;
	}

	return true;
}


//使用尾插法创建一个带头结点的链表,当用户输入666时表示链表创建结束
bool List_TailInsert(LinkList& L)
{
	//对链表进行初始化操作
	L = (LNode*)malloc(sizeof(LNode) * 1);
	if (L == NULL)
		return false;
	L->next = NULL;

	LNode* p, * t;   //p指针用于建立新结点,t用于指向当前链表的尾结点
	int inputs;
	t = L;

	printf("请输入链表元素:\n");
	while (1)
	{
		scanf("%d", &inputs);
		if (inputs == 666)
			break;

		p = (LNode*)malloc(sizeof(LNode) * 1);
		if (p == NULL)
			return false;

		p->data = inputs;
		p->next = NULL;

		t->next = p;
		t = p;
	}

	return true;
}


//合并两个有序链表
bool Merge_SortedLinkList(LinkList La, LinkList Lb, LinkList& Lc)
{
	LNode* a, * b, * c, * t;
	a = La->next;
	b = Lb->next;

	//初始化链表Lc;
	Lc = (LNode*)malloc(sizeof(LNode) * 1);
	if (Lc == NULL)
		return false;
	Lc->next = NULL;
	t = Lc;          //t指针指向Lc的尾部结点

	while (a != NULL && b != NULL)
	{
		c = (LNode*)malloc(sizeof(LNode) * 1);
		if (c == NULL)
			return false;
		

		if (a->data <= b->data)
		{
			c->data = a->data;
			c->next = NULL;

			t->next = c;
			t = c;

			a = a->next;
		}
		else
		{
			c->data = b->data;
			c->next = NULL;

			t->next = c;
			t = c;

			b = b->next;
		}
	}

	while (a == NULL && b != NULL)
	{
		c = (LNode*)malloc(sizeof(LNode) * 1);
		c->data = b->data;
		c->next = NULL;
		t->next = c;
		t = c;
		b = b->next;
	}

	while (b == NULL && a != NULL)
	{
		c = (LNode*)malloc(sizeof(LNode) * 1);
		c->data = a->data;
		c->next = NULL;
		t->next = c;
		t = c;
		a = a->next;
	}

	return true;
}

//删除有序链表中的重复元素
bool DeleteRpeatElem(LinkList& L)
{
	//判断是否是空表
	if (L->next == NULL)
		return false;

	LNode* p, * e = NULL;   //p指针用于记录当前结点,e指针用于表示值等于当前结点的最后一个结点

	p = L->next;

	while (p != NULL)
	{
		e = p->next;
		if (e == NULL)
			break;
		while (p->data == e->data)
		{
			LNode* temp = e;
			e = e->next;
			free(temp);
		}

		p->next = e;
		p = p->next;	
	}
	return true;
}

//逆置一个链表,从头开始扫描一个链表,不断将当前结点插入到链表的开始位置
bool ReverseLinkList(LinkList& L)
{
	if (L->next == NULL)
		return false;
	LNode* end = L->next;  //指向逆置以后的表尾元素
	LNode* p = end->next;  //指向当前元素

	while (p != NULL)
	{
		LNode* temp = p->next;

		p->next = L->next;
		L->next = p;

		p = temp;
	}
	
	end->next = NULL;

	return true;
}

//顺序打印一个链表中的所有元素
bool PrintLinkList(LinkList L)
{
	if (L->next == NULL)
		return false;
	LNode* p = L->next;
	while (p != NULL)
	{
		printf("%d\t", p->data);
		p = p->next;
	}
	printf("\n");
	
	return true;
}


//测试程序
int main()
{
	LinkList La, Lb, Lc;

	//逆序创建链表La,即使用头插法创建链表La
	List_HeadInsert(La);
	printf("链表La:\n");
	PrintLinkList(La);

	//正序创建链表Lb,即使用尾插法创建链表Lb
	List_TailInsert(Lb);
	printf("链表Lb:\n");
	PrintLinkList(Lb);


	//合并La和Lb
	
	//先逆序La
	ReverseLinkList(La);
	printf("逆序后的链表La:\n");
	PrintLinkList(La);

	//调用函数合并La和Lb
	Merge_SortedLinkList(La, Lb, Lc);
	printf("合并链表La和链表Lb得到的链表Lc:\n");
	PrintLinkList(Lc);

	//删除Lc中的重复元素
	DeleteRpeatElem(Lc);
	printf("删除链表Lc中的重复元素的结果:\n");
	PrintLinkList(Lc);

	//将Lc逆序
	ReverseLinkList(Lc);
	printf("将链表Lc逆序之后的结果:\n");
	PrintLinkList(Lc);

    return 0;

}

测试结果截图:

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

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

相关文章

Spring Bean 生命周期常见错误

虽然说 Spring 容器上手简单&#xff0c;可以仅仅通过学习一些有限的注解&#xff0c;即可达到快速使用的目的。但在工程实践中&#xff0c;我们依然会从中发现一些常见的错误。尤其当你对 Spring 的生命周期还没有深入了解时&#xff0c;类初始化及销毁过程中潜在的约定就不会…

AJAX-URL查询参数

定义&#xff1a;浏览器提供给服务器的额外信息&#xff0c;让服务器返回浏览器想要的数据 http://xxxx.com/xxx/xxx?参数名1值1&参数名2值2 axios语法 使用axios提供的params选项 注意&#xff1a;axios在运行时把参数名和值&#xff0c;会拼接到url?参数名值 axios(…

第5课 使用FFmpeg将rtmp流再转推到rtmp服务器

本课对应源文件下载链接&#xff1a; https://download.csdn.net/download/XiBuQiuChong/88801992 通过前面的学习&#xff0c;我们已经可以正常播放网络rtmp流及本地mp4文件。这节课&#xff0c;我们将在前面的基础上实现一个常用的转推功能&#xff1a;读取rtmp流或mp4文件并…

matlab|【EI复现】日前日内多阶段多时间尺度源荷储协调调度

目录 一、模型 二、程序运行 三、下载链接 多阶段多时间尺度的协调调度的优势是考虑新能源出力的波动性与随机性&#xff0c;减少需求响应负荷的不确定性对电网制定的日前调度计划准确性造成的影响&#xff0c;也就是能够更加精准的进行调度和分析&#xff0c;优化结果的可用…

(java版)排序算法----【冒泡,选择,插入,希尔,快速排序,归并排序,基数排序】超详细~~

目录 冒泡排序(BubbleSort)&#xff1a; 代码详解&#xff1a; 冒泡排序的优化&#xff1a; 选择排序(SelectSort)&#xff1a; 代码详解&#xff1a; 插入排序&#xff08;InsertSort&#xff09;&#xff1a; 代码详解&#xff1a; 希尔排序(ShellSort)&#xff1a; 法一…

【数据结构与算法】之排序系列-20240202

这里写目录标题 一、389. 找不同二、414. 第三大的数三、455. 分发饼干四、506. 相对名次五、561. 数组拆分六、594. 最长和谐子序列 一、389. 找不同 简单 给定两个字符串 s 和 t &#xff0c;它们只包含小写字母。 字符串 t 由字符串 s 随机重排&#xff0c;然后在随机位置添…

双非本科准备秋招(14.3)—— java线程

创建和运行线程 1、使用Thread Slf4j(topic "c.Test1")public class Test1 {public static void main(String[] args) {Thread t new Thread("t1") {Overridepublic void run() {log.debug("running");}};t.start();​log.debug("runnin…

VUE项目导出excel

导出excel主要可分为以下两种&#xff1a; 1. 后端主导实现 流程&#xff1a;前端调用到导出excel接口 -> 后端返回excel文件流 -> 浏览器会识别并自动下载 场景&#xff1a;大部分场景都有后端来做 2. 前端主导实现 流程&#xff1a;前端获取要导出的数据 -> 把常规数…

Apache Paimon 文件布局设计

Apache Paimon 介绍 Apache Paimon 基础概念 一张表的所有文件都存储在一个基本目录下&#xff0c;Paimon 文件以分层方式组织。从快照文件开始&#xff0c;可以递归地访问表中的所有记录。 image.png Snapshot Files 所有的 snapshot 文件都存储在 snapshot 目录下&#xff0c…

【C语言刷题系列】喝汽水问题

文章目录 一、文章简介 1.先买再换 1.1 代码逻辑&#xff1a; 1.2 完整代码 1.3 运行结果 1.4 根据方法一总结优化 2.边买边换 2.1 代码逻辑&#xff1a; 2.2 完整代码 2.3 运行结果 一、文章简介 本文所述专栏——C语言经典编程问题 C语言刷题_倔强的石头106的博客…

【AI绘画UI+Windows部署】Fooocus:Controlnet原作者结合了sd的开源和Midjourney重新设计的UI

代码&#xff1a;https://github.com/lllyasviel/Fooocus windows一键启动包下载&#xff1a;https://github.com/lllyasviel/Fooocus/releases/download/release/Fooocus_win64_2-1-831.7z B站视频教程&#xff1a;AI绘画入门神器&#xff1a;Fooocus | 简化SD流程&#xff0c…

创建型模式-单例模式:定义、实现及应用

目录 一、模式定义二、针对问题1.解决的问题2.解决方案3.举个例子4.设计模式适合场景5.实现方式6.优缺点7.与其他模式的关系 三、代码实现 一、模式定义 单例模式&#xff08;Singleton Pattern&#xff09;是一种创建型模式&#xff0c;用于限制某个类只能创建一个对象。它提…

【代码随想录】LC 455. 分发饼干

文章目录 前言一、题目1、原题链接2、题目描述 二、解题报告1、思路分析2、时间复杂度3、代码详解 前言 本专栏文章为《代码随想录》书籍的刷题题解以及读书笔记&#xff0c;如有侵权&#xff0c;立即删除。 一、题目 1、原题链接 455. 分发饼干 2、题目描述 二、解题报告 1、…

367. Valid Perfect Square(有效的完全平方数)

题目描述 给你一个正整数 num 。如果 num 是一个完全平方数&#xff0c;则返回 true &#xff0c;否则返回 false 。 完全平方数 是一个可以写成某个整数的平方的整数。换句话说&#xff0c;它可以写成某个整数和自身的乘积。 不能使用任何内置的库函数&#xff0c;如 sqrt(…

随着网络的快速发展,网络安全问题也日益凸显,遇到攻击该如何处理,如何抉择合适的防护方案

DexunCloud 经过研究发现当今世界&#xff0c;随着网络的快速发展&#xff0c;网络安全问题也日益凸显。其中&#xff0c;DDoS&#xff08;分布式拒绝服务&#xff09;攻击被认为是网络安全领域里最为严重的威胁之一。毫无疑问&#xff0c;DDoS攻击不仅可以导致网络服务中断&am…

【笔记】React Native实战练习(仿网易云游戏网页移动端)

/** * 如果系统看一遍RN相关官方文档&#xff0c;可能很快就忘记了。一味看文档也很枯燥无味&#xff0c; * 于是大概看了关键文档后&#xff0c;想着直接开发一个Demo出来&#xff0c;边学边写&#xff0c;对往后工作 * 开发衔接上能够更顺。这期间肯定会遇到各种各样的问题&a…

【数据结构】链表OJ面试题(题库+解析)

前言 还不清楚链表的码喵们可以看看前篇关于链表的详解 http://t.csdnimg.cn/X6t6P 1.链表面试题 既然已经懂得了链表该如何实现&#xff0c;那么现在就趁热打铁开始练习&#xff01;这里给码喵们整理了相对不错的一些OJ题来练习 1. 删除链表中等于给定值 val 的所有结点。 力…

RK3568平台 安卓hal3适配usb camera

一.RK安卓hal3 camera框架 Camera hal3 在 android 框架中所处的位置如上图&#xff0c; 对上&#xff0c;主要实现 Framework 一整套 API 接口&#xff0c;响应其 控制命令&#xff0c;返回数据与控制参数结果。 对下&#xff0c; 主要是通 V4l2 框架实现与 kernel 的交互。3a…

AI应用开发-git开源项目的一些问题及镜像解决办法

AI应用开发相关目录 本专栏包括AI应用开发相关内容分享&#xff0c;包括不限于AI算法部署实施细节、AI应用后端分析服务相关概念及开发技巧、AI应用后端应用服务相关概念及开发技巧、AI应用前端实现路径及开发技巧 适用于具备一定算法及Python使用基础的人群 AI应用开发流程概…

Redis核心技术与实战【学习笔记】 - 18.Redis 缓存被污染了,如何选择淘汰策略

前言 在一些常见下&#xff0c;有些数据被访问的次数非常少&#xff0c;甚至只会被访问一次。当这些数据请求后&#xff0c;还继续留存在缓存中的话&#xff0c;只会白白占用缓存的空间。这种情况就是缓存污染。 当缓存污染不严重时&#xff0c;只有少量数据占据缓存空间&…