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

yizhihongxing

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日

相关文章

  • C语言实现扫雷游戏源代码

    C语言实现扫雷游戏源代码 概述 扫雷游戏是一款经典的休闲游戏,通过探查已知方块及周围方块的数字,寻找安全区域,最终完成游戏目标。本文介绍了使用C语言实现扫雷游戏的完整攻略,主要包括如何实现游戏逻辑、界面设计和数据存储等方面。 游戏逻辑 扫雷游戏的核心逻辑是根据已知方块周围的数字计算出未知区域是否有雷。我们需要使用以下数据结构来存储游戏状态: 数据结构 地图:…

    other 2023年6月26日
    00
  • 迅雷怎么修改文件后缀名?迅雷重命名文件方法

    迅雷怎么修改文件后缀名?迅雷重命名文件方法攻略 迅雷是一款常用的下载工具,它提供了一种简便的方法来修改文件后缀名。下面是使用迅雷修改文件后缀名的完整攻略: 步骤一:打开迅雷软件 首先,确保你已经安装了迅雷软件,并且打开了它。 步骤二:选择要修改后缀名的文件 在迅雷软件中,找到你想要修改后缀名的文件。你可以通过在迅雷的下载列表中找到文件,或者通过导航到文件所在…

    other 2023年8月5日
    00
  • securecrt破解安装详细教程

    SecureCRT破解安装详细教程 SecureCRT是一款非常流行的终端仿真软件,但是官方版本需要付费才能使用,本文将介绍如何破解SecureCRT并进行安装,以实现免费使用。 步骤1:下载破解文件 首先,需要下载SecureCRT的破解文件,可以在网络上搜索到。 步骤2:停止官方版SecureCRT进程 在进行破解之前,需要先停止正常运行的SecureC…

    其他 2023年3月28日
    00
  • 微软Windows系统版本Build号即将突破10000大关

    微软Windows系统版本Build号攻略 微软的Windows操作系统版本Build号即将突破10000大关,这是一个令人兴奋的里程碑。在本攻略中,我将详细介绍如何了解和跟踪Windows系统版本Build号的变化,并提供两个示例说明。 了解Windows系统版本Build号 Windows系统版本Build号是一个标识符,用于表示Windows操作系统的…

    other 2023年8月3日
    00
  • 浅析C++中结构体的定义、初始化和引用

    下面是详细的讲解关于“浅析C++中结构体的定义、初始化和引用”的完整攻略。 结构体的定义 在C++中,结构体是一种数据类型,可以包含不同类型的数据成员。定义结构体的语法格式如下: struct 结构体名{ 数据类型1 成员名1; 数据类型2 成员名2; … }; 其中,结构体名可以自定义,成员名和数据类型可以按需指定。 例如,定义一个学生结构体Stude…

    other 2023年6月20日
    00
  • iPadOS14.4固件下载地址 iPadOS14.4正式版下载

    iPadOS 14.4固件下载攻略 iPadOS 14.4是最新的iPad操作系统版本,它带来了一些新功能和改进。如果你想下载iPadOS 14.4固件,下面是一个详细的攻略,包含了下载地址和示例说明。 步骤1:备份你的iPad 在开始下载之前,强烈建议你备份你的iPad。这样可以确保你的数据在升级过程中不会丢失。你可以通过iCloud或iTunes进行备份…

    other 2023年8月4日
    00
  • 详谈PHP程序Laravel 5框架的优化技巧

    详谈PHP程序Laravel 5框架的优化技巧 Laravel 5是目前最流行的PHP框架之一,但是在处理大量请求和数据时,应用程序可能会面临性能瓶颈。以下是一些优化技巧,可以帮助您提高Laravel 5应用程序的性能。 1. 避免使用较慢的操作 在编写代码时,需要时刻关注应用程序中的每个操作对性能的影响。一些操作会比其他操作慢得多,最好尽可能避免使用这些操…

    other 2023年6月26日
    00
  • PHP内核探索:变量概述

    PHP内核探索:变量概述攻略 简介 在PHP内核探索中,了解变量的概述是非常重要的。本攻略将详细介绍PHP变量的基本概念、内部实现和使用方法。 变量的基本概念 在PHP中,变量是用于存储数据的容器。每个变量都有一个名称和一个关联的值。变量的名称是由字母、数字和下划线组成的字符串,且必须以字母或下划线开头。变量的值可以是任何数据类型,包括整数、浮点数、字符串、…

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