数据结构-链表-第二天

结合leetcode学习c++
链表比数组更易增加和删除数据,但访问速度更慢
在这里插入图片描述

定义

链表(linked list)是一种线性数据结构,其中的每个元素都是一个节点对象,各个节点通过“引用”相连接。
引用记录了下一个节点的内存地址,通过它可以从当前节点访问到下一个节点。

在这里插入图片描述

在这里插入图片描述

1 单向链表通常用于实现栈、队列、哈希表和图等数据结构。

栈与队列:当插入和删除操作都在链表的一端进行时,它表现的特性为先进后出,对应栈;当插入操作在链表的一端进行,删除操作在链表的另一端进行,它表现的特性为先进先出,对应队列。
哈希表:链式地址是解决哈希冲突的主流方案之一,在该方案中,所有冲突的元素都会被放到一个链表中。
图:邻接表是表示图的一种常用方式,其中图的每个顶点都与一个链表相关联,链表中的每个元素都代表与该顶点相连的其他顶点。

2 双向链表常用于需要快速查找前一个和后一个元素的场景。

高级数据结构:比如在红黑树、B 树中,我们需要访问节点的父节点,这可以通过在节点中保存一个指向父节点的引用来实现,类似于双向链表。
浏览器历史:在网页浏览器中,当用户点击前进或后退按钮时,浏览器需要知道用户访问过的前一个和后一个网页。双向链表的特性使得这种操作变得简单。
LRU 算法:在缓存淘汰(LRU)算法中,我们需要快速找到最近最少使用的数据,以及支持快速添加和删除节点。这时候使用双向链表就非常合适。

3 环形链表常用于需要周期性操作的场景,比如操作系统的资源调度。

时间片轮转调度算法:在操作系统中,时间片轮转调度算法是一种常见的 CPU 调度算法,它需要对一组进程进行循环。每个进程被赋予一个时间片,当时间片用完时,CPU 将切换到下一个进程。这种循环操作可以通过环形链表来实现。
数据缓冲区:在某些数据缓冲区的实现中,也可能会使用环形链表。比如在音频、视频播放器中,数据流可能会被分成多个缓冲块并放入一个环形链表,以便实现无缝播放。

1 c++中的单链表

在 C++ 中,单链表通常是由一系列节点组成的,每个节点包含两个部分:数据部分 (val) 和指向下一个节点的指针 (next)。

单链表结构体定义

struct SinglyListNode {int val;       // 数据域,存储节点的值SinglyListNode *next; // 指针域,指向下一个节点SinglyListNode(int x) : val(x), next(NULL) {} // 构造函数,初始化节点
};

成员变量

  1. val: 用于存储节点的值。在这个例子中,val 是一个 int 类型的变量,但也可以是其他类型。
  2. next: 用于存储指向链表中下一个节点的指针。初始化为 NULL 表示这是一个新创建的节点,还没有被链接到链表中。

构造函数

  1. SinglyListNode(int x): 这是一个构造函数,用于创建新的 SinglyListNode 实例。构造函数接收一个整数参数 x 并将其赋值给 val,同时将 next 指针初始化为 NULL

构造函数的初始化列表

构造函数使用了初始化列表的形式来初始化成员变量:

SinglyListNode(int x) : val(x), next(NULL) {}

这里,val(x)next(NULL) 分别初始化 valnext 成员变量。具体来说:

  • val(x): 将构造函数传入的参数 x 赋值给成员变量 val
  • next(NULL): 将成员变量 next 初始化为 NULL,表示这个新创建的节点目前还没有指向下一个节点。

使用示例

下面是一个简单的示例,展示了如何使用 SinglyListNode 结构体创建并操作单向链表:

#include <iostream>
using namespace std;// Definition for singly-linked list.
struct SinglyListNode {int val;SinglyListNode *next;SinglyListNode(int x) : val(x), next(NULL) {}
};int main() {// 创建链表SinglyListNode *head = new SinglyListNode(1); // 创建第一个节点head->next = new SinglyListNode(2);           // 创建第二个节点并连接head->next->next = new SinglyListNode(3);     // 创建第三个节点并连接// 打印链表中的值SinglyListNode *current = head;while (current != NULL) {cout << current->val << " ";current = current->next;}// 释放内存while (head != NULL) {SinglyListNode *temp = head;head = head->next;delete temp;}return 0;
}

输出

1 2 3

创建多个节点并连接

