C++数据结构之链表详解

C++数据结构之链表详解

链表是一种重要的数据结构,它可以动态的分配内存空间,实现灵活的元素插入,删除等操作。本文将详细讲解链表的定义、实现、常见操作以及链表的应用。

定义与特点

链表是一种线性表数据结构,由一系列节点组成,每个节点包含数据和指向下一个节点的指针。链表分为单向链表和双向链表,其中单向链表的每个节点只包含一个指针,指向下一个节点,而双向链表的每个节点包含两个指针,分别指向前一个节点和后一个节点。

链表的特点:
- 空间动态分配。
- 灵活的插入和删除操作。
- 随机访问效率较低,但插入和删除操作的效率很高。

实现

链表的实现需要定义一个节点结构体,包含数据和指针部分。下面是单向链表实现的代码:

struct ListNode {
    int val;        //数据部分
    ListNode* next; //指针部分
    ListNode(int x) : val(x), next(nullptr) {} //构造函数
};

常见操作

链表操作包括节点的插入、删除、查找等,下面介绍常用的操作:

节点的插入

链表的节点插入操作包括头部插入和尾部插入两种方式,可以通过指针操作实现。

//头部插入
ListNode* insertHead(ListNode* head, int val) {
    ListNode* new_node = new ListNode(val);
    new_node->next = head;
    return new_node;
}

//尾部插入
ListNode* insertTail(ListNode* head, int val) {
    if (!head) {
        return new ListNode(val);
    }
    ListNode* curr = head;
    while (curr->next) {
        curr = curr->next;
    }
    curr->next = new ListNode(val);
    return head;
}

节点的删除

链表的节点删除同样包括头部删除和尾部删除两种方式,需要将指针指向下一个节点或前一个节点,再释放删除的节点。

//头部删除
ListNode* deleteHead(ListNode* head) {
    if (!head) {
        return nullptr;
    }
    ListNode* temp = head->next;
    delete head;
    return temp;
}

//尾部删除
ListNode* deleteTail(ListNode* head) {
    if (!head) {
        return nullptr;
    }
    if (!head->next) {
        delete head;
        return nullptr;
    }
    ListNode* curr = head;
    while (curr->next->next) {
        curr = curr->next;
    }
    delete curr->next;
    curr->next = nullptr;
    return head;
}

节点的查找

链表的节点查找包括按值查找和按位置查找两种方式。

//按值查找
ListNode* findByValue(ListNode* head, int val) {
    ListNode* curr = head;
    while (curr && curr->val != val) {
        curr = curr->next;
    }
    return curr;
}

//按位置查找
ListNode* findByIndex(ListNode* head, int index) {
    ListNode* curr = head;
    int i = 0;
    while (curr && i != index) {
        curr = curr->next;
        i++;
    }
    return curr;
}

链表的应用

链表可用于实现栈、队列、哈希表等数据结构,同时也可以用于解决一些算法问题,如链表反转、链表合并等问题。

下面是链表合并的实现:

ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
    ListNode dummy(0);
    ListNode* curr = &dummy;
    while (l1 && l2) {
        if (l1->val < l2->val) {
            curr->next = l1;
            l1 = l1->next;
        } else {
            curr->next = l2;
            l2 = l2->next;
        }
        curr = curr->next;
    }
    curr->next = l1 ? l1 : l2;
    return dummy.next;
}

示例说明

假设现在有两个单向链表,l1表示[1,2,4],l2表示[1,3,4],需要将这两个链表合并成一个新的链表。

ListNode* l1 = new ListNode(1);
l1->next = new ListNode(2);
l1->next->next = new ListNode(4);

ListNode* l2 = new ListNode(1);
l2->next = new ListNode(3);
l2->next->next = new ListNode(4);

ListNode* l3 = mergeTwoLists(l1, l2);

最终得到的合并后的链表l3表示[1,1,2,3,4,4]。

另外一个示例是如何使用链表实现栈数据结构,下面是代码示例:

class MyStack {
public:
    /** Initialize your data structure here. */
    MyStack() {
        top_ = nullptr;
    }

    /** Push element x onto stack. */
    void push(int x) {
        ListNode* new_node = new ListNode(x);
        new_node->next = top_;
        top_ = new_node;
    }

    /** Removes the element on top of the stack and returns that element. */
    int pop() {
        if (!top_) {
            return -1;
        }
        ListNode* temp = top_;
        top_ = top_->next;
        int val = temp->val;
        delete temp;
        return val;
    }

