C++中链表操作实例分析

C++中链表操作实例分析

什么是链表

链表(Linked List)是一种常见的数据结构,它由一系列节点组成,每个节点包含两个部分,一个是数据,另一个是指向下一个节点的指针。通过这些指针将节点串联起来,形成一个链表。

链表的数据结构定义

struct ListNode {
    int val;
    ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};

链表中每个节点的数据类型为 int,指针类型为 ListNode*,其中 next 指向下一个节点,当 next 为NULL 时表示链表的末尾。

链表的基本操作

链表的常见操作包括以下几个:

1. 创建链表

创建链表需要动态分配内存,创建节点并将各个节点串联起来,常用的方式有头插法和尾插法。

头插法

头插法创建一个链表时,从头结点开始逐个创建节点,并将新创建的节点插入到链表头部。

ListNode* createListByHeadInsert(vector<int> vec) {
    ListNode* head = new ListNode(0);
    for (int i = 0; i < vec.size(); i++) {
        ListNode* node = new ListNode(vec[i]);
        node->next = head->next;
        head->next = node;
    }
    return head->next;
}

尾插法

尾插法创建一个链表时,从头结点开始逐个创建节点,并将新创建的节点插入到链表尾部。

ListNode* createListByTailInsert(vector<int> vec) {
    ListNode* head = new ListNode(0);
    ListNode* tail = head;
    for (int i = 0; i < vec.size(); i++) {
        ListNode* node = new ListNode(vec[i]);
        tail->next = node;
        tail = tail->next;
    }
    return head->next;
}

2. 遍历链表

遍历链表就是依次访问链表中每个节点,可以通过 while 循环和 for 循环来实现。

void traverseList(ListNode* head) {
    while (head) {
        cout << head->val << "->";
        head = head->next;
    }
    cout << "NULL" << endl;
}

3. 插入节点

在链表中插入一个节点,需要先找到插入位置的前一个节点,然后将新节点插入到该节点之后。

void insertListNode(ListNode* pos, ListNode* node) {
    node->next = pos->next;
    pos->next = node;
}

4. 删除节点

在链表中删除一个节点,需要先找到要删除的节点的前一个节点,然后将该节点从链表中剔除。

void deleteListNode(ListNode* head, ListNode* node) {
    while (head && head->next != node) {
        head = head->next;
    }
    if (head && head->next == node) {
        head->next = head->next->next;
    }
}

5. 反转链表

反转链表是指将链表的方向逐一反向,例如原先链表是 1->2->3->4->5,反转后的链表为 5->4->3->2->1

ListNode* reverseList(ListNode* head) {
    ListNode* cur = head;
    ListNode* pre = NULL;
    while (cur) {
        ListNode* next = cur->next;
        cur->next = pre;
        pre = cur;
        cur = next;
    }
    return pre;
}

示例说明

以下是基于链表进行归并排序和删除倒数第n个节点的两个示例说明。

1. 归并排序

题目要求:对链表进行归并排序,注意时间复杂度

示例输入:[4,3,2,1]

示例输出:[1,2,3,4]

归并排序的时间复杂度为 O(nlogn),其中 n 表示链表的长度。

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        if (l1 == NULL) return l2;
        if (l2 == NULL) return l1;
        if (l1->val < l2->val) {
            l1->next = mergeTwoLists(l1->next, l2);
            return l1;
        } else {
            l2->next = mergeTwoLists(l1, l2->next);
            return l2;
        }
    }

    ListNode* sortList(ListNode* head) {
        if (head == NULL || head->next == NULL) return head;
        ListNode* slow = head;
        ListNode* fast = head;
        ListNode* prev = NULL;
        while (fast && fast->next) {
            prev = slow;
            slow = slow->next;
            fast = fast->next->next;
        }
        prev->next = NULL;
        ListNode* left = sortList(head);
        ListNode* right = sortList(slow);
        return mergeTwoLists(left, right);
    }
};

2. 删除倒数第n个节点

题目要求:删除链表的倒数第 n 个节点,并且返回链表的头结点。

示例输入:[1,2,3,4,5] n = 2

示例输出:[1,2,3,5]

算法思路:使用双指针,快指针先走 k 步,然后快慢指针一起走,当快指针走到链表末尾时,慢指针所在节点的 next 指针就是要删除节点的前一个节点。

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* fast = head;
        ListNode* slow = head;
        for (int i = 0; i < n; i++) {
            fast = fast->next;
        }
        if (fast == NULL) {
            return head->next;
        }
        while (fast->next != NULL) {
            fast = fast->next;
            slow = slow->next;
        }
        slow->next = slow->next->next;
        return head;
    }
};