/* 初始化链表 1 -> 3 -> 2 -> 5 -> 4 */
// 初始化各个节点
ListNode* n0 = new ListNode(1);
ListNode* n1 = new ListNode(3);
ListNode* n2 = new ListNode(2);
ListNode* n3 = new ListNode(5);
ListNode* n4 = new ListNode(4);
// 构建节点之间的引用
n0->next = n1;
n1->next = n2;
n2->next = n3;
n3->next = n4;

总结

单链表的定义和构造函数的设计是为了方便创建和操作链表。通过这样的设计,你可以轻松地在链表中插入、删除和查找节点,同时也能够有效地管理内存,避免内存泄漏等问题。

2 双链表

/* 双向链表节点结构体 */
struct ListNode {int val;         // 节点值ListNode *next;  // 指向后继节点的指针ListNode *prev;  // 指向前驱节点的指针ListNode(int x) : val(x), next(nullptr), prev(nullptr) {}  // 构造函数
};

3 环形链表

环形链表(Circular Linked List)是一种特殊类型的链表,其中最后一个节点的指针不是指向 NULL,而是指向链表的头节点,形成一个闭环。这种结构使得遍历链表时可以从任何一个节点开始,并且在到达末尾节点后可以无缝地回到头节点。

环形链表(Circular Linked List)是一种特殊类型的链表,其中最后一个节点的指针不是指向 NULL,而是指向链表的头节点,形成一个闭环。这种结构使得遍历链表时可以从任何一个节点开始,并且在到达末尾节点后可以无缝地回到头节点。

环形链表的基本概念

  1. 节点: 环形链表中的每个节点包含数据和一个指向下一个节点的指针。
  2. 头节点 (Head): 链表的第一个节点,通常用来标识整个链表的开始。
  3. 尾节点 (Tail): 链表的最后一个节点,其指针指向头节点。

环形链表的类型

环形链表可以根据节点间的连接方式分为不同的类型:

  • 单向环形链表 (Singly Circular Linked List): 每个节点只包含一个指向下一个节点的指针。
  • 双向环形链表 (Doubly Circular Linked List): 每个节点包含两个指针,一个指向前一个节点,另一个指向后一个节点。

环形链表的操作

环形链表支持多种操作,包括但不限于:

  1. 插入节点:

    • 头部插入: 在链表的头部添加一个新节点。
    • 尾部插入: 在链表的尾部添加一个新节点。
    • 中间插入: 在指定位置插入一个新节点。
  2. 删除节点:

    • 删除头部节点.
    • 删除尾部节点.
    • 删除中间节点.
  3. 查找节点: 根据给定的值或索引查找对应的节点。

  4. 遍历链表: 由于链表形成闭环,可以方便地从任意节点开始遍历整个链表。

环形链表的优点

  • 方便的遍历: 无需担心遍历到最后一个节点时如何返回头节点的问题。
  • 节省空间: 对于单向环形链表,不需要额外的空间来存储尾节点的指针,因为最后一个节点直接指向头节点。

环形链表的缺点

  • 检测环形: 对于外部用户来说,需要额外的逻辑来确定链表是否已经遍历完整个环。
  • 额外的复杂性: 与普通链表相比,环形链表的插入和删除操作可能需要更多的指针更新。

示例代码

下面是一个使用 C++ 实现单向环形链表的简单示例:

#include <iostream>
using namespace std;// 定义节点结构
struct Node {int data;Node *next;Node(int x) : data(x), next(NULL) {}
};// 定义环形链表类
class CircularLinkedList {
public:Node *head;CircularLinkedList() : head(NULL) {}void append(int data) {Node *newNode = new Node(data);if (!head) {head = newNode;head->next = head;} else {Node *temp = head;while (temp->next != head) {temp = temp->next;}temp->next = newNode;newNode->next = head;}}void prepend(int data) {Node *newNode = new Node(data);if (!head) {head = newNode;head->next = head;} else {Node *temp = head;while (temp->next != head) {temp = temp->next;}newNode->next = head;head = newNode;temp->next = head;}}void deleteNode(int key) {if (!head) {return;}Node *prev = NULL;Node *cur = head;do {if (cur->data == key) {if (cur == head) {Node *temp = head;while (temp->next != head) {temp = temp->next;}head = cur->next;temp->next = head;} else {prev->next = cur->next;}delete cur;return;}prev = cur;cur = cur->next;} while (cur != head);}void printList() {if (!head) {cout << "Empty List" << endl;return;}Node *temp = head;do {cout << temp->data << " ";temp = temp->next;} while (temp != head);cout << endl;}
};int main() {CircularLinkedList cll;cll.append(1);cll.append(2);cll.prepend(0);cll.deleteNode(1);cll.printList();return 0;
}

