数据结构——队列和链表

前言

        还有一个多月就要打蓝桥杯了,荔枝最近开始学习一些基本的数据结构和算法,接下来在数据结构这个专栏里可以看到荔枝学习的脚步哦哈哈哈哈。这篇文章主要是荔枝在队列和链表的学习笔记,希望对大家有帮助哈哈哈


文章目录

前言

一、队列

1.1 STL普通队列——queue

1.2 STL双端队列——deque

1.3 循环队列 

二、链表

2.1  ListNode及其基本操作

2.2 样题分析——力扣21.合并两个有序链表

总结


一、队列

        什么是队列呢?顾名思义,队列这种数据结构其实跟日常生活中排队的情景类似,都是采用先进先出的策略,这很好理解,因为在日常生活中的排队场景下,第一个排队的一定是第一个通过的。 那么我们如何使用队列这种数据结构呢?C++在STL库中就提供了一个queue容器适配器,使用前首先导入头文件<queue>。

1.1 STL普通队列——queue

获取队首

front():返回队首元素

获取队尾

back():返回队尾元素

入队与出队

push():队尾插入元素

pop():弹出队首元素

检查是否为空

empty():检查队列中元素为空

返回元素个数

size():返回队列中元素的个数

1.2 STL双端队列——deque

STL在deque容器中提供了有关双端队列的一众成员函数给我们使用。与queue相比,同样有front()和back()这两个获取队首和队尾的成员函数;同样的也有empty()和size()这两种成员函数。

有关修改操作的成员函数:

push_back():在队尾插入元素

pop_back():弹出队尾元素

push_front():在队首插入元素

push_back(): 弹出队首元素

insert():在指定位置前插入元素(传入迭代器和元素)

erase():删除指定位置的元素(传入迭代器)

1.3 循环队列 

        不管是顺序队列还是顺序链表,都会存在内存空间无法再次利用的情况,也就是假溢出的情况。这时候有一个循环的数据结构无疑会解决这一问题——随着元素的入队与出队,整个队列的存储其实即相当于在队列圈中环绕进行,但是整个队列还是一种线性表的形式,只是被我们当作环状表来实现。

判断队列已满的条件:

队列的rear指针(rear+1)%队列长度==top,其中rear是尾指针,top是头指针。


二、链表

        在前面我们其实比较熟悉的就是数组这一种数据结构,链表与数组相比都可以自由管理数据存取和删除,但其优点在于数据的增添或删除的速度上,这是因为链表并不是一种线性存储的结构,而是利用指针达到一种指向的关系从而形成数据的存储形式。

2.1  ListNode及其基本操作

struct ListNode {
      int val;  //当前结点的值
      ListNode *next;  //指向下一个结点的指针
      ListNode(int x) : val(x), next(NULL) {}  //初始化当前结点值为x,指针为空
  };

初始化: 

//初始化一个空节点,head就是一个结构体指针,初始赋值为0
ListNode* head = new ListNode(0);
//cur和head都是一个结构体指针,指向同一个new关键字开辟的内存空间
ListNode* cur = head;

 单链表的构建过程:

struct ListNode
{
    double value;
    ListNode *next;
};
ListNode* head = nullptr;//空节点
head = new ListNode;
//给第一个节点赋值
head->value = 1;
//第一个创建节点的指针指向链表的末位置  
head->next = nullptr;

//创建第二个节点
ListNode* sPtr = new ListNode;
sPtr->value = 2;
//第二个创建节点的指针next指向链表的末位置  
sPtr->next = nullptr; 
//第一个创建节点的next指针第二个
head->next = sPtr; 

C++中new关键字的作用:

        一般来说我们在创建一个变量的时候会默认是以栈的形式来储存的,但使用了new关键字就可以实现数据是以堆的形式来储存。使用new关键字来创建一个对象时,会获得一块内存空间(动态内存分配)、同时调用构造函数并放回正确的指针。使用了new关键字就可以不再使用定义结构体变量在将地址赋值给指针了。需要注意的是:new出来的是一段空间的首地址。所以一般需要用指针来存放这段地址。而对于结构体指针ListNode*,可以通过new来直接开辟内存空间并获得地址,使用->来获取属性或指针,当然也可以直接使用结构体的调用方法来实现功能。

2.2 样题分析——力扣21.合并两个有序链表

题目

输入两个递增的链表,单个链表的长度为n,合并这两个链表并使新链表中的节点仍然是递增排序的。

数据范围: 0<=n<=1000,  -1000<=节点值<=1000
要求:空间复杂度 O(1),时间复杂度 O(n)

