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

单链表的定义

在这里插入图片描述

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

在这里插入图片描述

单链表的特点是每个节点只有一个指针,指向下一个节点,而最后一个节点的指针指向空(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;
}

在这里插入图片描述

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

  • 不带头结点的单链表:

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

  • 带头结点的单链表:

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

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

知识点回顾脉络

在这里插入图片描述

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

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

相关文章

【Elasticsearch】es脚本编程使用详解

目录 一、es脚本语言介绍 1.1 什么是es脚本 1.2 es脚本支持的语言 1.3 es脚本语言特点 1.4 es脚本使用场景 二、环境准备 2.1 docker搭建es过程 2.1.1 拉取es镜像 2.1.2 启动容器 2.1.3 配置es参数 2.1.4 重启es容器并访问 2.2 docker搭建kibana过程 2.2.1 拉取ki…

Git的远程仓库

Git的远程仓库 添加远程仓库从远程库克隆 添加远程仓库 你在本地创建了一个Git仓库后&#xff0c;又想在GitHub创建一个Git仓库&#xff0c;并且让这两个仓库进行远程同步&#xff0c;这样&#xff0c;GitHub上的仓库既可以作为备份&#xff0c;又可以让其他人通过该仓库来协作…

如何在VScode中让printf输出中文

如何在VScode中让printf输出中文&#xff1f; 1、在“Visual Studio Code”图标上右击&#xff0c;弹出对话框。见下图&#xff1a; 2、点击“以管理员身份运行”&#xff0c;得到下图&#xff1a; 3、点击“UTF-8”按钮&#xff0c;得到下图&#xff1a; 4、点击“通过编码重…

Python---练习:使用for循环嵌套实现打印九九乘法表

思考&#xff1a; 外层循环主要用于控制循环的行数&#xff0c;内层循环用于控制列数。 基本语法&#xff1a; # 外层循环 for i in 序列1:# 内层循环for j in 序列2:循环体 序列1 序列2 &#xff0c;就可以是range(1, 10) -----也就是从1&#xff0c;到9。 参考while循环…

【vector题解】杨辉三角 | 删除有序数组中的重复项 | 只出现一次的数字Ⅱ

杨辉三角 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 给定一个非负整数 numRows&#xff0c;生成「杨辉三角」的前 numRows 行。 在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。 示例 1: 输入: numRows 5 输出: [[1],[1,1…

动态规划(记忆化搜索)

AcWing 901. 滑雪 给定一个 R行 C 列的矩阵&#xff0c;表示一个矩形网格滑雪场。 矩阵中第 i 行第 j 列的点表示滑雪场的第 i 行第 j 列区域的高度。 一个人从滑雪场中的某个区域内出发&#xff0c;每次可以向上下左右任意一个方向滑动一个单位距离。 当然&#xff0c;一个人能…

鸿蒙跨平台框架来了ArkUi-X

前言&#xff1a; 各位同学大家有段时间没有给大家更新博客了 之前鸿蒙推出了鸿ArkUi-X 框架所以就写个文章分享一下 效果图&#xff1a; 首先需要下载支持 ArkUI-X 套件的华为开发工具 DevEco &#xff0c;版本为 4.0 以上&#xff0c;目前可以下载预览版进行体验。下载地址…

Node.js与npm版本比对

Node.js与npm版本比对 Node.js与npm版本比对版本对比表Node版本对比 Node.js与npm版本比对 我们在项目开发过程中&#xff0c;经常会遇到公司一些老的前端工程项目&#xff0c;而我们当前的node及npm版本都是相对比较新的了。 在运行以前工程时&#xff0c;会遇到相关环境不匹…

宝塔Python3.7安装模块报错ModuleNotFoundError: No module named ‘Crypto‘解决办法

前言 今晚遇到一个问题&#xff0c;宝塔服务器上安装脚本的模块时&#xff0c;出现以下报错&#xff0c;这里找到了解决办法 Traceback (most recent call last):File "/www/wwwroot/unifysign/fuck_chaoxing/fuck_xxt.py", line 4, in <module>from Crypto.…

WORD中的表格内容回车行距过大无法调整行距