总结

链表是一种常见的数据结构,常用于解决链式存储的问题。在 C++ 中,我们可以通过定义 ListNode 结构体来自定义链表类型,并通过基本操作来方便地对链表进行增删改查操作。同时在实际开发中,我们也可以借助链表来解决一些经典的算法问题。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++中链表操作实例分析 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • 字体模糊怎么调节 解决电脑字体模糊的方法大全详细图解

    字体模糊怎么调节?解决电脑字体模糊的方法大全详细图解 当我们使用电脑时,可能会发现在某些情况下,屏幕上显示的字体会出现模糊的情况,这不仅会影响用户的体验,还会降低使用的效率。因此,如何调节字体模糊并解决电脑字体模糊的问题,成为了我们使用电脑时必须掌握的技巧之一。 常见情况分析 首先,我们需要了解一下造成字体模糊的情况有哪些: 1. 分辨率问题 如果我们将电脑…

    other 2023年6月26日
    00
  • ubuntu下安装使用nvm

    以下是Ubuntu下安装使用nvm的完整攻略,包含两个示例: 步骤1:安装nvm 在Ubuntu中安装nvm的最简单方法是使用curl命令。打开终端并输入以下命令: curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash 这将下载并运行nvm的安装脚本。安…

    other 2023年5月6日
    00
  • 浅析SpringBoot打包上传到docker并实现多实例部署(IDEA版)

    下面我就来详细讲解“浅析SpringBoot打包上传到docker并实现多实例部署(IDEA版)”的完整攻略。 简介 本文主要介绍如何使用SpringBoot将Web应用程序打包上传到Docker镜像仓库并实现多实例部署。 准备工作 开发工具:IntelliJ IDEA JDK:1.8 或以上 Docker:要求安装 Docker Maven:要求使用 Ma…

    other 2023年6月27日
    00
  • 如何查询自己的ip地址 查询自己电脑的ip地址的方法

    如何查询自己的IP地址 要查询自己的IP地址,可以按照以下步骤进行操作: 方法一:使用命令提示符(Windows) 打开命令提示符。可以通过按下Win + R键,在弹出的运行窗口中输入\”cmd\”,然后点击\”确定\”来打开命令提示符。 在命令提示符窗口中,输入\”ipconfig\”命令,并按下回车键。 在输出结果中,查找\”IPv4 地址\”或\”IP…

    other 2023年7月29日
    00
  • Spring如何使用xml创建bean对象

    Spring如何使用XML创建Bean对象 以下是使用XML配置文件创建Bean对象的完整攻略: 创建XML配置文件:在Spring项目中创建一个XML配置文件(例如applicationContext.xml)。 声明命名空间:在XML文件的根元素中声明Spring的命名空间,以便使用Spring的XML配置。 示例代码: xml <beans xm…

    other 2023年10月15日
    00
  • 解决pycharm 安装numpy失败的问题

    以下是解决PyCharm安装NumPy失败的完整攻略。 问题描述 在使用PyCharm安装NumPy时,可能会出现安装失败的情况,如下所示: ERROR: Could not find a version that satisfies the requirement numpy (from versions: none) ERROR: No matching…

    other 2023年6月27日
    00
  • u盘怎么装win8系统 手把手教你用U盘装win8全过程图解

    用U盘装win8系统全过程图解 如果你想用U盘的方式安装win8系统,这里提供了一份详细的攻略,手把手教你操作。 准备工作 一台电脑(内存2G以上); 一枚U盘(容量4G以上); 一个win8系统镜像文件(可以从官方渠道或者其他安全可靠的网站下载)。 制作U盘启动盘 插入U盘,打开电脑。 打开电脑的磁盘管理界面,找到对应的U盘,右键点击选择“格式化”,格式化…

    other 2023年6月27日
    00
  • 有关数据库SQL递归查询在不同数据库中的实现方法

    SQL递归查询是指一个查询语句可以通过不断地自关联查询来完成一定程度的递归操作。这种查询方式在许多应用场景中经常使用。在不同的数据库中,SQL递归查询的实现方式也存在一些异同。下面我们就来详细讲解一下有关数据库SQL递归查询在不同数据库中的实现方法,具体内容如下: MySQL 实现递归查询 在 MySQL 中,可以通过使用 WITH RECURSIVE 或使…

    other 2023年6月27日
    00
合作推广
合作推广
分享本页
返回顶部