结构体和数据结构--动态数据结构体-单向链表

news2024/9/24 7:13:45

目录

一、问题的提出

二、链表的定义

三、单向链表的建立

四、单向链表的删除操作

五、单向链表的插入操作


一、问题的提出

        数组实质是一种顺序存储,随机访问的线性表,它的优点是使用直观,便于快速、随机地存取线性表中地任意元素。但缺点是对其进行插入和删除操作时需要移动大量地数组元素,同时由于数组数据静态内存分配,定义数组时必须指定数组地长度,程序一旦运行,其长度就不能在改变,若想改变,只能修改程序,实际使用地数组元素个数不能超过数组元素最大长度地限制,否则就会发生下标越界地错误,而低于所设定地最大长度时,又会造成系统资源浪费,因而空间效率差。

        所以有没有更合理使用系统资源地方法呢?即当需要添加一个元素时,程序可以自动地申请内存并添加,而当需要删除一个元素时,程序又可以自动地放弃该元素原来占用地内存。

        方法就是使用动态数据结构。它是利用动态内存分配、使用结构体并配合指针来实现地一种数据结构。先看看下面地结构体代表地是什么意思:

struct temp

{

int data;

struct temp pt;

};

这个定义将出现错误警告。

这说明,结构体声明时不能包含本结构体类型成员。因本结构体类型尚未定义结束,它所占用地内存字节数尚未确定,因此系统无法为这样地结构体成员分配内存。

        然而,在声明结构体类型时可以包含指向本结构体类型地指针成员。这是因为变量存放地数据是地址,系统为指针变量分配的内存字节数(即存放地址所需要的内存字节数)是固定的(对于32位计算机系统是4个字节),不依赖于它所指向的数据类型。包含指向本结构体类型的指针成员的结构体类型说明方式如下:

struct temp

{

        int data;

        struct temp *pt;

}

二、链表的定义

        结构体和指针配合使用可表示许多复杂的动态数据结构,如链表(Linked Table)、堆栈(Stack)、队列(Queue)、树(Tree)、图(Graph)等。其中链表又包括单链表、双链表和循环链表等。

        链表实际是链式存储、顺序访问的的线性表,与数组不同的是,它是用一组任意的存储单元来存储线性表中的数据,存储单元不一定是连续的,且链表的长度不是固定的。链表数据结构体的这一特点使其可以非常方便地实现节点的插入和删除操作。

        链表的每个元素称为一个节点(Node),每个节点都可存储在内存中的不同位置。为了表示每个元素与后继元素的逻辑关系,以便构成“一个节点链着一个节点”的链式存储结构,除了存储元素本身的信息之外,还要存储器直接后继信息。因此,每个节点都包含两个部分:第1部分称为链表的数据域,用于存储元素本身的数据信息,即用户需要的数据,这里用data表示,它不局限于一个成员数据,也可是多个成员数据;第2部分是一个结构体指针,称为链表的指针域,用于存储其直接后继的节点信息,这里用next表示,next的值实际上就是下一个节点的地址,即next指向下一个节点,当前节点为末节点时,next的值设为空指针(NULL),表示链表的结束。为简单起见,通常在示意图中用符号“^”来表示。

        为表示链表结构,必须在结构体中定义一个指针类型的成员变量,用它来存储下一个节点的地址,并且该指针变量必须具有与结构体相同的数据类型。例如:

struct  link

{

        int data;

        struct link * next;

}

        此外,链表还必须有一个指向链表的起始节点的头指针变量head。

三、单向链表的建立

        我们采取向链表中添加节点的方式来建立一个单向链表。为了向链表中添加一个新的节点。首先要为新建节点申请动态内存,让指针p指向这个新建的节点,然后将新建节点添加到链表中,此时需要考虑两种情况:

(1)若原链表为空链表,则将新建节点置为头节点;

(2)若原链表为非空,则将新建节点添加到表位。

根据上述思想编写向链表添加节点数据的程序:

#include <stdio.h>
#include <stdlib.h>
struct link *AppendNode(struct link * head);
void displynode(struct link *head);
void deletememory(struct link * head);

struct link
{
	int data;
	struct link *next;
};

