线性表的链式表示

news2024/12/24 10:02:16

文章目录

  • 1.单链表
    • 1.1单链表的表示
      • 1.1.1构建 带头结点的单链表
    • 1.2基本操作
      • 1.2.1 头插法
      • 1.2.2 尾插法
      • 1.2.3 按序号查找结点
      • 1.2.4 按值查找表结点
      • 1.2.5 插入结点操作
        • 扩展:前插操作
      • 1.2.6 删除结点操作
        • 扩展:删除结点*p
      • 1.2.7 求表长操作
  • 2.双链表
    • 2.1 双链表的表示
    • 2.2基本操作
      • 2.2.1 插入操作
      • 2.2.2 删除操作
  • 3.循环链表
    • 3.1 循环单链表
    • 3.2 循环双链表
  • 4.静态链表


1.单链表

1.1单链表的表示

单链表中节点类型的描述如下:

typedef struct LNode{
	ElemType data;	//数据域
	struct LNode *next;	//指针域
}LNode,*LinkList;

1.1.1构建 带头结点的单链表

typedef struct LNode{	//定义单链表结点类型
	ElemType data;		//每个结点存放一个数据元素
	struct LNode *next;	//指针指向下一个节点
} LNode,*LinkList;

//初始化一个单链表(带头结点)
bool InitList(LinkList &L){
	L=(LNode*)malloc(sizeof(LNode));	//分配一个头结点
	if(L==NULL)			//内存不足,分配失败
		return false;
	L->next=NULL;	//节点之后暂时还没有节点
	return true;	
}

void test(){
	LinkList L;		//声明一个指向单链表的指针
	//初始化一个空表
	InitList(L);
	//后续代码...
}
//判断单链表是否为空(带头结点)
bool Empty(LinkList L){
	if(L->next==NULL)
		return true;
	else
		return false;
}

1.2基本操作

受某些限制,没法把动画效果做出来,看看图理解一下吧~

在这里插入图片描述

强调这是一个单链表使用LinkList
强调这是一个结点使用LNode*

1.2.1 头插法

LinkList List_HeadInsert(LinkList &L){	//逆向建立单链表
	LNode *a;
	int x;
	L=(LinkList)malloc(sizeof(LNode));	//创建头结点
	L->next=NULL;	//初始为空链表
	scanf("%d",&x);	//输入节点的值
	while(x!=9999){	//输入9999表示结束
		s=(LNode*)malloc(sizeof(LNode));	//创建新结点
		s->data=x;
		s->next=L->next;
		L->next=s;	//将新结点插入表中
		scanf("%d",&x);
	}
	return L;
}

采用头插法建立单链表时,读入数据的顺序与生成的链表中的元素的顺序是相反的

时间复杂度为O(n)

1.2.2 尾插法

将新结点插入到当前链表的表尾,为此必须增加一个尾指针r,使其始终指向当前链表的尾结点

LinkList List_TailInsert(LinkList &L){	//正向建立单链表
	int x;	//设元素为整形
	L=(LinkList)malloc(sizeof(LNode));
	LNode *s,*r=L;	//r为表尾指针
	scanf("%d",&x);	//输入结点的值
	while(x!=9999){
		s=(LNode *)malloc (sizeof (LNode));
		s->data=x;	//新的数据为x
		r->next=s;	//r的下个结点指向s
		r=s;		//r指向s
		scanf("%d",&x);
	}
	r->nxt=NULL;	//尾结点指针置空
	return L;
}

时间复杂度为O(n)

1.2.3 按序号查找结点

LNode *GetElem(LinkList L,int i){
	if (i<1)
		return NULL;
	int j=1;	//计数,初始为1
	LNode *p=L->next;	//第一个结点指针赋值给p
	while(p!=NULL&&j<i){	//从第一个结点开始找,查找第i个结点
		p=p->next;
		j++;
	}
	return p;	//返回第i个结点的指针,若i大于表长,则返回NULL
}

时间复杂度为O(n)

1.2.4 按值查找表结点

LNode *LocateElem(LinkList L,ElemType e){
	LNode *p=L->next;
	while(p!=NULL&&p->data!=e)	//从第一个结点开始查找data域为e的结点
		p=p->next;
	return p;	//找到后返回该结点指针,否则返回NULL
}

1.2.5 插入结点操作

在这里插入图片描述

p=GetElem(L,i-1);	//查找插入位置的前驱结点
s->next=p->next;	//操作步骤1
p->next=s;			//操作步骤2

扩展:前插操作

设插入结点为s,将s插入到*p的后面,然后将p->data和s->data交换

//将*s结点插入到*p之前的主要代码片段
s->next=p->next;	//修改指针域,不能颠倒
p->next=s;
temp=p->data;		//交换数据域部分
p->data=s->data;
s->data=temp;

1.2.6 删除结点操作

假设p为找到的被删结点的前驱结点,仅需修改p的指针域,即将p的指针域next指向q的下一结点

