数据结构链表入门指南 链表基本代码实现以及测试步骤

链表介绍

链表是一种数据结构,它由一系列节点组成,每个节点包含数据部分和指向下一个节点的指针。链表的基本特性包括:

  1. 动态大小:链表的大小可以根据需要动态调整,不像数组那样需要事先定义固定大小。
  2. 节点连接:每个节点通过指针连接到下一个节点,从而形成一个链状结构。
  3. 灵活插入和删除:在链表中插入和删除节点通常比数组更高效,因为这些操作不需要移动其他元素。

链表的类型

  1. 单向链表(Singly Linked List):每个节点包含一个指针,指向链表中的下一个节点。最后一个节点的指针指向 null,表示链表的结束。

  2. 双向链表(Doubly Linked List):每个节点包含两个指针,一个指向前一个节点,一个指向下一个节点。这样可以在两个方向上遍历链表。

  3. 循环链表(Circular Linked List):链表的最后一个节点指向第一个节点,形成一个循环结构。它可以是单向或双向的。

  4. 双向循环链表(Doubly Circular Linked List):结合了双向链表和循环链表的特性,既可以在两个方向上遍历,又形成了一个循环结构。

链表的基本操作
  1. 插入:在链表的任意位置插入新节点。
  2. 删除:从链表中删除指定节点。
  3. 查找:在链表中查找指定值的节点。
  4. 遍历:访问链表中所有节点,通常用来打印或处理数据。
  5. 更新:修改链表中某个节点的数据。
C++ 实现链表

下面是一个包含基本操作的链表实现代码:

#include <iostream>

class Node {
public:
    int data;
    Node* next;
    Node(int val) : data(val), next(nullptr) {}
};

class LinkedList {
private:
    Node* head;
public:
    LinkedList() : head(nullptr) {}

    // 插入节点到链表头部
    void insertAtHead(int val) {
        Node* newNode = new Node(val);
        newNode->next = head;
        head = newNode;
    }

    // 插入节点到链表尾部
    void insertAtTail(int val) {
        Node* newNode = new Node(val);
        if (!head) {
            head = newNode;
            return;
        }
        Node* temp = head;
        while (temp->next) {
            temp = temp->next;
        }
        temp->next = newNode;
    }

    // 删除指定值的节点
    void deleteValue(int val) {
        if (!head) return;
        if (head->data == val) {
            Node* temp = head;
            head = head->next;
            delete temp;
            return;
        }
        Node* temp = head;
        while (temp->next && temp->next->data != val) {
            temp = temp->next;
        }
        if (temp->next) {
            Node* nodeToDelete = temp->next;
            temp->next = temp->next->next;
            delete nodeToDelete;
        }
    }

    // 查找指定值的节点
    bool search(int val) {
        Node* temp = head;
        while (temp) {
            if (temp->data == val) return true;
            temp = temp->next;
        }
        return false;
    }

    // 遍历链表并打印数据
    void traverse() {
        Node* temp = head;
        while (temp) {
            std::cout << temp->data << " -> ";
            temp = temp->next;
        }
        std::cout << "nullptr" << std::endl;
    }

    ~LinkedList() {
        while (head) {
            Node* temp = head;
            head = head->next;
            delete temp;
        }
    }
};

int main() {
    LinkedList list;

    // 插入数据
    list.insertAtHead(1);
    list.insertAtHead(2);
    list.insertAtTail(3);
    list.insertAtTail(4);

    // 遍历链表
    std::cout << "Linked List: ";
    list.traverse();

    // 查找数据
    std::cout << "Searching for 3: " << (list.search(3) ? "Found" : "Not Found") << std::endl;

    // 删除数据
    list.deleteValue(2);
    std::cout << "After deleting 2, Linked List: ";
    list.traverse();

    return 0;
}

代码说明

  1. Node 类:定义了链表节点的结构。
  2. LinkedList 类
    • insertAtHead(int val):在链表头部插入新节点。
    • insertAtTail(int val):在链表尾部插入新节点。
    • deleteValue(int val):删除链表中第一个匹配值的节点。
    • search(int val):查找链表中是否存在指定值的节点。
    • traverse():遍历并打印链表所有节点的数据。
    • 析构函数~LinkedList():释放链表占用的内存。

编译代码

使用 C++ 编译器(如 g++)编译这个文件。打开终端或命令提示符,执行以下命令:

g++ -o linked_list linked_list.cpp -o linked_list

指定输出文件的名称为 linked_list。
linked_list.cpp 是你保存的代码文件名。

代码输出结果

