单链表的定义(数据结构与算法)

news2025/4/16 22:04:30

单链表的定义

在这里插入图片描述

单链表是一种常见的数据结构,用于存储元素的序列。它由一系列节点组成,每个节点包含一个数据元素和一个指向下一个节点的引用(指针)。单链表中的节点之间通过指针连接起来,形成一个线性结构。单链表是一种简单但灵活的数据结构,常用于实现队列、堆栈和图等其他高级数据结构。

在这里插入图片描述

单链表的特点是每个节点只有一个指针,指向下一个节点,而最后一个节点的指针指向空(null)。这意味着可以从链表的头节点开始,逐个访问每个节点,直到到达链表的末尾。

在这里插入图片描述

一个单链表包含一个头节点和一些后续的节点。头节点是链表的起点,它不存储任何实际的数据,只是用来标识链表的开始。头节点的指针指向链表中的第一个实际节点,而每个节点的指针则指向下一个节点。

通过这种指针链接,可以在链表中插入、删除和查找元素。插入元素时,只需要修改相应节点的指针,将新的节点插入到链表中的合适位置。删除元素时,需要修改前一个节点的指针,使其指向删除节点的下一个节点,然后将删除节点的内存空间释放。查找元素时,可以从头节点开始沿着指针依次访问链表,直到找到目标元素或到达链表的末尾。

单链表在某些场景下的操作效率较高,例如插入和删除操作,因为只需要修改指针而不需移动大量元素。然而,单链表的缺点是访问特定位置的元素较慢,需要从头节点开始遍历整个链表。此外,单链表不支持直接反向遍历,因为只有每个节点的下一个节点的指针,没有指向前一个节点的指针。

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

不带头结点的单链表在这里插入图片描述

带头结点的单链表

在这里插入图片描述

以下是一个完整的单链表的C++代码示例:

#include <iostream>

// 定义链表节点结构体
struct Node {
    int data;       // 存储节点的数据
    Node* next;     // 指向下一个节点的指针
};

// 定义链表类
class LinkedList {
private:
    Node* head;     // 头节点指针

public:
    // 构造函数,初始化链表为空
    LinkedList() : head(nullptr) {}

    // 在链表末尾插入新节点
    void insert(int value) {
        // 创建新节点
        Node* newNode = new Node;
        newNode->data = value;
        newNode->next = nullptr;
        
        // 如果链表为空,将新节点作为头节点
        if (head == nullptr) {
            head = newNode;
        } else {
            // 找到链表末尾的节点
            Node* current = head;
            while (current->next != nullptr) {
                current = current->next;
            }
            // 将新节点插入到末尾
            current->next = newNode;
        }
    }

    // 在指定位置插入新节点
    void insertAt(int value, int position) {
        // 创建新节点
        Node* newNode = new Node;
        newNode->data = value;
        newNode->next = nullptr;

        // 如果插入位置是头部
        if (position == 0) {
            newNode->next = head;
            head = newNode;
        } 
        // 如果插入位置不是头部
        else {
            int count = 0;
            Node* current = head;
            Node* prev = nullptr;

            // 找到插入位置的节点
            while (current != nullptr && count < position) {
                prev = current;
                current = current->next;
                count++;
            }

            // 在插入位置插入新节点
            prev->next = newNode;
            newNode->next = current;
        }
    }

    // 删除指定节点
    void remove(int value) {
        // 如果链表为空,直接返回
        if (head == nullptr) {
            return;
        }

        // 如果要删除的节点是头节点
        if (head->data == value) {
            Node* temp = head;
            head = head->next;
            delete temp;
            return;
        }

        // 查找要删除节点的前驱节点
        Node* current = head;
        Node* prev = nullptr;

        while (current != nullptr && current->data != value) {
            prev = current;
            current = current->next;
        }

        // 如果找到要删除的节点
        if (current != nullptr) {
            prev->next = current->next;
            delete current;
        }
    }

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

int main() {
    // 创建链表对象
    LinkedList list;

    // 在链表末尾插入节点
    list.insert(1);
    list.insert(2);
    list.insert(3);

    // 打印链表
    std::cout << "链表: ";
    list.printList();

    // 在指定位置插入节点
    list.insertAt(4, 2);

    // 打印链表
    std::cout << "链表: ";
    list.printList();

    // 删除节点
    list.remove(2);

    // 打印链表
    std::cout << "链表: ";
    list.printList();

    return 0;
}

在这里插入图片描述

单链表的带头结点和不带头结点的区别在于是否在链表的开头添加一个额外的头结点。