输出

0 2

总结

环形链表是一种特殊类型的链表,它在最后的节点处闭合成一个环。这种结构在某些应用场景中非常有用,特别是当需要频繁遍历整个链表时。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

windows本地搭建zookeeper和kafka环境

zookeeper 1.1 下载zookeeper 下载地址 随便进一个站点&#xff0c;默认是新版本&#xff0c;旧版本点击archives进入&#xff0c;选择合适的版本下载&#xff0c;本文使用的是3.7.2 下载时候选择apache-zookeeper-3.7.2-bin.tar.gz 格式的&#xff0c;编译后的&#xff0c;解…

centos 虚拟机器刚刚安装没有ip地址的问题

刚刚安装好的虚拟机器&#xff0c;我们通过 ip addr 查看ip发现是这样的 该虚拟机器没有ip地址&#xff0c;那么怎么办 原来是在/etc/sysconfig/network-scripts/ifcfg-ens33中关于网络的配置有问题 ONBOOTno 表示不开启网卡&#xff0c;我们需要将这个值进行修改为yes 当前…

prolog 基础 - 关系和属性

首先进入环境&#xff1b; 看一下一开始的提示符是 ?- &#xff0c;现在可以用write语句输出一些东西&#xff1b; 根据资料&#xff0c;在prolog中&#xff0c; 两个对象之间的关系&#xff0c;使用括号表示。比如&#xff0c;jack的朋友是peter&#xff0c;写成friend(ja…

嵌入式堆栈、ARM寄存器

栈里面存放的内容&#xff1a;局部变量和系统信息&#xff0c;函数调用链路也是系统信息的一环 ARM寄存器 LR&#xff1a;程序跳转的时候&#xff0c;返回到的地址就保存到此处 PC&#xff1a;程序计数器&#xff0c;pc 要执行的下一条指令地址&#xff0c;就存放在此处&#…

