IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 数据结构-单链表(2) -> 正文阅读

[数据结构与算法]数据结构-单链表(2)

摘要

接上一讲的线性表,这讲针对单链表对线性表的缺点和单链表的优缺点、怎么理解单链表的操作做一个笔记,如果对线性表有疑问的可以看第一讲:第一讲线性表

线性表的链式存储结构绪论

线性表的顺序存储结构问题,使得线性表不能高效的进行数据的增删操作,因此提出了线性表的链式存储结构。关于线性表的链式存储结构可以在一定程度认为用空间换取对线性表的增删等工作的操作时间,对于这句话的解释说明,放在了总结里面。
先看线性表链式存储的结构:
为了表示每个数据元素 a i a_i ai?与其直接后继元素 a ( i + 1 ) a_( i+1_) a(?i+1)?之间的逻辑关系,对数据元素 a i a_i ai?而言,除了存储本身的信息之外,还需要存储表示后继元素的信息,把存储数据元素的空间称为数据域,把存储后继元素位置的空间称为指针域-----《大话数据结构》指针域存储的信息称为指针(本身就是指针)或者链,数据域和存储下一个后继元素的位置信息的指针域称为结点
简单理解:
顺序存储结构就一个存储数据信息的地方,后继元素是紧挨着先驱元素(排除第一个元素和最后一元素,因为第一个元素没有先驱,最后一个元素没有后继),而链式存储结构中先驱结点中不仅有存储数据域还有存储后继结点位置的指针域。
注意:
顺序存储结构把线性表中相邻位置的元素(这里的元素不包括先驱和后继)称为先驱元素或者后继元素,链式存储结构则称为结点(这里指的节点不包括头和尾),同时要注意结点中的指针域存储的是下一个结点的位置,如下图示例所示:
链式存储结构

其中数据域存储的是该节点的数据信息,指针域存储的是下一个结点的指针,例如结点i的指针域[0x4586]存储的就是结点i+1的地址,结点i的指针域存储的是下一个结点的内存地址,该内存里面包含了该结点的数据信息的数据域和下一个结点内存的地址的指针域。下面对链式存储结构做一个补充:

  1. 单链表 :n个结点链接成一个链表,类似于线性表的链式存储结构,因为每个结点只包含一个指 针域,所以叫做单链表;
  2. 头结点:与第一个节点不同,头结点的指针域(头指针)存储了第一个结点的地址,其数据域可以存储线性表的长度等信息;
  3. 空链表:第一个结点的指针域存储 的为“NULL”或“^”;
  4. 单链表存储结构:
typedef struct Node
{
	ElemType data;
	struct Node *next;
}Node;
typedef struct Node *LinkList

单链表的常规操作

这里与线性表类似,但是又不一样,这里需要理解指针内存之间的关系。否则在进行插入和删除操作时不能理解。

单链表查找

查找第 i i i 个数据

  1. 声明一个结点 p p p指向链表的第一个结点,申明一个计数变量 j j j
  2. j < i j < i j<i时,遍历链表,结点 p p p向后移动, j j j累加;
  3. 如果遍历到末尾结点,则说明第 i i i个元素不存在;
  4. 否则查找成功,返回 p p p的数据域。
    伪代码:
Status GetElem(LinkList L, int i, ElemType *e)
{
	int j
	LinkList p;
	p = L -> next;
	j = 1;
	while(p && j< i) /*遍历链表*/
	{
		p = p -> next; /*获取下一个结点的地址*/
		++j; /*遍历计数*/
	}
	if !p || j>=i
		return error; /*链表中不存在i个元素*/
	*e = p->data; /*否则返回p的数据域*/
	return *e;
}

单链表就的遍历时间复杂度为 O ( n ) O(n) O(n)主要是遍历到第 i i i个元素,因为 i = 1 i=1 i=1 i = n i=n i=n即最后一个,这是事前无法预料的,因此时间复杂度为 O ( n ) O(n) O(n),其实是 O ( n + 1 2 ) O( \frac{n+1}{2}) O(2n+1?)

单链表插入

在第 i i i个位置插入元素操作步骤

  1. 声明一个结点 p p p指向链表的第一个结点,申明一个计数变量 j j j
  2. j < i j < i j<i时,遍历链表,结点 p p p向后移动, j j j累加;
  3. 如果遍历到末尾结点,则说明第 i i i个元素不存在;
  4. 否则查找成功,向系统申请一个LinkList类型的结点 s s s
  5. 将待插入的元素赋值给 s s s结点的数据域;
  6. 插入标准语句:s->next = p->next; p->next = s
  7. 返回
    伪代码:
Status ListInsert(LinkList *L, int i,ElemType e)
{
	int j =1 ;
	LinkList p,s;
	p = *L; /*单链表的头结点地址赋值给p*/
	while(p && j<i) /*遍历*/
	{
		p = p -> next;
		++j;
	}
	if(!p || j>=i)     /*判断i个位置是否在链表中存在*/
		return error;
	s = (LinkList) malloc(sizeof(Node)); /*申请一块类型为LinkList,大小为sizeof(Node)的内存*/
	s -> data = e; /*把待插入数据放入s结点的数据域*/
	s -> next = p -> next;   /*将p结点的指针域赋值给s结点的指针域*/
	p -> next = s;         /*将s的地址赋值给p的指针域(后继)*/
	return e;
}

这里的第六点,s->next = p->next; p->next = s 需要解释一下,最开始我也有点没看懂,但是仔细思考了指针和内存的关系链表中指针域和结点的关系之后再看这个就醍醐灌顶了。
申请的s结点内存数据格式跟链表的数据格式是一致的,首先把待插入的数据赋值到s -> data然后把p结点(第i个位置插入)的指针域赋值给s->next这样s结点的指针域就指向了原本p结点指针域指向的下一个结点。再把s结点的地址赋值给p->next这样使得p的指针域指向的是s结点。

单链表删除

在第 i i i个位置删除元素操作步骤

  1. 声明一个结点 p p p指向链表的第一个结点,申明一个计数变量 j j j
  2. j < i j < i j<i时,遍历链表,结点 p p p向后移动, j j j累加;
  3. 如果遍历到末尾结点,则说明第 i i i个元素不存在;
  4. 否则查找成功,向系统申请释放结点 p p p
  5. 将待删除的结点p->next赋值给 q q q结点;
  6. 删除的标准语句p->next = q -> next
  7. 释放;
  8. 返回;
    伪代码:
Status ListDelete(LinkList *L, int i, ElemType e)
{
	
	int j
	LinkList p,q;
	p = L -> next;
	j = 1;
	while(p && j< i) /*遍历链表*/
	{
		p = p -> next; /*获取下一个结点的地址*/
		++j; /*遍历计数*/
	}
	if(!p || j>=i)     /*判断i个位置是否在链表中存在*/
		return error ;
	q = p->next;
	p->next = q->next;
	e = q ->data;
	free(q);
	return e;
}

这里要注意的是代码的最后几句,这里先不做分析,如果看不懂的请看下讲,链表的整表操作,会仔细剖析指针和内存的关系与结点个指针域的结合。

总结

相比顺序存储结构的线性表,链式存储结构的插入和删除比较快,但是这种快是一次性插入或者删除多个连续的数据,因为只需要遍历一次。但是它比顺序存储结构占用的内存更多,因为不光要存储数据还要存储下一个结点的指针域。
2021-8-17

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-08-18 12:56:50  更:2021-08-18 12:57:03 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/28 16:59:35-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计