p=GetElem(L,i-1);		//查找删除位置的前驱结点
q=p->next;				//令q指向被删除结点
p->next=q->next;		//将*q结点从链中断开
free(q);				//释放结点的存储空间

时间复杂度为O(n)

扩展:删除结点*p

删除结点可用删除*p的后继结点来实现,本质就是将其后继节点的值赋予其自身,然后删除后继结点,这样使得时间复杂度为O(1)

q=p->next;		//令q指向*p的后继结点
p->data=p->next->data;	//用后继结点的数据域覆盖
p->next=q->next;		//将*q结点从链中断开
free(q);		//释放后继结点的存储空间

1.2.7 求表长操作

统计数据结点的个数(不包含头结点),需要设置一个计数器

单链表的长度是不包括头结点的


2.双链表

2.1 双链表的表示

双链表结点中有两个指针prior和next,分别指向其前驱结点和后继结点

访问前驱结点的时间复杂度为O(n)
访问后继结点的时间复杂度为O(1)

双链表中结点类型的描述如下:

typedef struct DNode{	//定义双链表结点类型
	ElemType data;		//数据域
	struct DNode *prior,*next;	//前驱和后继指针
}DNode,*DLinkList;

2.2基本操作

在这里插入图片描述

2.2.1 插入操作

s->next=p->next;	//将结点*s插入到结点*p之后
p->next->prior=s;
s->prior=p;
p->next=s;

2.2.2 删除操作

p->next=q->next;
q->next->prior=p;
free(q);

3.循环链表

3.1 循环单链表

表中最后一个结点的指针不是NULL,而改为指向头结点,从而整个链表形成一个环。

在循环单链表中,表尾结点*r的next域指向L,故表中没有指针域为NULL的结点,因此,循环单链表的判空条件不是头结点的指针是否为空,而是它是否等于头结点。

3.2 循环双链表

在循环双链表L中,某结点*p为尾结点时,p->next==L;当循环双链表为空表时,其头结点的prior域和next域都等于L。


4.静态链表

静态链表的指针是结点的相对地址(数组下标),又称游标
和顺序表一样,静态链表也要预先分配一块连续的内存空间。

静态链表的结构类型:

# define MaxSize=50		//静态链表的最大程度
typedef struct{
	ElemType data;
	int next;			//下一个元素的数组下标
}SlinkList[MaxSize];

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

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

相关文章

JVM相关知识

JVM类加载过程类什么时候被加载什么情况下会发生栈内存溢出JVM内存模型常量池回收方法区垃圾回收流程圾收集算法分代收集理论标记-清除算法标记-复制算法标记-整理算法类加载过程 加载–验证–准备–解析–初始化–使用–卸载 ​ 加载&#xff1a;通过全类名获取类的二进制流…

【C++】非类型的模板参数,特化

目录 1.类型模板参数和非类型模板参数 2.特化 3. 模板的分离编译 4.模板的优缺点 1.类型模板参数和非类型模板参数 之前写模板传的都是类型——类型模板参数 现在想定义两个静态数组&#xff0c;数组长度不同&#xff0c;就可以用模板参数传数值而不是传类型 非类型模板…

Docker与微服务实战2022

基础篇(零基小白)1.Docker简介1.1 是什么问题&#xff1a;为什么会有docker出现&#xff1f;您要如何确保应用能够在这些环境中运行和通过质量检测&#xff1f;并且在部署过程中不出现令人头疼的版本、配置问题&#xff0c;也无需重新编写代码和进行故障修复&#xff1f; 答案就…

Android源码分析 - View的触摸事件分发

0. 相关分享 Android源码分析 - InputManagerService与触摸事件 1. 接收Input系统发送来的事件 时序图源&#xff1a;稀土掘金 在注册Window的时候&#xff0c;来到ViewRootImpl&#xff0c;其中不仅发起窗口注册&#xff0c;还开启了输入事件的监听&#xff1a; //ViewRoo…

nuxt3使用总结

目录 背景 安装 项目配置 路由 Tailwindcss引入 全局样式配置 css预处理器 安装 Tailwindcss 项目的配置 部署上线 seo优化 背景 新入职了一家公司&#xff0c;刚进入公司第一个需求就是先做一个公司的官网&#xff0c;需要使用vue写&#xff0c;作为祖师爷的粉丝…

Java 电话号码的组合

电话号码的字母组合中等给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。答案可以按 任意顺序 返回。给出数字到字母的映射如下&#xff08;与电话按键相同&#xff09;。注意 1 不对应任何字母。示例 1&#xff1a;输入&#xff1a;digits "23…

案例学习--016 消息队列作用和意义

简介MQ全称为Message Queue, 是一种分布式应用程序的的通信方法&#xff0c;它是消费-生产者模型的一个典型的代表&#xff0c;producer往消息队列中不断写入消息&#xff0c;而另一端consumer则可以读取或者订阅队列中的消息。主要产品有&#xff1a;ActiveMQ、RocketMQ、Rabb…

【RV1126】RKMedia模块简介