  • 不带头结点的单链表:

不带头结点的单链表直接将第一个节点作为链表的头节点。
特点是第一个节点存储数据,并且没有指向前一个节点的指针。
删除头节点时需要特殊处理,需要更新头指针。

  • 带头结点的单链表:

带头结点的单链表在链表开头添加一个额外的头结点,头结点的数据域可以不存储实际数据。
头结点的作用是使得链表的第一个节点与其他节点的操作一致,简化链表操作。
头结点的指针域指向链表的第一个节点,方便遍历和插入。
删除头节点时可以直接将头指针指向下一个节点。

带头结点的单链表更常用,它使得链表的操作更加简单一致,避免了一些边界情况的特殊处理,更加方便处理链表的插入、删除等操作。同时,带头结点的单链表还可以避免链表为空的特殊情况的处理。

知识点回顾脉络

在这里插入图片描述

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

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

相关文章

【C++进阶之路】第三篇:二叉搜索树 kv模型

文章目录 一、二叉搜索树1.二叉搜索树概念2.二叉搜索树操作3.二叉搜索树的实现 二、二叉搜索树的应用1.kv模型2.kv模型的实现 三、 二叉搜索树的性能分析 一、二叉搜索树 1.二叉搜索树概念 二叉搜索树又称二叉排序树&#xff0c;它或者是一棵空树&#xff0c;或者是具有以下性…

使用 kind 集群实现 all-in-one 在线安装 DCE 5.0 社区版

文章目录 一、什么是DCE 5.0二、部署先决条件三、创建云服务器实例3.1 实例节点配置[最低配置要求]3.2 远程连接云实例3.3 更新系统 四、安装Docker-CE五、使用 Kind 搭建 Kubernetes 集群六、安装依赖包6.1 helm安装6.2 skopeo安装6.3 kubectl安装6.4 yq安装 七、安装 DCE 5.0…

软考系列(系统架构师)- 2014年系统架构师软考案例分析考点

试题一 软件架构&#xff08;MYC 架构、扩展接口模式&#xff09; MVC架构风格最初是Smalltalk-80中用来构建用户界面时采用的架构设计风格。其中M代表模型&#xff08;Model)&#xff0c;V代表视图&#xff08;View)&#xff0c;C代表控制器&#xff08;Controller)。在该风格…

Transformers实战(一)快速入门命名实体识别、多项选择

Transformers实战&#xff08;一&#xff09;快速入门命名实体识别、多项选择 1、命名实体识别(NER) 1.1 命名实体识别简介 1.1.1 NER数据标注体系 命名实体识别(Named Entity Recognition&#xff0c;简称NER)是指识别文本中具有特定意义的实体&#xff0c;主要包括人名、…

【管理运筹学】第 10 章 | 排队论(4,系统容量有限制和顾客源有限的情形)

文章目录 引言一、系统的容量有限制&#xff08; M / M / 1 / N / ∞ M/M/1/N/\infty M/M/1/N/∞&#xff09;二、顾客源为有限的情形&#xff08; M / M / 1 / ∞ / m M/M/1/\infty/m M/M/1/∞/m&#xff09;写在最后 引言 了解了标准的 M / M / 1 M/M/1 M/M/1 模型后&#…

[UDS] --- DiagnosticSessionControl 0x10 service

1 会话 $10包含3个子功能&#xff0c;01 Default默认会话&#xff0c;02 Programming编程会话&#xff0c;03 Extended扩展会话&#xff0c;ECU上电时&#xff0c;进入的是默认会话&#xff08;Default&#xff09;。 为什么设计三个会话模式呢&#xff1f;因为权限问题。默认…

华为eNSP配置专题-路由策略的配置

文章目录 华为eNSP配置专题-路由策略的配置0、概要介绍1、前置环境1.1、宿主机1.2、eNSP模拟器 2、基本环境搭建2.1、终端构成和连接2.2、终端的基本配置 3、配置路由策略3.1、目标3.2、配置路由策略 华为eNSP配置专题-路由策略的配置 0、概要介绍 路由策略就是通过一系列工具…

Java SE 学习笔记(十四)—— IO流(2)

目录 1 字节流1.1 字节流写数据1.1.1 创建字节输出流对象1.1.2 字节流写数据 1.2 字节流读数据1.2.1 创建字节输入流对象1.2.2 字节流读数据 1.3 字节流复制文件1.4 流的刷新与关闭1.5 资源释放方式1.5.1 try-catch-finally1.5.2 try-with-resource 2 字符流2.1 字符流概述2.2 …

Spring中Bean的作用域

目录 一、什么是Bean的作用域 二、Scope注解 三、Bean的6种作用域 3.1 singleton单例模式 3.2 prototype 原型模式 3.3 request 3.4 session 3.5 application 3.6 websocket 一、什么是Bean的作用域 在之前学习的过程中&#xff0c;我们把作用域定义为&#xff1a;限定程序中变…

关于数字化转型的know how

关于定义——到底什么是“数字化转型”&#xff1f; 关于价值——数字化转型对企业到底有多重要&#xff1f; 关于框架——企业数字化转型的框架必备要素有哪些&#xff1f; 关于执行——企业数字化转型到底怎么做&#xff1f; 一、什么是数字化转型&#xff1f; 现在各种…

Flink将数据写入MySQL(JDBC)

一、写在前面 在实际的生产环境中&#xff0c;我们经常会把Flink处理的数据写入MySQL、Doris等数据库中&#xff0c;下面以MySQL为例&#xff0c;使用JDBC的方式将Flink的数据实时数据写入MySQL。 二、代码示例 2.1 版本说明 <flink.version>1.14.6</flink.version…

2000-2021年上市公司内部薪酬差距数据(原始数据+计算代码Stata do文档+计算结果)

2000-2021年上市公司内部薪酬差距数据&#xff08;原始数据计算代码Stata do文档计算结果&#xff09; 1、时间&#xff1a;2000-2021年 2、来源&#xff1a;上市公司年报 3、指标&#xff1a; 原始数据指标&#xff1a;code、year、证券代码、应付职工薪酬、员工人数、支付…

美国IP代理如何获取?适用于哪些场景?

美国代理IP可以是静态&#xff08;不会改变&#xff09;或动态&#xff08;周期性更改&#xff09;&#xff0c;并且可以由专业的代理服务提供商提供。不同的代理IP服务提供商可能提供不同类型的代理&#xff0c;包括数据中心代理、住宅代理和移动代理&#xff0c;以满足不同用…

RT-Thread 7. RT-Thread Studio ENV修改MCU型号

1. 修改MCU型号 2.在ENV界面输入 scons -c scons --dist3. dist下为更新后完整源代码 4.导入RT-Thread Studio 发现GD32F330已经生效了。 5. 自己编写startup_gd32f3x0.S&#xff0c;准确性待验证 ;/* ; * Copyright (c) 2006-2021, RT-Thread Development Team ; * ; * SPD…

Vue组件样式设置,解决样式冲突问题

如果我们在不同的组件内&#xff0c;使用相同的类名&#xff0c;就会发生样式的冲突&#xff0c;使用后引入的组件中的样式&#xff1a; 一、scoped属性 在一个组件的style标签上添加scoped属性&#xff0c;该组件的所有样式都是该组件独有的&#xff0c;即使其他组件中有相同…

详解傅立叶变换,看这一文足矣!

从听到傅立叶变换这个名词后到现在已经四年了&#xff0c;这次终于对傅立叶变换有了一个基本的初步了解。记录一下&#xff0c;这个傅立叶变换也同时记录了我本科到研究生的四年&#xff0c;一路以来跌跌撞撞&#xff0c;没想到最后还是入了图像的坑 数字图像处理——傅立叶变换…

freeRTOS内部机制——创建任务的内部细节

创建任务的两个核心&#xff1a;栈和任务结构体 函数运行过程中的局部变量保存在哪里&#xff1f;他自己的栈中 任务被切换过后&#xff0c;在切换的瞬间&#xff0c;哪些寄存器的值保存在哪里&#xff1f;保存在任务结构体中 在任务创建函数中&#xff0c;会malloc动态分配…

【Javascript】函数隐藏参数ar

function test(a,b,c){console.log(abc);}test(1,2,3);这里的形参有三个分别是a&#xff0c;b&#xff0c;c分别对应实参1&#xff0c;2&#xff0c;3 假如在调用函数的时候多传入几个实参会怎么样&#xff1f; function test(a,b,c){console.log(arguments);console.log(a…

吃瓜教程3|决策树

ID3算法 假定当前样本集合D中第k类样本所占比例为pk&#xff0c;则样本集合D的信息熵定义为 信息增益 C4.5算法 ID3算法存在一个问题&#xff0c;就是偏向于取值数目较多的属性&#xff0c;因此C4.5算法使用了“增益率”&#xff08;gain ratio&#xff09;来选择划分属性 CA…

第四章 文件管理 六、文件的基本操作

目录 一、创建文件(create系统调用) 1、进行Create系统调用时&#xff0c;需要提供的几个主要参数: 2、操作系统在处理Create系统调用时&#xff0c;主要做了两件事: 二、删除文件(delete系统调用) 1、进行Delete系统调用时&#xff0c;需要提供的几个主要参数: 2、操作系…