首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

一种用于双向链表C++的插入方法

双向链表的插入方法

基础概念

双向链表(Doubly Linked List)是一种链式数据结构,其中每个节点包含三个部分:数据域、前驱指针(指向前一个节点)和后继指针(指向后一个节点)。这种结构允许从任意节点向前或向后遍历链表。

插入方法的优势

  1. 灵活性:双向链表允许在任何位置插入或删除节点,而不需要移动其他节点。
  2. 高效查找:虽然链表的查找效率不如数组,但双向链表可以通过前驱和后继指针快速定位前后节点。
  3. 内存利用率:链表的节点可以动态分配内存,不需要预先分配固定大小的数组。

插入方法的类型

  1. 头插法:在链表头部插入新节点。
  2. 尾插法:在链表尾部插入新节点。
  3. 中间插法:在链表的任意位置插入新节点。

应用场景

双向链表广泛应用于需要频繁插入和删除操作的场景,例如:

  • LRU缓存:最近最少使用的缓存淘汰算法。
  • 双向链表栈:结合栈和链表的优点,实现高效的入栈和出栈操作。
  • 图和树的遍历:在某些遍历算法中,双向链表可以用于存储路径或状态。

插入方法的实现

以下是一个C++实现双向链表插入方法的示例代码:

代码语言:txt
复制
#include <iostream>

// 定义双向链表节点结构
struct Node {
    int data;
    Node* prev;
    Node* next;
    Node(int val) : data(val), prev(nullptr), next(nullptr) {}
};

// 定义双向链表类
class DoublyLinkedList {
public:
    DoublyLinkedList() : head(nullptr), tail(nullptr) {}

    // 头插法
    void insertAtHead(int value) {
        Node* newNode = new Node(value);
        if (!head) {
            head = tail = newNode;
        } else {
            newNode->next = head;
            head->prev = newNode;
            head = newNode;
        }
    }

    // 尾插法
    void insertAtTail(int value) {
        Node* newNode = new Node(value);
        if (!tail) {
            head = tail = newNode;
        } else {
            newNode->prev = tail;
            tail->next = newNode;
            tail = newNode;
        }
    }

    // 中间插法
    void insertAtPosition(int value, int position) {
        if (position <= 0) {
            insertAtHead(value);
            return;
        }

        Node* newNode = new Node(value);
        Node* current = head;
        int count = 0;

        while (current && count < position - 1) {
            current = current->next;
            count++;
        }

        if (!current) {
            insertAtTail(value);
        } else {
            newNode->next = current->next;
            newNode->prev = current;
            if (current->next) {
                current->next->prev = newNode;
            } else {
                tail = newNode;
            }
            current->next = newNode;
        }
    }

    // 打印链表
    void printList() {
        Node* current = head;
        while (current) {
            std::cout << current->data << " ";
            current = current->next;
        }
        std::cout << std::endl;
    }

private:
    Node* head;
    Node* tail;
};

int main() {
    DoublyLinkedList list;
    list.insertAtHead(1);
    list.insertAtTail(3);
    list.insertAtPosition(2, 2);
    list.printList(); // 输出: 1 2 3
    return 0;
}

可能遇到的问题及解决方法

  1. 内存泄漏:在插入节点时,如果没有正确管理内存,可能会导致内存泄漏。解决方法是在删除节点时释放内存。
  2. 空指针异常:在访问节点的前驱或后继指针时,如果节点为空,会导致空指针异常。解决方法是在访问指针前检查节点是否为空。
  3. 插入位置错误:在中间插入节点时,如果插入位置超出链表范围,会导致插入失败。解决方法是检查插入位置的有效性。

参考链接

通过以上内容,你应该对双向链表的插入方法有了全面的了解,包括基础概念、优势、类型、应用场景以及常见问题的解决方法。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

DS双向链表—祖玛 C++