Linked List: 2 -> 1 -> 3 -> 4 -> nullptr
Searching for 3: Found
After deleting 2, Linked List: 1 -> 3 -> 4 -> nullptr

链表与其他数据结构的优缺点

优点
  1. 动态大小:链表可以动态分配内存,避免了固定大小数组的限制。
  2. 高效插入和删除:在链表中插入和删除节点比数组高效(O(1)时间复杂度),特别是在头部或中间位置。
  3. 无需预定义大小:链表不需要定义固定的大小,可以根据需要扩展。
缺点
  1. 内存开销:每个节点需要额外的指针,导致比数组占用更多的内存。
  2. 随机访问困难:链表不支持直接索引,必须从头部开始逐一遍历(O(n)时间复杂度)。
  3. 访问速度慢:由于节点分散在内存中,链表的遍历比数组慢。

总结

链表是一种灵活且高效的动态数据结构,适用于需要频繁插入和删除操作的应用场景。尽管它的内存开销和访问速度可能不如数组,但它的动态特性和高效的插入/删除操作使其在某些情况下非常有用。了解链表的基本操作和特性,可以帮助在不同的应用场景中选择合适的数据结构。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++,std::queue 详解

文章目录 1. 概述2. 包含头文件3. 基本操作3.1 构造函数3.2 赋值操作3.3 成员函数 4. 迭代器5. 示例6. 注意事项参考 1. 概述 std::queue 是 C 标准模板库&#xff08;STL&#xff09;中的一个容器适配器&#xff0c;它提供了一种先进先出&#xff08;FIFO&#xff09;的数据结…

[数据集][目标检测]木材缺陷检测数据集VOC+YOLO格式2383张10类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;2383 标注数量(xml文件个数)&#xff1a;2383 标注数量(txt文件个数)&#xff1a;2383 标注…

网络安全入门教程(非常详细)从零基础入门到精通_网路安全 教程

前言 1.入行网络安全这是一条坚持的道路&#xff0c;三分钟的热情可以放弃往下看了。2.多练多想&#xff0c;不要离开了教程什么都不会了&#xff0c;最好看完教程自己独立完成技术方面的开发。3.有时多百度&#xff0c;我们往往都遇不到好心的大神&#xff0c;谁会无聊天天给…

线性数据结构的基本概念(数组,链表,栈,队列)

数组 数组由相同类型的元素组成&#xff0c;使用一块连续的内存来存储。 数组的特点是&#xff1a; 1.利用索引进行访问 2.容量固定 3.使用一块连续的内存来存储 各种操作的时间复杂度&#xff1a; 查找/修改&#xff1a;O&#xff08;1&#xff09;//访问特定位置的元素 插入…

[鹏城杯 2022]简单的php

