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 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 【数据结构】一文了解链表【思路+例题学习】 -> 正文阅读

[数据结构与算法]【数据结构】一文了解链表【思路+例题学习】

🏆今日学习目标:
🍀学习算法-数据结构-链表
?创作者:贤鱼
?预计时间:30分钟
🎉个人主页:贤鱼的个人主页
🔥专栏系列:算法
🍁贤鱼的个人社区,欢迎你的加入 贤鱼摆烂团

请添加图片描述

🍁链表

🍀介绍🍀

链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。

每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域

🍀分类🍀

🍉单项链表🍉

在这里插入图片描述

每一个单元都指向下一位

在这里插入图片描述

🍉循环链表🍉

在这里插入图片描述

和单链表差不多,只不过第一位和最后一位相连,变成了循环链表

🍉双向链表🍉

在这里插入图片描述

🍁常见操作🍁

🍀链表🍀

头文件

#include

插入

前方插入push_front(数字)
在链表最前面插入一个数字
后方插入push_back(数字)
链表最后面插入一个数字
中间插入insert(迭代器,数字)
在迭代器指向的链表元素前面插入一个数字

删除

erase(迭代器)
删除迭代器指向的链表元素

查找

begin()
链表头
end()
链表末尾
需要迭代器储存

输出

需要迭代器,后文会讲

结构体模拟部分看例题解法2

🍀迭代器🍀

list::iterator 名字

迭代器是一种检查容器内元素并遍历元素的数据类型
可以理解为数组的下标
举个例子

list<int>::iterator pos[10005];
list<int> m;
pos[5]//迭代器代表的内容就是链表中元素为5的部分
list<int>::iterator iterbegin;
iterbegin=m.begin();
cout<<*iterbegin;//输出链表第一位数值
//循环
list<int>::iterator iterend;
iterend=m.end();
for(;iterbegin!=iterend;iterbegin++){
//内容
}

循环也很好理解

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

只有当begin=end的时候循环就会结束

🍁例题🍁

🍀队列安排🍀

🍎题目描述🍎

一个学校里老师要将班上 N N N 个同学排成一列,同学被编号为 1 ~ N 1\sim N 1N,他采取如下的方法:

  1. 先将 1 1 1 号同学安排进队列,这时队列中只有他一个人;

  2. 2 ? N 2-N 2?N 号同学依次入列,编号为 i i i 的同学入列方式为:老师指定编号为 i i i 的同学站在编号为 1 ~ ( i ? 1 ) 1\sim(i-1) 1(i?1) 中某位同学(即之前已经入列的同学)的左边或右边;

  3. 从队列中去掉 M ( M < N ) M(M<N) M(M<N) 个同学,其他同学位置顺序不变。

在所有同学按照上述方法队列排列完毕后,老师想知道从左到右所有同学的编号。

🍎输入格式🍎

1 1 1 行为一个正整数 N N N,表示了有 N N N 个同学。

2 ~ N 2\sim N 2N行,第 i i i 行包含两个整数 k , p k,p k,p,其中 k k k 为小于 i i i 的正整数, p p p 0 0 0 或者 1 1 1。若 p p p 为$ 0$,则表示将 i i i 号同学插入到 k k k 号同学的左边, p p p 1 1 1 则表示插入到右边。

N + 1 N+1 N+1 行为一个正整数 M M M,表示去掉的同学数目。

接下来 M M M 行,每行一个正整数 x x x,表示将 x x x 号同学从队列中移去,如果 x x x 号同学已经不在队列中则忽略这一条指令。

🍎输出格式🍎

1 1 1 行,包含最多 N N N 个空格隔开的正整数,表示了队列从左到右所有同学的编号,行末换行且无空格。

🍎样例 #1🍎

🍍样例输入 #1🍍

4
1 0
2 1
1 0
2
3
3

🍍样例输出 #1🍍

2 4 1

🍎提示🍎

样例解释:

将同学 2 2 2 插入至同学 1 1 1 左边,此时队列为:

2 1

将同学 3 3 3 插入至同学 2 2 2 右边,此时队列为:

2 3 1

将同学 4 4 4 插入至同学 1 1 1 左边,此时队列为:

2 3 4 1

将同学 3 3 3 从队列中移出,此时队列为:

2 4 1

同学 3 3 3 已经不在队列中,忽略最后一条指令

最终队列:

2 4 1

数据范围

对于 20 % 20\% 20% 的数据,有 1 ≤ N ≤ 10 1\leq N\leq 10 1N10

对于 40 % 40\% 40% 的数据,有 1 ≤ N ≤ 1000 1\leq N\leq 1000 1N1000

对于 100 % 100\% 100% 的数据,有 1 ≤ N , M ≤ 100000 1\leq N,M\leq100000 1N,M100000

🍀思路🍀

这个题很简单,如果不是m数据范围太大,循环直接就可以解决

问题是他数据范围很大

我们可以用一个迭代器pos[]来储存每一位数字
这样子插入就解决了
利用insert
pos[k]就是插入数字的位置(找到k数字插入)

然后就是删除
输入x
利用erase
删除pos[x]就好了

接着就是输出
我们用迭代器ib,id(iterbegin和iterend)来储存链表头和链表尾,循环输出就可以了
ib=m.begin()
id=m.end()

当然,结构体也可以做这个题
结构体a,内有l,r。表示当前数字的左边和右边
a[].r就是当前数字的右边
a[].l就是当前数字的左边
这样子也可以模拟链表
其他具体内容下列题解见