文章目录简介源码与编译rkmedia log等级配置目录参考文档&#xff1a;【Rockchip RKMedia Development Guide】rkmedia的手册在sdk目录下/docs/RV1126_RV1109/Multimedia rkmedia的代码在sdk目录下/external/rkmedia rkmedia的demo在sdk目录下/external/rkmedia/examples&…

antlr4-maven-plugin简单学习

1. 序言 antlr4-maven-plugin的官方介绍为&#xff1a; The ANTLR 4 plugin for Maven can generate parsers for any number of grammars in your project.博客《 mac上的Antlr4环境搭建》&#xff0c;有介绍如何通过antlr4-maven-plugin实现.g4文件的编译 这里将介绍antlr4-…

弹性存储-对象存储OSS部分

对象存储介绍 对象存储&#xff08;object storage service&#xff0c;简称oss&#xff09;&#xff0c;具备与平台无关的rest api接口&#xff0c;可提供99.9999999999%&#xff08;12个9&#xff09;的数据持久性和99.995%的数据可用性。 OSS优势 功能介绍 存储空间bucke…

秒杀高并发解决方案

秒杀高并发解决方案 1.秒杀/高并发方案-介绍 秒杀/高并发 其实主要解决两个问题&#xff0c;一个是并发读&#xff0c;一个是并发写并发读的核心优化理念是尽量减少用户到 DB 来"读"数据&#xff0c;或者让他们读更少的数据, 并 发写的处理原则也一样针对秒杀系统需…

麒麟服务器V10 版本 安装 Anaconda教程,也就是安装Python环境的教程(亲测有效)

目录1 Anaconda 是什么2 安装1 Anaconda 是什么 你可以理解为一个软件&#xff0c;和QQ一样的软件&#xff0c;你安装之后&#xff0c;里面就有naconda包括Conda、Python以及一大堆安装好的工具包&#xff0c;比如&#xff1a;numpy、pandas等 1&#xff09;包含conda&#x…

【C++学习】类和对象(上)

前言&#xff1a; 由于之前电脑“嗝屁”了&#xff0c;导致这之前一直没有更新博客&#xff0c;今天才拿到电脑&#xff0c;在这里说声抱歉。接下来就进入今天的学习&#xff0c;在之前我们已经对【C】进行了初步的认识&#xff0c;有了之前的知识铺垫&#xff0c;今天我们将来…

初识BFC

初识BFC 先说如何开启BFC&#xff1a; 1.设置display属性&#xff1a;inline-block&#xff0c;flex&#xff0c;grid 2.设置定位属性&#xff1a;absolute&#xff0c;fixed 3.设置overflow属性&#xff1a;hidden&#xff0c;auto&#xff0c;scroll 4.设置浮动&#xf…

英雄算法学习路线

文章目录零、自我介绍一、关于拜师二、关于编程语言三、算法学习路线1、算法集训1&#xff09;九日集训2&#xff09;每月算法集训2、算法专栏3、算法总包四、英雄算法联盟1、英雄算法联盟是什么&#xff1f;2、如何加入英雄算法联盟&#xff1f;3、为何会有英雄算法联盟&#…

Linux系统安装mysql(rpm版)

目录 Linux系统安装mysql&#xff08;rpm版&#xff09; 1、检测当前系统中是否安装MySQL数据库 2、将mysql安装包上传到Linux并解压 3、按照顺序安装rpm软件包 4、启动mysql 5、设置开机自启 6、查看已启动的服务 7、查看临时密码 8、登录mysql&#xff0c;输入临时密…

C++ STL学习之【vector的使用】

✨个人主页&#xff1a; Yohifo &#x1f389;所属专栏&#xff1a; C修行之路 &#x1f38a;每篇一句&#xff1a; 图片来源 The power of imagination makes us infinite. 想象力的力量使我们无限。 文章目录&#x1f4d8;前言&#x1f4d8;正文1、默认成员函数1.1、默认构造…

STM32之SPI

SPISPI介绍SPI是串行外设接口(Serial Peripherallnterface)的缩写&#xff0c;是一种高速的&#xff0c;全双工&#xff0c;同步的通信总线&#xff0c;并且在芯片的管脚上只占用四根线&#xff0c;节约了芯片的管脚&#xff0c;同时为PCB的布局上节省空间&#xff0c;提供方便…

蓝桥杯嵌入式(G4系列):定时器捕获

前言&#xff1a; 定时器的三大功能还剩下最后一个捕获&#xff0c;而这在蓝桥杯嵌入式开发板上也有555定时器可以作为信号发生器供定时器来测量。 原理图部分&#xff1a; 开发板上集成了两个555定时器&#xff0c;一个通过跳线帽跟PA15相连&#xff0c;最终接到了旋钮R40上&…

STM32F103CubeMX定时器

前言定时器作为最重要的内容之一&#xff0c;是每一位嵌入式软件工程师必备的能力。STM32F103的定时器是非常强大的。1&#xff0c;他可以用于精准定时&#xff0c;当成延时函数来使用。不过个人不建议这么使用&#xff0c;因为定时器很强大&#xff0c;这么搞太浪费了。如果想…