    /** Get the top element. */
    int top() {
        return top_->val;
    }

    /** Returns whether the stack is empty. */
    bool empty() {
        return top_ == nullptr;
    }

private:
    ListNode* top_;
};

总结

链表是一种十分重要的数据结构,在算法问题中也非常常见。本文介绍了链表的定义、实现、常见操作和应用,并给出了两个示例说明链表的使用。希望本文可以帮助读者更好的掌握链表的知识。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++数据结构之链表详解 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • C语言数据结构与算法之时间空间复杂度入门

    C语言数据结构与算法之时间空间复杂度入门攻略 1. 什么是时间复杂度和空间复杂度? 在进行算法设计时,我们不仅需要考虑到算法的正确性,还要考虑到算法的执行效率。而衡量算法执行效率的指标主要有两个,即时间复杂度和空间复杂度: 时间复杂度:衡量算法所需时间的度量,通常用“大O”符号来表示。比如,对于n个元素的数组,某些算法需要执行n次操作,这个算法的时间复杂度就…

    数据结构 2023年5月16日
    00
  • Java数据结构之链表、栈、队列、树的实现方法示例

    Java数据结构之链表、栈、队列、树的实现方法示例 链表 链表是一种线性数据结构,由节点的集合构成。每个节点包含两部分,数据部分和指针部分。数据部分用于存储数据,指针部分用于指向下一个节点。 单向链表示例 public class LinkedList<E>{ private Node<E> head; private int siz…

    数据结构 2023年5月17日
    00
  • 2020滴滴最新PHP试题(附答案及解析)

    题目链接:https://www.fibar.cn/newsDetail/18216.html 本文主要是对“2020滴滴最新PHP试题(附答案及解析)”的解题思路和过程进行详细讲解。 题目难度 此题属于中等难度,需要考生具备 PHP 基础知识和算法基础。 题目要求 题目要求我们编写一个程序,实现多个字符串的排序输出。程序需要满足以下要求: 输入:多个字符串…

    数据结构 2023年5月17日
    00
  • Redis数据结构之链表与字典的使用

    Redis是一个开源、基于内存的数据结构存储系统。Redis支持多种数据类型,包括字符串、整数、浮点数、列表、哈希表、集合、有序集合等。本文将详细介绍Redis数据结构之链表与字典的使用。 链表 链表是Redis中常用的数据结构之一,主要用于存储有序的元素列表。链表中的每个元素都包含了一个指向前驱元素和后继元素的指针,这种结构可以方便地实现链表的插入、删除和…

    数据结构 2023年5月17日
    00
  • 【JavaScript快速排序算法】不同版本原理分析

    说明 快速排序(QuickSort),又称分区交换排序(partition-exchange sort),简称快排。快排是一种通过基准划分区块,再不断交换左右项的排序方式,其采用了分治法,减少了交换的次数。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速…

    算法与数据结构 2023年4月18日
    00
  • C++数据结构AVL树全面分析

    C++数据结构AVL树全面分析 简介 AVL树是一种二叉搜索树,它通过使树保持高度平衡来提高搜索、插入和删除操作的效率。AVL树本质上是通过在插入和删除节点时旋转子树来保持平衡的。AVL树被认为是最早的自平衡二元搜索树。 AVL树的定义 AVL树是一种满足以下特性的BST: 每个节点都有一个左子树和一个右子树,并且左子树、右子树也是AVL树。 左子树高度和右…

    数据结构 2023年5月17日
    00
  • C语言数据结构树的双亲表示法实例详解

    C语言数据结构树的双亲表示法实例详解 什么是双亲表示法 在树上,每个节点都有且仅有一个父节点(根节点除外)。对于一个树结构,我们可以使用许多方法来表示这个树,其中最常见的一种方法是双亲表示法。该表示法使用一个一维数组来存储树的节点,数组的下标即为该节点的编号,数组的值则表示该节点的父节点编号。 当一个节点没有父节点时,该节点即为根节点。 双亲表示法的优缺点 …

    数据结构 2023年5月17日
    00
  • 「线段树」!(简单)的线段树

    本题为3月20日23上半学期集训每日一题中B题的题解 题面 题目描述 给你一个序列 \(A[1],A[2],…,A[n]\) .( \(|A[i]| \leq 15007, 1 \leq N \leq 50,000\) ). M( \(1 \leq M \leq 500,000\) ) 次询问,每次询问 \(Query(x, y) = Max{A[i] …

    算法与数据结构 2023年4月18日
    00
合作推广
合作推广
分享本页
返回顶部