🍀做法1🍀

第一种是用链表的做法,来巩固一下上文学习的知识

#include<cmath>
#include<iostream>
#include<cstdio>
#include<iostream>
#include<list>
using namespace std;
typedef  list<int>::iterator iter;//这个的意思是iter代表前面迭代器部分,不然手打好麻烦(你问我为啥不用下头两个??我觉得颜色放一起好看~)
//using Iner =;
//const int maxn=xxx;常量
iter next(iter it){//这里手写一个next函数,意思就是指向传入参数迭代器的下一位
	it++;
	return it;
}
iter pos[100005];//定义迭代器
list<int>m;//定义链表
int f[100005];
int n;
void build(){
	m.push_front(1);//链表第一位插入1
	pos[1]=m.begin();//储存
	for(int i=2;i<=n;i++){
		int k,p;
		cin>>k>>p;
		if(p==0){//这个是在左边插入,直接用insert就可以了
			pos[i]=m.insert(pos[k],i);//意思是在数组k的左边插入数字i
		}else{
			iter nextx=next(pos[k]);//这里右边插入需要处理一下,利用手写next函数指向下一位迭代器(老版本无法直接用next函数,所以手打)
			pos[i]=m.insert(nextx,i);//在数字k的下一位的前面插入i
		}
	}
	int mm;
	cin>>mm;
	for(int i=1;i<=mm;i++){
		int x;
		cin>>x;
		if(!f[x]) m.erase(pos[x]);//删除链表中x元素
		f[x]=1;
	}
}
int main(){
	cin>>n;
	build();
	iter ib=m.begin();//储存链表头
	iter id=m.end();//储存链表尾
	int f1=1;
	for(;ib!=id;ib++){//循环
		if(!f1) cout<<" ";//这里处理一下空格,不理解代入数据走一遍就知道了
		cout<<*ib;//意思是输出ib迭代器指向的数字
		f1=0;
	}
	cout<<endl;
	return 0}


🍀做法2🍀

#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
struct node{
	int l,r;
}a[100005];
void del(int x){
	if(a[x].l==-1) return ;
	a[a[x].l].r=a[x].r;
	a[a[x].r].l=a[x].l;
	a[x].l=-1;
	a[x].r=-1;
}
void adr(int x,int k){
	a[x].l=k;
	a[a[k].r].l=x;
	a[x].r=a[k].r;
	a[k].r=x;
}
void adl(int x,int k){
	a[x].r=k;
	a[a[k].l].r=x;
	a[x].l=a[k].l;
	a[k].l=x;
}
int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		a[i].l=a[i].r=-1;
	}
	a[1].l=0;
	a[0].r=1;
	for(int i=2;i<=n;i++){
		int k,p;
		cin>>k>>p;
		if(p==1){
		 adr(i,k);
		}else{
			adl(i,k);
		}
	}
	int m;
	cin>>m;
	for(int i=1;i<=m;i++){
		int x;
		cin>>x;
		del(x);
	}
	int xx=a[0].r;
	while(1){
		cout<<xx<<" ";
		if(a[xx].r==-1) break;
		xx=a[xx].r;
	}
	cout<<endl;
}

结构体模拟链表
在这里插入图片描述

删除部分

void del(int x){
	if(a[x].l==-1) return ;
	a[a[x].l].r=a[x].r;
	a[a[x].r].l=a[x].l;
	a[x].l=-1;
	a[x].r=-1;
}

这里a[a[x].l].r代表的就是当前数字
a[x].r代表就是当前数字的右边
所以这两个等于的意思就是当前数字左边的右边变成当前数字的右边
在这里插入图片描述
在这里插入图片描述

第二个的意思就是当前数字右边的左边指向当前数字的左边
在这里插入图片描述
这么一看,是不是中间的 b 部分就被孤立出来啦
所以总结一下删除的两个步骤

  • 将当前元素的 右边元素 的左边 指向 当前元素 的左边
  • 将当权元素的 左边元素 的右边 指向 当前元素 的右边
  • 所以当前数字左右两边互相联系,当前数字就被删除了

    右边添加数字部分

    void adr(int x,int k){
    	a[x].l=k;
    	a[a[k].r].l=x;
    	a[x].r=a[k].r;
    	a[k].r=x;
    }
    

    第一句话的意思就是插入的数字的左边指向k
    第二句话的意思是在k指向右边的数字的左边指向x

    在这里插入图片描述

    在这里插入图片描述

    第三个的意思就是x的右边指向k的右边,也就是c
    最后让k的右边变成x就可以了
    在这里插入图片描述

  • 将要添加的数字的左元素右边,右元素左边指向自己,就做到了添加数据的功能
  • 左边添加数字部分

    void adl(int x,int k){
    	a[x].r=k;
    	a[a[k].l].r=x;
    	a[x].l=a[k].l;
    	a[k].l=x;
    }
    

    这里恰好和上文相反,可以参照右边添加数字部分
    在这里插入图片描述

    所以结构体也是可以模拟链表的速度比链表还要快

    在这里插入图片描述

    (上链表,下结构体)

    🏆结束语🏆

    今天链表的学习就到这里了,如果大家有什么问题或者有意见可以在评论区中提出,相信在贤某的努力和大家的监督下一定会创作出更加优质的文章

    后序会讲解更多关于算法的知识,感兴趣的各位可以订阅一下专栏呀

    请添加图片描述

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-11-05 00:49:40  更:2022-11-05 00:54:07 
 
开发: 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年11日历 -2024/11/25 19:26:34-

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