int main(void)
{
	int i=0;
	char c;
	struct link * head = NULL;   //链表头指针 
	printf("Do you want to append a new node (y/Y)?");
	scanf(" %c",&c);			//%c前有一个空格 
	while(c=='y'||c=='Y')
	{
		head = AppendNode(head);//向head为头指针的链表末尾添加节点 
		displynode(head);		//显示当前链表中个节点的信息 
		printf("Do you want to append a new node (Y/y)?");
		scanf(" %c",&c);       //%c前有一个空格 
		i++;
	}
	printf("%d new node have been apended! \n",i);
	deletememory(head);			//释放所有动态分配的内存 
}
//函数功能:新建一个节点并添加到链表末尾,返回添加节点后的链表的头指针 
struct link * AppendNode(struct link*head)
{
	struct link *p=NULL,*pr = head;
	int data;
	p = (struct link*)malloc(sizeof(struct link));//让p指向新建节点 
	if(p==NULL)						//若为新建节点申请内存失败,则退出程序 
	{
		printf("No enough memory to allocate!\n");
		exit(0);
	}
	if(head==NULL)					//若原链表为空表 
	{
		head=p;						//将新建节点置为头节点 
	}	
	else							//若原链表为非空,则将新建节点添加到尾表	
	{
		while(pr->next!=NULL)		//若未到尾表,则移动pr直到pr指向尾表 
		{
			pr=pr->next;			//让pr指向下一个节点 
		}
		pr->next=p;					//让末节点的指针域指向新建节点 
	}
	printf("Input node data:");
	scanf("%d",&data);				//输入节点数据 
	p->data= data;					//将新建节点的数据域赋值为输入的节点数据 
	p->next=NULL;					//将新建节点置为表尾 
	return head;					//返回添加节点后的链表的头指针 
}
//函数的功能:显示链表中所有节点的节点符号和该节点中的数据项内容 
void displynode(struct link * head)
{
	struct link *p = head;
	int j=1;
	while(p!=NULL)					//若不是表尾,则循环打印节点的值 
	{
		printf("%5d%10d\n",j,p->data); //打印第j个节点的数据 
		p= p->next;						//让p指向下一个节点 
		j++;
	}
 } 
//函数功能:释放head 指向的链表中的所有节点占用的内存。 
void deletememory(struct link * head)
{
	struct link *p = head,*pr = NULL;
	while(p != NULL)				//若不是尾表,则释放节点占用的内存 
	{
		pr= p;						//在pr中保存当前节点的指针 
		p= p->next;					//让p指向下一个节点 
		free(pr);					//释放pr指向的当前节点占用的内存 
	}
}

四、单向链表的删除操作

        链表的删除操作就是将一个待删除节点从链表中断开,不在于链表中的其他节点有任何联系。为了在已有的链表中删除一个节点,需要考虑如下四种情况:

(1)若原链表为空,则无需删除节点,直接退出程序;

(2)若找到待删除节点p是头节点,则将head指向当前节点的下一个节点(head=p->next),即可删除当前节点;

(3)若找到的待删除节点不是头节点,则将前一节的指针域指向当前节点的下一节点(pr->next=p->next)即可伤处当前节点。当待删除节点是末节点是,执行pr->next=p->next。

(4)若以搜索到表尾(p->next==NULL),仍未找到待删除节点,则显示“未找到”。

注意:节点被删除后,指标是将它从链表中断开而已,它仍然占用内存,必须释放其所占的内存,否则将出现内存泄漏。 

struct link * deletenode(struct link*head,int nodedata)
{
	struct link * p=head,*pr=head;
	if(head=NULL)		//若链表为空,则退出程序 
	{
		printf("Linked table is empty!\n");
		return(head);
	}
	while(nodedata!=p->data && p->next!=NULL)//未找到且未到末尾 
	{
		pr=p;
		p=p->next; 
	}
	if(p->data==nodedata)
	{
		if(p==head)
		{
			head=p->next;
		}
		else 
		{
			pr->next= p->next;
		}
		free(p);
		if(head==NULL)
			printf("over!");
	}
	else
	{
		printf("This Node has not been found!\n");
	}
	if(head!=NULL)
	return head;
	else exit(0);
}

五、单向链表的插入操作

        向链表中插入一个新的节点时,首先要新建一个节点,将其指针域赋值为空指针(p->next=NULL),然后再链表中寻找合适的位置执行节点插入操作,此时需要考虑以下四种情况。

(1)若原链表为空,则将新节点p作为头节点,让head指向新节点p。

