线性表操作的实现--单链表(链式存储结构)

news2024/9/24 23:30:16

本文参考朱战力老师的数据结构与算法--使用C语言一书

目录

文章目录

前言

一、链表是什么?

二、具体实现

1.单链表的定义

2.初始化ListInitiate(SLNode **head)

3.求当前元素的个数ListLength(SLNode *head)

4.插入ListInsert(SLNode *head,int i,DataType x)

5.删除ListDelete(SLNode *head,int i,DataType *x)

6.取元素ListGet(SLNode *head,int i,DataType *x)

 7.撤销单链表Destroy(SLNode **head)

  8.链表排序ListSort(SLNode* head)

  9.链表查找ListSearch(SLNode* head, DataType target)

  10.小试牛刀

总结


前言

        本文所介绍的内容为数据结构与算法的基础内容--顺序表操作的实现,笔者通过不断的深入学习发现,后续的数据结构中,包括堆栈、队列、串、数组、表、数和二叉树无不是通过线性表去实现,故很好的理解线性表的操作对于广大的读者来说非常的有必要!


一、链表是什么?

        本篇文章讨论线性表的链式存储结构和链式存储结构下操作的实现。链式存储结构存储线性表元素的方法是,把存储有元素的结点用指针域构造成链。指针是指向物理内存单元地址的变量。我们把一个由元素域及一个或若干个指针域组成的结构体称为一个结点。其中,数据域用来存放元素,指针域用来构造元素之间的关联关系。链式存储结构的特点是,元素间的逻辑关系表现在结点的链接关系上。链式存储结构的线性表称为链表。根据指针域的不同和结点构造链的方法不同,链表主要有单链表、循环单链表和双向循环链表三种。其中单链表是最经常使用的链表。

二、具体实现

1.单链表的定义

代码如下(示例):

typedef struct Node {
    DataType data;
    struct Node* next;
}SLNode;

2.初始化ListInitiate(SLNode **head)

代码如下(示例):

void ListInitiate(SLNode** head) {	//初始化
	*head = (SLNode*)malloc(sizeof(SLNode));	//申请头结点,由head指示其地址
	(*head)->next = NULL;	//置结束标志NULL
}

说明:在初始化操作前,头指针参数head没有具体的地址值。在初始化操作时,头指针参数head才得到了具体的地址值,而这个地址值要返回给调用函数,所以,此时头指针参数head要设计成双重指针(指针的指针)类型。如果此时头指针参数head设计成指针类型,那么调用函数将无法得到在初始化函数中被赋值的头指针参数head的值。

3.求当前元素的个数ListLength(SLNode *head)

代码如下(示例):

int ListLength(SLNode* head) {
	SLNode* p = head;	//p指向头结点
	int size = 0;	//size初始为0

	while (p->next != NULL) {	//循环计数
		p = p->next;
		size++;
	}
	return size;
}

算法实现过程:

4.插入ListInsert(SLNode *head,int i,DataType x)

代码如下(示例):

int ListInsert(SLNode* head, int i, DataType x) {
	//在带头结点的单链表head的第i给结点前插入一个存放元素x的结点
	//插入成功则返回1,失败则返回0
	SLNode* p, * q;
	int j;
	p = head;
	j = -1;
	while (p->next != NULL && j < i - 1) {
		//最终让指针p指向第i-1个结点
		p = p->next;
		j++;
	}

	if (j != i - 1) {
		printf("插入元素位置参数错!");
		return 0;
	}

	q = (SLNode*)malloc(sizeof(SLNode));	//生成新结点
	q->data = x;							//新结点数据域赋值

	q->next = p->next;						//插入步骤1
	p->next = q;							//插入步骤2
	return 1;
}

算法实现过程:

5.删除ListDelete(SLNode *head,int i,DataType *x)

代码如下(示例):