QT error: undefined reference to `vtable for Net‘

报错 C:\Users\Administrator\Desktop\VideoHill\GikISearch\net.cpp:4: error: undefined reference to vtable for Net 以下是两个可能错误原因 1&#xff0c;未定义Q_OBJECT 宏 在头文件中加上 加上#include <QObject>&#xff0c; 改写继承QObject 和定义宏 …

Unity3D 遍历预制体

Unity3D 遍历预制体进行批量化处理。 遍历预制体 有时候&#xff0c;我们需要对一些预制体资源进行批量化处理&#xff0c;如果每一个预制体都手动处理&#xff0c;就会耗费很多时间精力&#xff0c;也容易出错。 我们可以写一个脚本遍历预制体&#xff0c;对预制体进行修改…

电脑U口管理软件分享|U口管理软件哪个好?

电脑U口&#xff08;即USB端口&#xff09;管理软件是保护电脑安全、防止数据泄露和恶意软件入侵的重要工具。 在选择U口管理软件时&#xff0c;需要考虑其功能、易用性、安全性以及是否满足个人或企业的具体需求。以下是一些值得推荐的电脑U口管理软件及其特点&#xff1a; 1…

白酒与旅行日记:探索世界,品味美酒

在旅行的道路上&#xff0c;我们追寻着不同的风景&#xff0c;体验着不同的文化。而白酒&#xff0c;作为中国文化的瑰宝&#xff0c;也在这一旅途中扮演着不同的角色。它不仅仅是一种饮品&#xff0c;更是一种情感的寄托&#xff0c;一种文化的传承。今天&#xff0c;就让我们…

.net maui安卓开发中使用明文传输(一)

背景:最近在做一个pad上的项目,目的是执行每日点检功能(就是检查设备的各项保养指标);前期用HBuilder做了一个,但是现场的触摸屏选用的是TouchPie 安卓版本是6.0版本,上次开发的软件可以在安卓7.0上完美兼容,但由于触摸屏安卓版本太低不能兼容;询问厂商才知道这款触摸…

8.21-部署eleme项目

1.设置主从从mysql57服务器 &#xff08;1&#xff09;配置主数据库 [rootmsater_5 ~]# systemctl stop firewalld[rootmsater_5 ~]# setenforce 0[rootmsater_5 ~]# systemctl disable firewalldRemoved symlink /etc/systemd/system/multi-user.target.wants/firewalld.serv…

PV、UV、IP:网站流量分析的关键指标

原文&#xff1a;PV、UV、IP&#xff1a;网站流量分析的关键指标 - 孔乙己大叔 (rebootvip.com) 摘要&#xff1a; 在浩瀚的互联网海洋中&#xff0c;PV&#xff08;Page View&#xff0c;页面浏览量&#xff09;、UV&#xff08;Unique Visitor&#xff0c;独立访客数…

基于改进YOLOv8的景区行人检测算法

贵向泉, 刘世清, 李立, 秦庆松, 李唐艳. 基于改进YOLOv8的景区行人检测算法[J]. 计算机工程, 2024, 50(7): 342-351. DOI: 10.19678/j.issn.10 原文链接如下&#xff1a;基于改进YOLOv8的景区行人检测算法https://www.ecice06.com/CN/rich_html/10.19678/j.issn.1000-3428.006…

墨者学院 手工注入题解(oracle数据库)

简介 Oracle 数据库系统&#xff0c;是美国ORACLE公司&#xff08;甲⻣⽂&#xff09;提供的以分布式数据库为核⼼的⼀组软件 产品。是⽬前世界上使⽤最为⼴泛的&#xff0c;数据库管理系统。 以下是手工注入的流程&#xff1a; 1、判断注入点 使用 and 11 进行拼接 2、确定…

Unity实现棋盘方格

本文参考&#xff1a;p1_哔哩哔哩_bilibili 一、精要提炼 1、Button自带的白色底图是圆角的&#xff0c;Image组件自带的白色底图是方角的。 2、2D中Instantiate指定的位置为屏幕坐标系的位置&#xff0c;左下角为(0,0) 3、求某个组件的位置&#xff1a;xx.transform.posi…

【数据结构4】树的实例-模拟文件系统、二叉树的遍历(先序遍历、中序遍历、后序遍历、层次遍历)

1 树和二叉树 2 树的实例-模拟文件系统 3 二叉树 3.1 二叉树的遍历 二叉树的先序遍历 二叉树的中序遍历 二叉树的后序遍历 二叉树的层次遍历 1 树 树是一种数据结构 比如:目录结构 树是一种可以递归定义的数据结构树是由n个节点组成的集合:如果n0&#xff0c;那这是一棵空树;如…

[C++]一、C++基础编程

G:\Cpp\2023版C教程 C语言程序设计 第一部分 基础篇 一、什么是C 1.1 C 简介 C 是一门非常经典的高级编程语言。顾名思义&#xff0c;C可以看做是C语言的增强版&#xff0c;在C的基础上扩展了更多的功能&#xff1b;最主要的扩展&#xff0c;就是面向对象和泛型编程。 因…

buuctf [MRCTF2020]hello_world_go

前言 学习笔记 这题签到&#xff01; 64IDA打开。 查找字符串发现什么都没有。。。 没事 搜索main()【不知道go语言有没有&#xff0c;先搜索再说】 随便点开一个。 有flag格式&#xff0c;提交看看呗。 成了&#xff0c;签到。 flag{hello_world_gogogo} 题外话&#xff0c;…

Day18_Netty

文章目录 NettyIO 模型Java有哪些数据类型零拷贝深拷贝和浅拷贝的区别是什么?BIO、NIO、AIO的区别是什么?Netty 是什么?Netty 基于 NIO,那为啥不直接用 NIO 呢? / 为什么要用 Netty?Netty 应用场景了解么?那些开源项目用到了 Netty?Netty的核心组件是什么?请解释Netty…

Golang | Leetcode Golang题解之第371题两整数之和

题目&#xff1a; 题解&#xff1a; func getSum(a, b int) int {for b ! 0 {carry : uint(a&b) << 1a ^ bb int(carry)}return a }

汇编知识MOV,MRS,MSR,PUSH和POP指令

处理器做得最多的事情就是在处理器内部来回的进行数据传递 1) 将数据从一个寄存器传递到另一个寄存器中 2) 将数据从一个寄存器传递到特殊寄存器&#xff0c;例如CPSR,SPSR寄存器 3) 将立即数传递到寄存器。 数据传输常用的三个指令&#xff1a;MOV,MRS,MSR指令 常用的…