一旦有三个或更多同色的珠子变成相邻,它们就会立即消失。这类消除现象可能会连锁式发生,其间你将暂时不能发射珠子。 给定轨道上初始的珠子序列,然后是玩家所做的一系列操作。...你的任务是,在各次操作之后及时计算出新的珠子序列。 输入 第一行是一个由大写字母'A'~'Z'组成的字符串,表示轨道上初始的珠子序列,不同的字母表示不同的颜色。...这道题关键在于消除,首先要注意到是三个或三个以上都能消,所以去判断连续三个或四个甚至五个的方法是不行的,所以我的解决方法是先去数有多少个相同的,大于等于三个的才去消除,因为有可能会出现连环反应,所以必须写成循环...using namespace std; class Node { public: char data; Node * next = NULL; }; class List {//带头结点的单链表...List(); //析构函数,逐个结点回收 int Insert(char item, int i); //第i位置插入元素,操作成功或失败返回OK或ERROR void print();//打印单链表所有数据

22230

链表和双向链表的实现

前言 ---- 链表中的数据通过指针连接,添加、插入或删除节点只需要修改指针指向 实现思路 实现一个链表需要具备以下方法 在链表尾部添加节点 获取链表所有节点的数据 链表指定位置插入元素 获取链表指定位置的节点数据...获取节点在链表中的位置 更新链表指定位置的数据 移除链表指定位置的节点 移除链表中的指定节点 判断链表是否为空 获取链表长度 链表内部需要定义head指针和链表长度 实现代码 定义head指针和length...(linkedList.size()) 双向链表 双向链表的指针是双向的,前指针指向上一个节点,后指针指向下一个节点 head指向第一个节点,tail指向最后一个节点 双向链表实现思路 需要具备以下方法...判断链表是否为空 获取链表长度 定义head和tail分别指向第一个节点和最后一个节点 代码实现 /** * 双向链表 */ function DoublyLinkedList() { //指向第一个节点...this.tail = node } //链表长度加一 this.length += 1 } 向前遍历链表获取节点数据 forwardString() { //用于存储节点数据

71040
  • 【C++】深入理解List:双向链表的应用

    凭时间赢来的东西,时间肯定会为之作证。 前言 这是我自己学习C++的第七篇博客总结。后期我会继续把C++学习笔记开源至博客上。...上一期笔记是关于C++的vector类知识,没看的同学可以过去看看:【C++】探索Vector:灵活的数据存储解决方案-CSDN博客 https://blog.csdn.net/hsy1603914691...2. string类的底层其实是一个储存字符的顺序表结构,而vector类的底层是一个顺序表模板,使用时需要显示实例化,而list类的底层是一个双向链表模板,使用时也需要显示实例化,后面的笔记中以整形为例...注意反向迭代器进行迭代的步骤也是++,反向迭代器是用来反向遍历链表的。 5. 范围for循环,用于有范围的集合进行遍历,C++11中引入了基于范围的for循环。...范围for循环,是用于遍历容器的,它的底层也是迭代器。(数组也可以用范围for循环。)

    5510

    循环双向链表的

    链表的使用 初级版:   结构体   struct data{     struct data* next;     int data;   };   head=p1->p2->p3->p4->NULL...  需要删除节点p3时就很麻烦,我们需要从头去遍历,找到next指针为p3时将next指针指向p3的next;   为此方便起见,我们可以使用双向链表进行实现。...内核中是这样处理的,   创建一个双向循环链表   =>headp1p2p3p4=   向链表中指定位置插入节点   原有链prenext   这也是最基本的插入节点的方法...}   根据插入节点的方式写删除节点就容易的多了   _del(struct data * pre,struct data * next){     pre->next = next;     next...}   没有做释放的代码,创建链的时候需要用malloc去创建,内核中的双向链表正是这么实现的,   特别容易书写,不太会产生副作用。二级指向是在太难理解了

    29010

    java双向链表解析实现双向链表的创建含代码

    一.双向链表 单向链表从头部开始我们的每一个节点指向后驱的节点。...此处为单向链表 单向链表 双向链表是相互指向前驱以及后驱的链表 前驱链表我们需要在我们的MyListCode内部类中在定义一个previous来接收每一个前驱的地址 想要删除任意节点可以直接通过访问下一个节点使其...、指定元素删除含有该元素的第一个节点、指定元素删除含有该元素的所有节点等… 二.创建MyListCode类实现双向链表创建 public class MyListNode implements IList...,将头部的上一个节点置空(这里还要考虑头部如果该链表只有一个节点的情况下,下一个节点一定为空,这里将last也置空)当下一个节点head不为空后在将上一个节点置空 如果尾部为key则需要last跳到上一个节点...,将数值大的放在后 public void clean();//释放链表中的所有节点 } MyListNode整体代码 import java.util.List; public class

    9010

    C++ 链链不忘@必有回响之双向链表

    前言 写过一篇与单链表相关的博文,实际应用中,双向循环链表的功能更强大。 单链表中,查询一个已知结点的后驱结点的时间复杂度为O(1)。...双向链表 双向链表中除了有存储头结点的head头指针变量外,一般还会增加一个存储尾结点的名为tail尾指针变量。这样,可以实现从头到尾或从尾到头对链表进行遍历。...在双向链表中,在尾结点的后驱指针位存储头结点地址,头结点的前驱指针位存储尾结点地址,形成一个首尾相连的闭环,称这样的链表为双向循环链表。...双向链表需要提供对链表中的数据进行常规维护的算法,如: 链表初始化。 创建链表。 查找。 后插入、前插入。 删除。...…… 算法的整体思路和单链表相似,因结点中多了一个前驱结点信息,为各种操作带来便利的同时,需要注意细节。下文将介绍双向链表中的几个重要函数。

    24910

    C++ STL源码剖析之双向环形链表list

    C++ STL源码剖析之双向环形链表list 0. 导语 源码对应的版本为gcc-4.9.1 1.list list为双向环形链表,其结构为: ? 自己绘制的图如下: ?...像前面提到的push_back、push_front、_M_insert,还有insert都是使用最基础的双向链表插入函数_M_hook实现的。...sort接受的输入迭代器是随机访问迭代器,但是双向list链表容器的访问方式是双向迭代器,因此,不能使用STL本身的排序算法sort,必须自己定义属于自己访问的排序算法。..._M_node) { list __carry; // 辅助链表,用于从a中提取元素以及临时保存两个链表的合并结果 list __tmp[64]; // 保存着当前每一个归并层次的结果...,用于从a中提取元素以及临时保存两个链表的合并结果 list counter[64]; // 保存着当前每一个归并层次的结果, i号链表保存的元素个数为2的i次方或者0 int

    1.6K40

    双向链表的优雅实现

    文中涉及的代码可访问 GitHub:https://github.com/UniqueDong/algorithms.git 上次我们说了「单向链表」的代码实现,今天带大家一起玩下双向链表,双向链表的节点比单项多了一个指针引用...双向链表就像渣男,跟「前女友」和「现女友」,还有一个「备胎』都保持联系。前女友就像是前驱节点,现女友就是 「当前 data」,而「next」指针就像是他套住的备胎。...使用这样的数据结构就能实现「进可攻退可守」灵活状态。 接下来让我们一起实现『渣男双向链表』。...prev; this.item = item; this.next = next; } } 代码实现 定义好渣男节点后,就开始实现我们的双向链表...一种是在指定节点的前面插入新节点。 在后面添加前面尾巴添加已经说过,对于在指定节点的前面插入需要我们先找到指定位置节点,然后改变他们的 prev next 指向。

    82130

    循环链表的实现_建立双向循环链表

    循环链表   循环链表是一个收尾相接的链表,将单链表的最后一个指针域改由NULL改为指向表头结点这就是单链式的循环链表,并称为循环单链表   带头结点的循环单链表的各种操作的算法实现与带头结点单链表的算法实现类似...单链表中的判别条件为p!=NULL或p->next!=NULL,而单循环链表判别条件是p!=L或p->next!=L   在循环单链表中附设尾指针有时候比附设头指针更简单。...如:在用头指针的循环单链表中找a1的时间复杂度是O(1),找an需要从头找到尾,时间复杂度是O(n),如果用为指针rear,找开始结点和终端结点的存储位置分别是rear->next->next和rear...    方法一:先找到两个链表LA,LB的表尾,分别用p,q指向它,然后将第一个链表的表尾与第二个链表的第一个结点连起来,修改第二个表的尾q,使它的链域指向第一个表头 //头指针合并循环链表 #include...;//返回新的链表的尾指针 }   循环链表求长度 #include #define len sizeof(Node) #include typedef struct

    75320

    C++奇迹之旅:双向链表容器list的灵活使用技巧

    kw=list std::list 是 C++ 标准库中的一个序列容器,它实现了双向链表(doubly linked list)。...列表是序列容器,允许在序列中的任何位置进行常数时间的插入和删除操作,并且支持双向遍历。 列表容器实现为双向链表;双向链表可以将它们包含的每个元素存储在不同且无关的存储位置。...); explicit 关键字在 C++ 中用于控制构造函数的隐式转换行为。...具体来说,explicit 关键字主要用于防止以下两种情况: 隐式类型转换:构造函数可以被用于隐式地将一种类型的对象转换为另一个类型。...总结 std::list是C++标准库中的双向链表容器,具有常数时间内插入和删除元素的优势。

    9010

    【C++】- 掌握STL List类:带你探索双向链表的魅力

    前言:  C++中的List容器是标准模板库(STL)中的一种序列容器,它实现了双向链表的功能。...与数组(如vector)和单向链表相比,List容器提供了更加灵活的元素插入和删除操作,特别是在容器中间位置进行这些操作时。...一.list的介绍及使用 1. list的介绍 双向链表结构: list容器使用双向链表来存储元素,每个元素(节点)都包含数据部分和两个指针,分别指向前一个元素和后一个元素。...因为list的底层结构为带头结点的双向循环链表,因此在list进行插入操作时不会导致迭代器失效,只有删除时才会失效,并且失效的是被删除节点的迭代器,其他迭代器不会受到影响。...最后想说: 本章我们STL的List就介绍到这里,下期我将介绍关于stack和queue的有关知识,如果这篇文章对你有帮助,记得点赞,评论+收藏 ,最后别忘了关注作者,作者将带领你探索更多关于C++方面的问题

    12710

    深入探索 C++ STL: 高效双向链表 list 的使用与实践

    C++ STL(Standard Template Library)的 list 容器是双向链表的实现,适合需要频繁插入和删除元素的场景。...概述 C++ 中的 list 是一个双向链表,与 vector 或 deque 相比,它的主要优点在于插入和删除操作效率较高,因为插入和删除操作只涉及局部的节点调整,而不会像 vector 那样涉及整个容器的重新分配...2. list 容器的特性 list 是双向链表,具有以下几个显著特性: 双向链表:每个节点都包含指向前一个节点和后一个节点的指针,支持从任意位置高效的插入和删除操作。...list 提供了 sort() 函数用于对链表中的元素进行排序。...由于 list 的迭代器是双向迭代器,因此可以使用适用于双向迭代器的所有算法。

    11610

    双向链表的增删改查

    双向链表,我们曾经拿了一幅非常形象的图片来形容他,就像几个人手拉手围成一个圈一样。在我们代码中的呈现就是每个节点都有一个指向下一个节点的指针,同时也有一个指向上一个节点的指针。...(如图) 双向链表图形表示: 【实现代码】 因为插入和删除节点的步骤跟单向循环链表差不多,只是多了一个前驱指针,我们这里值给出代码,具体的插入和删除操作的示例图就不一一列举了。...#ifndef _DLINK_LIST_H #define _DLINK_LIST_H //自定义双向链表数据类型 typedef void DLinkList; //自定义双向链表节点数据类型 typedef...打印链表的长度 printf(“打印链表的长度, Length = %d\n”, DLinkList_Length(dlist)); //销毁双向链表 DLinkList_Destroy(dlist);...} void main() { dLinkListTest(); system(“pause”); } 双向链表增加了前驱的指针,在功能上完全是可以替代单向链表的,并且通过前驱指针我们可以更高效的遍历所有元素

    13510

    单循环链表-带头双向循环链表的实现

    今天我们就来学习一下结构最复杂的带头双向循环链表!!!...;   虽然名字听上去比较复杂单循环链表,但是实现起来比单链表(全名:不带头、不循环、单向链表)更加简单,也不需要过多考虑特殊情况;   两种链表的比较:(上面是单链表,下面是带头双向循环链表)   结构分析...  首先链表的头节点是不存储有效数据的(该节点被称为哨兵位),其次我们只需要知道改头节点的指针就能找到整个链表单循环链表,并且便于对整个链表进行维护;   当然既然是双向的嘛,那节点一定有个指针域指向前一个节点...  该链表的尾插,比单链表的尾插简单太多了,不用遍历找尾:    // 双向链表尾插 void ListPushBack(ListNode* pHead, LTDataType...// 双向链表在pos的前面进行插入 void ListInsert(ListNode* pos, LTDataType x); // 双向链表删除pos位置的节点 void

    61130

    【C++进阶】深入STL之list:高效双向链表的使用技巧

    前言:双向链表是链表数据结构的一种重要变体,它允许我们在链表的任何位置进行高效的插入和删除操作,而无需像数组那样进行大量的数据移动。...1. list的基本概念 list 是 C++ 标准模板库 (STL) 中的一个容器,它基于双向链表实现。...双向链表是一种动态数据结构,由一系列节点组成,每个节点包含数据元素和两个指向其他节点的指针 在介绍list的使用之前,我们先来看看它的结构: 实际上:list就是一个带头双向链表 2. list...双向迭代器能支持++,--, 单向迭代器只支持++ 这些迭代器是向上兼容的,随机访问迭代器是特殊的单向迭代器 总结 通过本篇文章,我们一同探索了C++标准模板库(STL)中list容器的奥秘。...list以其基于双向链表的特性,为我们提供了在序列容器中进行高效插入和删除操作的强大工具。

    37610

    从零开始实现 C++ 双向链表:深入理解链表底层原理

    前言: 在 C++ 标准库中,std::list 是一种非常常用的数据结构,其底层采用了双向链表的实现。...在实际开发中,双向链表是一种具有灵活插入和删除操作的数据结构,尤其适合那些需要频繁操作非连续内存数据的场景。本文将通过一个手动实现的双向链表类 list 来讲解双向链表的底层结构和实现原理。 1....总结 本文从底层实现的角度详细讲解了如何手动实现一个双向链表容器 list。我们设计了双向链表的数据结构,通过节点、迭代器、基本的插入、删除操作,最终实现了一个功能完整的链表容器。...4.迭代器操作与遍历:通过 begin() 和 end() 函数,我们可以使用 C++ 标准的范围遍历方式遍历链表的所有元素。...这使得链表容器的使用方式与 C++ 标准库中的其他容器一致,降低了使用门槛。 5.拷贝构造与赋值运算符:为了确保链表可以被正确拷贝,我们实现了拷贝构造函数和赋值操作符。

    12710

    c++的链表-C++链表

    C++链表   链表是由一系列连接在一起的结点构成,其中的每个结点都是一个数据结构。   ...链表是一种复杂的数据结构,其数据之间相互关系使得链表分成三种:单链表、循环链表、双向链表。   ...除了数据之外,每个结点还包含一根后继指针指向链表中的下一个结点。   单个结点的组成   非空链表的第一个结点称为链表的头。要访问链表中的结点,需要有一个指向链表头的指针。...从链表头开始,可以按照存储在每个结点中的后继指针访问链表中的其余结点。最后一个结点中的后继指针被设置为 以指示链表的结束。   指向链表头的指针用于定位链表的头部,所以也可以认为它代表了链表头。...链表的尾结点由于无后续结点c++的链表,其指针域为空,写作NULL。

    97220
    领券