int ListDelete(SLNode* head, int i, DataType* x) {
	//删除带头结点单链表head的第i(0~size-1)个结点
	//被删除结点的数据域值由x带回,删除成功则返回1,失败则返回0
	SLNode* p, * s;
	int j;
	p = head;
	j = -1;

	while (p->next != NULL && p->next->next != NULL && j < i - 1) {
		//循环结束时指针p指向第i-1个结点
		p = p->next;
		j++;
	}

	if (j != i - 1) {
		printf("删除元素位置参数错!");
		return 0;
	}

	s = p->next;		//指针s指向第i个结点
	*x = s->data;		//把指针s所指结点的数据域值赋予x
	p->next = p->next->next;		//删除
	free(s);			//释放指针s所指结点的内存空间
	return 1;
}

算法实现过程:

6.取元素ListGet(SLNode *head,int i,DataType *x)

代码如下(示例):

int ListGet(SLNode* head, int i, DataType* x) {
	SLNode* p;
	int j;

	p = head;
	j = -1;
	while (p->next != NULL && j < i) {
		p = p->next;
		j++;
	}

	if (j != i) {
		printf("取元素位置参数错!");
		return 0;
	}

	*x = p->data;
	return 1;
}

 7.撤销单链表Destroy(SLNode **head)

代码如下(示例):

void Destroy(SLNode** head) {
	SLNode* p, * p1;

	p = *head;
	while (p != NULL) {
		p1 = p;
		p = p->next;
		free(p1);
	}
	*head = NULL;
}

  8.链表排序ListSort(SLNode* head)

代码如下(示例):

void ListSort(SLNode* head) {
	if (head == NULL || head->next == NULL) {
		return;		//空链表或只有一个结点,无需进行排序
	}

	SLNode* p, * q;
	DataType temp;
	int len = ListLength(head);

	for (int i = 0; i < len - 1; i++)
	{
		p = head->next;
		q = head->next->next;

		for (int j = 0; j < len - 1 - i; j++)
		{
			if (p->data > q->data)
			{
				temp = p->data;
				p->data = q->data;
				q->data = temp;
			}
			p = p->next;
			q = q->next;
		}
	}
}

  9.链表查找ListSearch(SLNode* head, DataType target)

代码如下(示例):

int ListSearch(SLNode* head, DataType target) {
	if (head == NULL)
	{
		return -1;	//空链表,查找失败
	}

	SLNode* p = head->next;
	int index = 0;

	while (p != NULL)
	{
		if (p->data == target)
		{
			return index;	//找到目标值,返回索引
		}
		p = p->next;
		index++;
	}
	return -1;
}

  10.小试牛刀

代码如下(示例):

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>	//包含printf()
#include<malloc.h>	//包含malloc()等函数
typedef int DataType;	//定义DataType为int
#include"LinList.h"	//包含LinList.h头文件
void main() {
	SLNode* head;	//定义头指针变量
	int i, x;

	ListInitiate(&head);	//初始化
	for (i = 0; i < 10; i++)	//插入10个元素
	{
		ListInsert(head, i, i + 1);
	}
	ListDelete(head, 3, &x);	//删除元素4
	for (i = 0; i < ListLength(head); i++) {	//显示当前的元素
		ListGet(head, i, &x);	//取元素
		printf("%d	", x);		//显示
	}

	// 测试排序函数
	printf("\n\n排序后的链表:\n");
	ListSort(head);
	for (i = 0; i < ListLength(head); i++) {	//显示当前的元素
		ListGet(head, i, &x);	//取元素
		printf("%d	", x);		//显示
	}

	// 测试查找函数
	int target = 7;
	int index = ListSearch(head, target);
	if (index != -1) {
		printf("\n\n目标值 %d 在链表中的索引位置为 %d\n", target, index);
	}
	else {
		printf("\n\n目标值 %d 不在链表中\n", target);
	}

	Destroy(&head);				//撤销单链表
}

运行结果:


总结

        

        单链表是一种常见的数据结构,它由节点组成,每个节点包含数据和指向下一个节点的指针。在本文中,我们实现了单链表的一些基本操作,包括插入、删除、排序和查找等。

        通过插入操作,我们可以在链表中添加新的节点。删除操作可以帮助我们删除指定节点。排序操作可以根据特定的规则对链表进行排序,使得节点按照一定的顺序排列。查找操作可以在链表中寻找特定的节点,并返回其位置或者相关信息。

        这些操作的实现需要注意指针的运用,以确保链表的结构正确。在排序和查找过程中,需要考虑不同的算法和复杂度,选择合适的方法来提高效率。

        总的来说,通过实现这些操作,我们可以灵活地对单链表进行操作,实现了对节点的添加、删除、排序和查找等功能。熟练掌握这些操作为我们日后学习哈希表和二叉树,都打下了非常坚实的基础。

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

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

相关文章

学会Docker之——界面化操作(Docker Desktop)

Docker Desktop 是一款用于在桌面环境下开发、构建和容器化应用程序的工具。它适用于 Windows 和 Mac 操作系统&#xff0c;让开发人员可以轻松地在本地环境中创建和运行容器&#xff0c;并与 Docker Hub 和其他容器注册表进行交互。Docker Desktop集成了Docker Engine&#xf…

C语言文件操作(详解)

&#x1f493;博客主页&#xff1a;江池俊的博客⏩收录专栏&#xff1a;C语言进阶之路&#x1f449;专栏推荐&#xff1a;✅C语言初阶之路 ✅数据结构探索✅C语言刷题专栏&#x1f4bb;代码仓库&#xff1a;江池俊的代码仓库&#x1f389;欢迎大家点赞&#x1f44d;评论&#x…

Maven历史版本下载

网址: https://archive.apache.org/dist/maven/maven-3/3.8.6/binaries/

个人博客测试报告

目录 一、项目背景 二、项目功能 三、测试计划 功能测试 1、测试用例 ​编辑 2、 实际执行测试的部分操作步骤/截图 3、发现的bug 自动化测试 博客访问连接 一、项目背景 个人博客系统采用前后端分离的方法来实现&#xff0c;同时使用了数据库来存储相关的数据&#xf…

文心一言简单体验

百度正式发布文心一言&#xff0c;文心一言 这里的插件模式挺有意思&#xff1a; 测试了一下图解说明&#xff0c;随意上传了一张图片&#xff1a; 提供图解让反过来画&#xff0c;抓住了部分重点&#xff0c;但是还是和原图有比较大的差异&#xff01; 百宝箱 暂未逐个体验&am…

台灯应该买什么样的才能护眼?五款专业的护眼台灯推荐

台灯主要还是以护眼台灯为主&#xff0c;因为不仅色谱丰富&#xff0c;贴近自然色的全光谱色彩&#xff0c;通常显色指数都能达到Ra95以上&#xff0c;显色能力特别强&#xff0c;而且还具有其他防辐射危害、提高光线舒适度的特性&#xff0c;比如侧发光技术、漫反射技术等大大…

Windows更新强制关闭

使用管理员身份运行cmd或者使用powershell 执行下述命令 reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings" /v FlightSettingsMaxPauseDays /t reg_dword /d 36525 /f可以看到更新选项中可以截止到2123年,我感觉比我生命的终点要靠后了! …

设树B是一棵采用链式结构存储的二叉树,编写一个把树 B中所有结点的左、右子树进行交换的函数 中国科学院大学2015年数据结构(c语言代码实现)