(2)若原链表非空,则按节点值的大小(假设节点值已按升序排序)确定插入新节点的位置。若在头节点前插入新节点,则将新节点的指针域指向原链表的头节点(p->next=head),且让head指向新节点(head=p)。

(3)若在链表中间插入新节点,则将新节点的指针域指向下一节点(p->next = pr->next),且让前一节点的指针域指向新节点(pr->next = p)。

(4)若在表尾插入新节点,则末节点指针域指向新节点(pr->next = p)。

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

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

相关文章

线性表综合应用题1

线性表综合应用题1 从顺序表中删除具有最小值的元素&#xff08;假设唯一&#xff09;并由函数返回被删除元素的值。空出的位置由最后一个元素填补&#xff0c;若顺序表为空&#xff0c;则显示出错信息并退出运行。 算法思想&#xff1a;搜索整个顺序表&#xff0c;查找最小值元…

多元回归预测 | Matlab基于鲸鱼算法(WOA)优化高斯过程回归(WOA-GPR)的数据回归预测,matlab代码,多变量输入模型

文章目录 效果一览文章概述部分源码参考资料效果一览 文章概述 多元回归预测 | Matlab基于鲸鱼算法(WOA)优化高斯过程回归(WOA-GPR)的数据回归预测,matlab代码,多变量输入模型 评价指标包括:MAE、RMSE和R2等,代码质量极高,方便学习和替换数据。要求2018版本及以上。 部分源…

ct.js笔记-整合SweetAlert2,弹出输入框(添加Cat模组)

如下&#xff1a; 效果如下&#xff1a; 点击Name后&#xff1a; 实现如下&#xff1a; 在ct.libs中添加个新文件夹sweetalert2文件夹。 内部要包含这几个关键文件&#xff1a; ①index.js&#xff1a;调用模组的入库文件&#xff1b; ②includes文件夹&#xff1a;把需要引…

keepalived 实现 IP 地址漂移

&#x1f388; 作者&#xff1a;Linux猿 &#x1f388; 简介&#xff1a;CSDN博客专家&#x1f3c6;&#xff0c;华为云享专家&#x1f3c6;&#xff0c;Linux、C/C、云计算、物联网、面试、刷题、算法尽管咨询我&#xff0c;关注我&#xff0c;有问题私聊&#xff01; &…

基于redis实现延时队列(二)

背景 上篇文章中使用了redis的zset定时器实现延时任务&#xff0c;虽然定时器设置为30秒执行一次&#xff0c;但是还是有时间上的差异化&#xff1b;现更换一种方式实现&#xff0c;可以避免时间上的差异。 redis的key过期回调事件&#xff0c;也能达到延迟队列效果 配置修改…

抖音短视频seo矩阵源码开源SaaS部署(四)

目录 一、 抖音短视频SEO矩阵包括以下内容&#xff1a; ​编辑 二、 源码开源部署流程 三、 SaaS的理解 四、 抖音短视频seo&#xff0c;SaaS矩阵部署用到的技术 抖音短视频SEO主要是通过以下几个方面实现的&#xff1a; SaaS矩阵部署主要用到的技术包括以下几个方面&…

深蓝学院C++基础与深度解析笔记 第 11 章 类

深蓝学院C基础与深度解析笔记 第 11 章 类 1. 结构体与对象聚合 **● 结构体&#xff1a;**对基本数据结构进行扩展&#xff0c;将多个对象放置在一起视为一个整体 – 结构体的声明与定义&#xff08;注意定义后面要跟分号来表示结束&#xff09; – 仅有声明的结构体是不完全…

【Linux后端服务器开发】共享内存

目录 一、共享内存概述 二、共享内存&#xff08;IPC资源&#xff09;的查看——ipcm 三、共享内存的创建——shmget 四、共享内存的控制&#xff08;删除&#xff09;——shmctl 五、共享内存的关联——shmat 六、共享内存去关联——shmdt 七、进程间通信 一、共享内存…

力扣 -- 309. 最佳买卖股票时机含冷冻期

题目链接&#xff1a;309. 最佳买卖股票时机含冷冻期 - 力扣&#xff08;LeetCode&#xff09; 下面是用动态规划的思想解决这道题的过程&#xff0c;相信各位小伙伴都能看懂并且掌握这道经典的动规题目滴。 参考代码&#xff1a; class Solution { public:int maxProfit(vec…

基于matlab使用深度神经网络对肿瘤图像进行分类(附源码)

