数据结构-链表-第二天

news2024/9/21 20:28:16

结合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.coloradmin.cn/o/2057876.html

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

相关文章

「字符串」前缀函数|KMP匹配:规范化next数组 / LeetCode 28(C++)

概述 为什么大家总觉得KMP难&#xff1f;难的根本就不是这个算法本身。 在互联网上你可以见到八十种KMP算法的next数组定义和模式串回滚策略&#xff0c;把一切都懂得特别混乱。很多时候初学者的难点根本不在于这个算法本身&#xff0c;而是它令人痛苦的百花齐放的定义。 有…

[C++] map、set的 红黑树 封装(一)

标题&#xff1a;[C] map、set的 红黑树 封装 水墨不写bug &#xff08;图片来源于网络&#xff09; 目录 一、红黑树与AVL树的比较&#xff08;为什么容器选择红黑树&#xff09; 二、map、set的封装 1.模板参数 2.红黑树迭代器设计 正文开始&#xff1a; 一、红黑树与AV…

RK3588J正式发布Ubuntu桌面系统,丝滑又便捷!

本文主要介绍瑞芯微RK3588J的Ubuntu系统桌面演示&#xff0c;开发环境如下&#xff1a; U-Boot&#xff1a;U-Boot-2017.09 Kernel&#xff1a;Linux-5.10.160 Ubuntu&#xff1a;Ubuntu20.04.6 LinuxSDK&#xff1a; rk3588-linux5.10-sdk-[版本号] &#xff08;基于rk3…

【GH】【EXCEL】P7: Control

XL Label XL Dropdown XL CHECK BOX XL Button XL Scroller XL Spinner XL ListBox

RocketMQ源码分析 - 环境搭建

RocketMQ源码分析 - 环境搭建 环境搭建源码拉取导入IDEA调试1) 启动NameServer2) 启动Broker3) 发送消息4) 消费消息 环境搭建 依赖工具 JDK&#xff1a;1.8MavenIntellij IDEA 源码拉取 从官方仓库 https://github.com/apache/rocketmq clone或者download源码。 源码目录…

【微服务】微服务组件之Nacos注册中心和配置中心的使用

背景&#xff1a; 在当前的软件架构领域&#xff0c;微服务架构凭借其高度的可扩展性、灵活性和可维护性&#xff0c;已成为企业构建复杂应用的首选。微服务架构通过将应用拆分成一系列小的、独立的服务&#xff0c;实现了服务的解耦和复用&#xff0c;从而提高了应用的可扩展性…

Sass实现网页背景主题切换

Sass 实现网页背景主题切换 前言准备工作一、 简单的两种主题黑白切换1.定义主题2. 添加主题切换功能3. 修改 data-theme 属性 二、多种主题切换1. 定义主题2. 动态生成 CSS 变量1.遍历列表2.遍历映射3.高级用法 3. 设置默认主题4. 切换功能HTML 三、多种主题多种样式切换1. 定…

在 Fedora 上安装 LAMP(Linux、Apache、MySQL、PHP)的方法

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 关于 LAMP LAMP 栈是一组用于启动和运行 Web 服务器的开源软件。该缩写代表 Linux、Apache、MySQL 和 PHP。由于服务器已经在运行 Fedo…

高性能web服务器1

基础 Web 服务简介 Web 服务是互联网的核心组成部分之一&#xff0c;它允许用户通过浏览器访问信息和应用程序。一个基础的 Web 服务通常由 Web 服务器软件、静态网页内容、以及可选的动态内容生成程序组成。 Web 服务器软件 Web 服务器软件是运行在服务器上的程序&#xff…

【Java 数据结构】PriorityQueue介绍

优先级队列 回顾二叉树堆堆是什么堆的实现初始化堆的创建向下调整建堆复杂度插入向上调整建堆复杂度删除 PriorityQueue类介绍PriorityQueue是什么PriorityQueue使用构造方法常用方法 PriorityQueue源码介绍Top-K问题 回顾二叉树 上一次我们简单的了解了二叉树这个数据结构, 但…