题目源代码 <?phpshow_source(__FILE__); $code $_GET[code]; if(strlen($code) > 80 or preg_match(/[A-Za-z0-9]|\|"||\ |,|\.|-|\||\/|\\|<|>|\$|\?|\^|&|\|/is,$code)){die( Hello); }else if(; preg_replace(/[^\s\(\)]?\((?R)?\)/, , $code…

Qt实现tcp协议

void Widget::readyRead_slot() {//读取服务器发来的数据QByteArray msg socket->readAll();QString str QString::fromLocal8Bit(msg);QStringList list str.split(:);if(list.at(0) userName){QString str2;for (int i 1; i < list.count(); i) {str2 list.at(i);…

使用DOM破坏启动xss

目录 实验环境&#xff1a; 分析&#xff1a; 找破坏点&#xff1a; 查看源码找函数&#xff1a; 找到了三个方法&#xff0c;loadComments、escapeHTM 、displayComments loadComments escapeHTM displayComments&#xff1a; GOGOGO 实验环境&#xff1a; Lab: Exp…

JLMSR超分算法说明和效果

一、简介 JLMSR是基于加权概率模型构造的一种超分算法&#xff0c;属于传统超分&#xff0c;无需训练&#xff0c;适合硬件化。与传统超分的插值方案最大区别在于基于16*16的块进行上下文概率统计&#xff0c;结合权重进行插值。目前该插值方案已经线性化和整数化&#xff0c;…

加油卡APP系统,探索新的市场机遇

当下&#xff0c;汽车已经成为了不可缺少的出行工具&#xff0c;汽车加油也成为了必要的环节。加油卡作为一种高效、便捷的加油方式&#xff0c;具有非常的市场发展空间&#xff0c;也成为了新的创业方式&#xff01; 在网络时代中&#xff0c;加油卡APP的开发大大减少了用户在…

NVF04M录音芯片在宠物喂食器的应用:录音播放功能,内置SPI闪存

在现代社会中&#xff0c;宠物已经成为人们生活中的一部分&#xff0c;而宠物喂食器作为宠物养护的重要工具&#xff0c;也越来越受到人们的关注。为了满足人们对宠物喂食器的多样化需求&#xff0c;九芯电子供应商研发了一款NVF04M录音芯片。它在宠物喂食器中的作用主要是提供…

[机器学习]--线性回归算法

线性回归算法原理 线性关系在生活中有很多案例: 摄氏度和华氏度的转化: F C ⋅ 9 5 32 F C \cdot\frac{9}{5}32 FC⋅59​32学科最终成绩的计算: 最终成绩 0.3 \times 平时成绩 0.7 \times 期末成绩 线性回归(Linear regression)就是利用回归函数对一个或多个自变量…

WEB渗透免杀篇-Golang免杀

往期文章 WEB渗透免杀篇-免杀工具全集-CSDN博客 WEB渗透免杀篇-加载器免杀-CSDN博客 WEB渗透免杀篇-分块免杀-CSDN博客 WEB渗透免杀篇-Powershell免杀-CSDN博客 WEB渗透免杀篇-Python源码免杀-CSDN博客 WEB渗透免杀篇-C#源码免杀-CSDN博客 WEB渗透免杀篇-MSFshellcode免杀…

土壤墒情固定监测站的工作原理

TH-GTS03土壤墒情固定监测站是一种专门用于监测土壤墒情信息的设备&#xff0c;它通过一系列精密的传感器和数据处理系统&#xff0c;实时、准确地获取土壤的水分含量、温度以及其他相关参数&#xff0c;为农业生产、生态保护和水资源管理等提供重要依据。 土壤墒情固定监测站通…

想做好专业儿童研学项目解决方案,建议先看看这篇

大家好&#xff0c;我是爱吐槽也爱分享的“教育&科技跨界老顽童”。今天想跟大家聊聊这几年越来越火的“沉浸式数字化研学”&#xff0c;因为前不久刚刚参与了一个不错的专业儿童研学项目解决方案&#xff0c;有一些心得想要及时分享&#xff0c;尤其是也想搞专业儿童研学项…

vue3 安装element-plus进行一些简单的测试

1、安装element-plus 官网地址&#xff1a;https://element-plus.org/zh-CN/guide/installation.html 2、安装方法&#xff1a; # 选择一个你喜欢的包管理器# NPM npm install element-plus --save# Yarn yarn add element-plus# pnpm pnpm install element-plus 这里我选择…

STM32G474的HRTIM用作时基定时器

STM32G474的HRTIM由7个定时器组成&#xff0c;分别是主定时器&#xff0c;定时器A&#xff0c;定时器B&#xff0c;定时器C&#xff0c;定时器D&#xff0c;定时器E和定时器F&#xff0c;每个定时器均可单独配置&#xff0c;独立工作。每个定时器都有1个独立的计数器和4个独立的…

[基础入门]正向shell和反弹shell

前言 在渗透过程能获取shell是很重要的一点&#xff0c;首先可以使用一些漏洞对ssh和ftp进行攻击获取shell&#xff0c;如果没有这些漏洞可以考虑一下使用正向shell或者是反弹shell。 一、什么是正向shell和反弹shell 其实这个过程是相对的&#xff0c;需要找到一个参考点&a…

使用 Python 绘制词云图的详细教程

如何使用python绘制词云图 词云图&#xff08;Word Cloud&#xff09;是数据可视化中常用的一种技术&#xff0c;通过将文字以不同的大小、颜色和方向排列&#xff0c;以展示文本数据中词汇的频次和重要性。对于文本分析、情感分析、关键词提取等应用&#xff0c;词云图都能够…

【FreeRTOS】队列实验-多设备玩游戏(旋转编码器)

目录 0 前言1 任务1.1 本节源码1.2实验目的1.3实现方案 2 code2.1 创建队列2.2 写队列2.3 创建任务 3 勘误 0 前言 学习视频&#xff1a; 【FreeRTOS入门与工程实践 --由浅入深带你学习FreeRTOS&#xff08;FreeRTOS教程 基于STM32&#xff0c;以实际项目为导向&#xff09;】…

CronTab及定时任务

目录 CronTab及定时任务 一、定时任务的基本原理 二、Cron定时任务 但是 三、其他补充命令 CronTab及定时任务 一、定时任务的基本原理 # 每5秒钟向文本中输出一次时间#for i in {1..10}; do while [ 1 < 2 ]; dodate "%Y-%m-%d %H:%M:%S" >> /opt/lea…