合并两个链表并按照升序的顺序进行重新排序并合并,这个过程需要利用链表的基本结构,这道题可以使用递归,也可以直接暴力出来,但是对比两种方法的复杂度其实我觉得直接暴力更好哈哈哈。 

代码示例: 

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/

//暴力解法——T:O(M,N)/S:O(1)
#include <cstddef>
class Solution {
public:
    ListNode* Merge(ListNode* pHead1, ListNode* pHead2) {
		//首先解决边界条件
		if(pHead1 == NULL)
			return pHead2;
		if(pHead2 == NULL)
			return pHead1;
		
		//初始化一个空节点
		ListNode* head = new ListNode(0);
		ListNode* cur = head;

		while (pHead1 && pHead2) {
			if(pHead1->val <= pHead2->val){
				cur->next = pHead1;
				pHead1 = pHead1->next;
			}else {
				cur->next = pHead2;
				pHead2 = pHead2->next;
			}
			//指针后移
			cur = cur->next;
		}
		if(pHead1)
            cur->next = pHead1;
        else
            cur->next = pHead2;
        //返回值去掉表头
        return head->next;
    }
};

总结

        在这篇文章中,荔枝主要做了一下队列和链表的基础知识笔记,荔枝也知道后期肯定是要通过刷题来掌握的这些数据结构的,总之任重而道远!今天还是有点收获的——至少弄懂了结构体指针和队列、链表的基础部分。最后还要特别鸣谢博主IC 1396给我答疑解惑哈哈哈哈哈,果然我还是太菜了~~~成熟太难了😭

今朝已然成为过去,明日依然向往未来!我是小荔枝,在技术成长的路上与你相伴,码文不易,麻烦举起小爪爪点个赞吧哈哈哈~~~ 比心心♥~~~

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
算法与数据结构它们分别涵盖了以下主要内容: 数据结构(Data Structures): 逻辑结构:描述数据元素之间的逻辑关系,如线性结构(如数组、链表)、树形结构(如二叉树、堆、B树)、图结构(有向图、无向图等)以及集合和队列等抽象数据类型。 存储结构(物理结构):描述数据在计算机中如何具体存储。例如,数组的连续存储,链表的动态分配节点,树和图的邻接矩阵或邻接表表示等。 基本操作:针对每种数据结构,定义了一系列基本的操作,包括但不限于插入、删除、查找、更新、遍历等,并分析这些操作的时间复杂度和空间复杂度。 算法: 算法设计:研究如何将解决问题的步骤形式化为一系列指令,使得计算机可以执行以求解问题。 算法特性:包括输入、输出、有穷性、确定性和可行性。即一个有效的算法必须能在有限步骤内结束,并且对于给定的输入产生唯一的确定输出。 算法分类:排序算法(如冒泡排序、快速排序、归并排序),查找算法(如顺序查找、二分查找、哈希查找),图论算法(如Dijkstra最短路径算法、Floyd-Warshall算法、Prim最小生成树算法),动态规划,贪心算法,回溯法,分支限界法等。 算法分析:通过数学方法分析算法的时间复杂度(运行时间随数据规模增长的速度)和空间复杂度(所需内存大小)来评估其效率。 学习算法与数据结构不仅有助于理解程序的内部工作原理,更能帮助开发人员编写出高效、稳定和易于维护的软件系统。
逻辑结构:描述数据元素之间的逻辑关系,如线性结构(如数组、链表)、树形结构(如二叉树、堆、B树)、图结构(有向图、无向图等)以及集合和队列等抽象数据类型。 存储结构(物理结构):描述数据在计算机中如何具体存储。例如,数组的连续存储,链表的动态分配节点,树和图的邻接矩阵或邻接表表示等。 基本操作:针对每种数据结构,定义了一系列基本的操作,包括但不限于插入、删除、查找、更新、遍历等,并分析这些操作的时间复杂度和空间复杂度。 算法: 算法设计:研究如何将解决问题的步骤形式化为一系列指令,使得计算机可以执行以求解问题。 算法特性:包括输入、输出、有穷性、确定性和可行性。即一个有效的算法必须能在有限步骤内结束,并且对于给定的输入产生唯一的确定输出。 算法分类:排序算法(如冒泡排序、快速排序、归并排序),查找算法(如顺序查找、二分查找、哈希查找),图论算法(如Dijkstra最短路径算法、Floyd-Warshall算法、Prim最小生成树算法),动态规划,贪心算法,回溯法,分支限界法等。 算法分析:通过数学方法分析算法的时间复杂度(运行时间随数据规模增长的速度)和空间复杂度(所需内存大小)来评估其效率。 学习算法与数据结构不仅有助于理解程序的内部工作原理,更能帮助开发人员编写出高效、稳定和易于维护的软件系统。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值