本题代码如下 void swap(tree* t) {if (*t)// 如果当前节点非空 {treenode* temp (*t)->lchild;// 临时存储左子节点 (*t)->lchild (*t)->rchild;// 将右子节点赋值给左子节点(*t)->rchild temp;// 将临时存储的左子节点赋值给右子节点 swap(&(*t)->l…

c语言进制的转换10进制转换2进制

c语言进制的转换之10进制转换2进制 c语言10进制转换2进制 c语言进制的转换之10进制转换2进制一、10进制转换2进制的方法 一、10进制转换2进制的方法 十进制转二进制&#xff1a; 除二反序取余法&#xff1a;将十进制数每次除以2 取出余数 按照结果倒叙依次获取结果 END

机器学习实验一:KNN算法,手写数字数据集(使用汉明距离)(2)

KNN-手写数字数据集&#xff1a; 使用sklearn中的KNN算法工具包&#xff08; KNeighborsClassifier)替换实现分类器的构建&#xff0c;注意使用的是汉明距离&#xff1b; 运行结果&#xff1a;&#xff08;大概要运行4分钟左右&#xff09; 代码&#xff1a; import pandas as…

JavaWeb——Servlet原理、生命周期、IDEA中实现一个Servlet(全过程)

6、servlet 6.1、什么是servlet 在JavaWeb中&#xff0c;Servlet是基于Java编写的服务器端组件&#xff0c;用于处理客户端&#xff08;通常是Web浏览器&#xff09;发送的HTTP请求并生成相应的HTTP响应。Servlet运行在Web服务器上&#xff0c;与Web容器&#xff08;如Tomcat&…

警惕!又2本期刊被“On Hold”!

【SciencePub学术】 此前&#xff0c;继一本SSCI期刊被取消“On hold”标识后&#xff0c;仍处于“On Hold”状态的期刊有6本&#xff0c;其中包括4本SCI期刊和2本ESCI期刊。近日&#xff0c;经小编查询&#xff0c;又新增2本“On Hold”期刊&#xff0c;详情如下&#xff1a;…

实例演示:拉格朗日乘子法(Lagrange multiplier method)

拉格朗日乘子法&#xff08;Lagrange multiplier method&#xff09;是一种寻找多元函数在一组约束下的极值的方法。通过引入拉格朗日乘子&#xff0c;可将有d个变量与k个约束条件的最优化问题转化为具有dk个变量的无约束优化问题求解。这种方法将一个有n个变量与k个约束条件的…

以数据赋能,星辰天合推进智慧化校园建设

近日&#xff0c;上海市高等教育学会校园网络专业委员会 2023 年度学术年会在上海举办&#xff0c;本次会议以“数智赋能教育 生成美好未来”为主题&#xff0c;围绕 AI 与教育融合、高校数字化转型创新发展等内容进行了专业研讨。 XSKY星辰天合解决方案总监李瑞宇作了《应用融…

ETHERNET/IP从站转CANOPEN主站连接AB系统的配置方法

你还在为配置网关的ETHERNET/IP从站和CANOPEN主站发愁吗&#xff1f;今天来教你解决办法&#xff01; 一&#xff0c;首先&#xff0c;配置网关的ETHERNET/IP从站&#xff0c;需要使用AB系统的配置方法&#xff0c;具体步骤如下 1&#xff0c;使用 AB 系统配置网关的 ETHERNET/…

Leetcode—547.省份数量【中等】

2023每日刷题&#xff08;八&#xff09; Leetcode—547.省份数量 实现代码 static int father[210] {0};int Find(int x) {if(x ! father[x]) {father[x] Find(father[x]);}return father[x]; }void Union(int x, int y) {int a Find(x);int b Find(y);if(a ! b) {fathe…

【java学习—八】单例设计模式(5)

文章目录 1. 相关概念2. 单例设计模式-饿汉式3. 单例设计模式-懒汉式4. 总结 1. 相关概念 单例&#xff1a;只有一个实例&#xff08;实例化对象&#xff09; 设计模式是在大量的实践中总结和理论化之后优选的代码结构、编程风格、以及解决问题的思考方式。设计模式就像是经典的…

MTC怎么办理?什么产品需要做MTC?

什么是MTC认证&#xff1f; 欧盟MTC认证也叫EN 10204认证&#xff0c;也叫承压材质认证。主要是对金属&#xff0c;钢材的一个追溯来源。 对于所有风险等级压力设备的承压部件材料及直接焊接到承压部件上的附件&#xff0c; 压力设备制造商必须通过向材料制造商索要保证其可追溯…

Android 应用流量监控实践

背景 得物Apm系统本身包含网络接口性能监控的能力&#xff0c;但接口监控主要关注的是接口的耗时、异常率等信息&#xff0c;没有流量消耗相关维度的统计信息&#xff0c;并且一部分流量消耗可能来自于音视频等其他特殊场景&#xff0c;在接口监控的盲区外。 为了了解用户目前…