一、前言 此示例演示如何使用 Inception-v3 深度神经网络对可能不适合内存的多分辨率全玻片图像 &#xff08;WSI&#xff09; 进行分类。 用于肿瘤分类的深度学习方法依赖于数字病理学&#xff0c;其中整个组织切片被成像和数字化。生成的 WSI 具有高分辨率&#xff0c;大约…

Openlayers实战:平移、弹性平移、飞行动画

Openlayers地图上经常会遇到这样的一种 场景,获取到某数据后,会重新定位中心点到某个位置,这里可以用setCenter([lon,lat]), 更可以用动画的形式展现。 在本实战中,展示出平移、弹性平移、飞行的动画。 效果图 源代码 /* * @Author: 大剑师兰特(xiaozhuanlan),还是大剑…

【图像处理OpenCV(C++版)】——5.5 图像平滑之双边滤波

前言&#xff1a; &#x1f60a;&#x1f60a;&#x1f60a;欢迎来到本博客&#x1f60a;&#x1f60a;&#x1f60a; &#x1f31f;&#x1f31f;&#x1f31f; 本专栏主要结合OpenCV和C来实现一些基本的图像处理算法并详细解释各参数含义&#xff0c;适用于平时学习、工作快…

第三十六天 Java基础学习(三十)

一、Spring MVC 组件是将处理某类问题的代码进行封装的整体模块。一个大的问题可以拆分为不同的小问题&#xff0c;解决每个小问题的代码封装可以称之为组件&#xff0c;但是组件又是无法独立运行的&#xff0c;必须结合其他组件一起才能最终解决问题。就好比汽车&#xff0c;…

同步任务和异步任务的执行过程

同步任务和异步任务的执行过程 1、执行过程描述2、EventLoop的概念 1、执行过程描述 同步任务 是由JS主线程按次序执行异步任务委托给宿主环境执行已完成的异步任务对应的回调函数&#xff0c;会被加入到任务队列中等待执行JS的主线程的执行栈被清空后&#xff0c;会读取任务队…

Java026——System 类和Scanner 类

一、System 类 1.1、System 类提供的常用方法 方法 功能描述 ----------------------------------------------------------------------------------------------------------------------- currentTimeMillis() 返回当前计算机时间 和 格林威治时间&#xff…

mysql查询练习

1.创建表 CREATE TABLE worker( 部门号 int(11) NOT NULL, 职工号 int(11) NOT NULL, 工作时间 date NOT NULL,工资 float(8,2) NOT NULL,政治面貌 varchar(10) NOT NULL DEFAULT 群众 , 姓名 varchar(20) NOT NULL,出生日期 date NOT NULL,PRIMARY KEY (职工号))ENGINE…

4.3Java EE——一对多查询

用户与订单关联关系图​​​​​​​ 与一对一的关联关系相比&#xff0c;接触更多的关联关系是一对多&#xff08;或多对一&#xff09;。例如一个用户可以有多个订单&#xff0c;多个订单也可以归一个用户所有。用户和订单的关联关系如图。 一、<collection>元素 在MyB…

前端技术学习第九讲:VUE基础语法---VUE常用指令

VUE常用指令 在VUE学习中&#xff0c;通常使用相关指令使VUE对象中的内容与网页进行挂载绑定&#xff0c;是我们的数据与视图之间产生关联&#xff0c;完成渐进式动态效果。VUE指令都会以“v-”开头。 指令名描述v-text将文本内容挂载到页面元素中v-html将html代码展示到页面…

更开放、更高性能、更具规模,闪马智能布局AGI时代

7月6日&#xff0c;2023世界人工智能大会&#xff08;WAIC 2023&#xff09;在上海盛大开幕。本届大会以“智联世界 生成未来”为主题&#xff0c;聚焦通用人工智能发展&#xff0c;共话产业新未来。 8日上午&#xff0c;由上海闪马智能科技有限公司&#xff08;下称“闪马智能…

ZGC垃圾收集器(-XX:+UseZGC)

ZGC在jdk11只支持Linux版本&#xff0c;4TB的内存&#xff0c;STW时间控制在10ms内&#xff1b;jdk16已经支持16TB的内存&#xff0c;STW时间不超过1ms&#xff0c;下面主要针对jdk11版本的详解 一、堆内存结构 ZGC堆内存分为三种类型的页面即小页面&#xff08;空间大小2M&a…