word插入表格&#xff0c;编辑内容&#xff0c;换行遇到如下问题&#xff1a; 回车后行距过大&#xff0c;无法调整行距。 解决方法&#xff08;并行&#xff09;&#xff1a; 方法1&#xff1a;选中要调整的内容&#xff0c;菜单路径&#xff1a;“编辑-清除-格式” 方法2&am…

解读BOT攻击,探索灵活且准确的安全之道

车票、秒杀、限量球鞋……面对这样的抢购场景&#xff0c;为什么总是落后于人&#xff1f;其实你遇到的并不是真人&#xff0c;而是恶意BOT。恶意的BOT进行信息数据爬取、薅羊毛等攻击行为&#xff0c;正损害着企业和用户的利益。在过去 5 年&#xff0c;几乎每个企业都会遇到由…

JVM相关面试题(每日一练)

1. 什么是垃圾回收机制&#xff1f; 垃圾收集 Garbage Collection 通常被称为“GC”&#xff0c;它诞生于1960年 MIT 的 Lisp 语言&#xff0c;经过半个多世纪&#xff0c;目前已经十分成熟了。 jvm 中&#xff0c;程序计数器、虚拟机栈、本地方法栈都是随线程而生随线程而灭&a…

Git(二)版本控制、发展历史、初始化配置、别名

目录 一、版本控制1.1 为什么要使用版本控制&#xff1f;1.2 集中化的版本控制系统1.3 分布式的版本控制系统1.3 两种版本控制系统对比集中式&#xff08;svn&#xff09;分布式&#xff08;git&#xff09; 二、发展历史三、初始化配置3.1 配置文件3.2 配置内容 四、别名 官网…

esp32-C3固件烧录用户手册

esp32-C3固件烧录用户手册1.4 文章目录 esp32-C3固件烧录用户手册1.4烧录所需硬件软件工具vscodeplatformIOflash_download_tools 插座与USB转TTL模块之间接线esp32-C3版本插座&#xff08;底板4针&#xff09; bin固件和烧录地址获取详细烧录地址和信息获取文件系统程序详细烧…

输入/输出应用程序接口和设备驱动程序接口

文章目录 1.输入/输出应用程序接口1.字符设备接口2.块设备接口3.网络设备接口1.网络设备套接字通信 4.阻塞/非阻塞I/O 2.设备驱动程序接口1.统一标准的设备驱动程序接口 1.输入/输出应用程序接口 1.字符设备接口 get/put系统调用:向字符设备读/写一个字符 2.块设备接口 read/wr…

Android拖放startDragAndDrop拖拽onDrawShadow动态添加View,Kotlin(3)

Android拖放startDragAndDrop拖拽onDrawShadow动态添加View&#xff0c;Kotlin&#xff08;3&#xff09; import android.content.ClipData import android.graphics.Canvas import android.graphics.Point import android.os.Bundle import android.util.Log import android.…

酷开科技 | 酷开系统大屏电视,打造精彩家庭场景

在信息资讯不发达的年代&#xff0c;电视机一直都是个人及家庭重要的信息获取渠道和家庭娱乐中心&#xff0c;是每个家庭必不可少的大家电之一&#xff01;在快节奏的现代生活中&#xff0c;受手机和平板的冲击&#xff0c;电视机这个曾经的客厅“霸主”一度失去了“主角光环”…

低概率Bug,研发敷衍说复现不到

测试工作中&#xff0c;经常会遇到一些低概率出现的问题&#xff0c;如果再是个严重问题&#xff0c;那测试人员的压力无疑是很大的&#xff0c;一方面是因为低概率难以复现&#xff0c;另一面则是来自项目组的压力。 如何在测试时减少此类问题的重复投入&#xff0c;我的思考如…

SAP ABAP 报表输出成 excel 统计图形 (RFC : GFW_PRES_SHOW_MULT)

SAP 预设了一个类型组 GFW &#xff0c;做简单的excel图形输出 话不多说&#xff0c;直接上代码&#xff1a; *&---------------------------------------------------------------------* *& Report ZCYCLE057 *&----------------------------------------------…