每天五分钟深度学习框架pytorch:神经网络工具箱nn的介绍

本文重点 我们前面一章学习了自动求导,这很有用,但是在实际使用中我们基本不会使用,因为这个技术过于底层,我们接下来将学习pytorch中的nn模块,它是构建于autograd之上的神经网络模块,也就是说我们使用pytorch封装好的神经网络层,它自动会具有求导的功能,也就是说这部…

夏晖WMS是什么?夏晖WMS怎么与金蝶云星空进行集成?

在数字化浪潮席卷全球的今天&#xff0c;企业对于业务流程的高效管理和数据集成的需求愈发迫切。夏晖WMS作为一款领先的仓库管理系统&#xff0c;与金蝶云星空ERP的集成成为了众多企业提升管理效率的关键环节。 夏晖WMS是什么? 夏晖WMS是一款由夏晖物流&#xff08;上海&…

Golang | Leetcode Golang题解之第355题设计推特

题目&#xff1a; 题解&#xff1a; type Twitter struct {Tweets []intUserTweets map[int][]intFollows map[int][]intIsFollowMy map[int]bool }/** Initialize your data structure here. */ func Constructor() Twitter {// 每一次实例化的时候&#xff0c;都重新分配一次…

C语言 | Leetcode C语言题解之第354题俄罗斯套娃信封问题

题目&#xff1a; 题解&#xff1a; int cmp(int** a, int** b) {return (*a)[0] (*b)[0] ? (*b)[1] - (*a)[1] : (*a)[0] - (*b)[0]; }int maxEnvelopes(int** envelopes, int envelopesSize, int* envelopesColSize) {if (envelopesSize 0) {return 0;}qsort(envelopes, …

宜佰丰超市进销存管理系统

你好呀&#xff0c;我是计算机学姐码农小野&#xff01;如果有相关需求&#xff0c;可以私信联系我。 开发语言&#xff1a; Java 数据库&#xff1a; MySQL 技术&#xff1a; JavaMysql 工具&#xff1a; IDEA/Eclipse、Navicat、Maven 系统展示 首页 管理员功能模块…

接口测试及常用接口测试工具(postman/jmeter)详解

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 首先&#xff0c;什么是接口呢&#xff1f; 接口一般来说有两种&#xff0c;一种是程序内部的接口&#xff0c;一种是系统对外的接口。 系统对外的接口&#x…

【Alibaba Cola 状态机】重点解析以及实践案例

【Alibaba Cola 状态机】重点解析以及实践案例 1. 状态模式 状态模式是一种行为型设计模式&#xff0c;允许对象在内部状态改变时改变其行为&#xff0c;简单地讲就是&#xff0c;一个拥有状态的context对象&#xff0c;在不同状态下&#xff0c;其行为会发生改变。看起来是改…

Spring项目:文字花园(四)

一.实现登录 传统思路: • 登陆⻚⾯把⽤⼾名密码提交给服务器. • 服务器端验证⽤⼾名密码是否正确, 并返回校验结果给后端 • 如果密码正确, 则在服务器端创建 Session . 通过 Cookie 把 sessionId 返回给浏览器. 问题: 集群环境下⽆法直接使⽤Session. 原因分析: 我们开…

渐变纹理的使用

1、渐变纹理的使用 通过单张纹理和凹凸纹理相&#xff0c;我们知道图片中存储的数据不仅仅可以是颜色数据&#xff0c;还可以是高度、法线数据。 理论上来说&#xff0c;图片中存储的数据我们可以自定义规则&#xff0c;我们可以往图片中存储任何满足 我们需求的数据用于渲染。…

原神4.8版本抽到角色和重点培养数据表

<!DOCTYPE html> <html lang"zh-cn"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>原神4.8版本抽到角色和重点培养数据表</title…