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

Java中的双向链表问题

双向链表(Doubly Linked List)是一种常见的数据结构,它由一系列节点组成,每个节点包含指向前一个节点和后一个节点的指针。与单向链表不同,双向链表可以在任意节点处进行双向遍历。

双向链表的优势在于可以快速地在任意位置插入或删除节点,而无需像数组那样进行元素的移动。它还可以支持双向遍历,使得在某些场景下的操作更加方便。

双向链表在Java中可以通过自定义类来实现。以下是一个简单的双向链表的Java实现示例:

代码语言:txt
复制
class Node {
    int data;
    Node prev;
    Node next;
    
    public Node(int data) {
        this.data = data;
        this.prev = null;
        this.next = null;
    }
}

class DoublyLinkedList {
    Node head;
    
    public DoublyLinkedList() {
        this.head = null;
    }
    
    // 在链表头部插入节点
    public void insertAtHead(int data) {
        Node newNode = new Node(data);
        if (head == null) {
            head = newNode;
        } else {
            newNode.next = head;
            head.prev = newNode;
            head = newNode;
        }
    }
    
    // 在链表尾部插入节点
    public void insertAtTail(int data) {
        Node newNode = new Node(data);
        if (head == null) {
            head = newNode;
        } else {
            Node current = head;
            while (current.next != null) {
                current = current.next;
            }
            current.next = newNode;
            newNode.prev = current;
        }
    }
    
    // 在指定位置插入节点
    public void insertAtPosition(int data, int position) {
        if (position <= 0) {
            insertAtHead(data);
        } else {
            Node newNode = new Node(data);
            Node current = head;
            int currentPosition = 0;
            while (current != null && currentPosition < position) {
                current = current.next;
                currentPosition++;
            }
            if (current != null) {
                newNode.next = current;
                newNode.prev = current.prev;
                current.prev.next = newNode;
                current.prev = newNode;
            } else {
                insertAtTail(data);
            }
        }
    }
    
    // 删除指定位置的节点
    public void deleteAtPosition(int position) {
        if (head == null) {
            return;
        }
        if (position <= 0) {
            head = head.next;
            head.prev = null;
        } else {
            Node current = head;
            int currentPosition = 0;
            while (current != null && currentPosition < position) {
                current = current.next;
                currentPosition++;
            }
            if (current != null) {
                current.prev.next = current.next;
                if (current.next != null) {
                    current.next.prev = current.prev;
                }
            }
        }
    }
    
    // 打印链表
    public void printList() {
        Node current = head;
        while (current != null) {
            System.out.print(current.data + " ");
            current = current.next;
        }
        System.out.println();
    }
}

这是一个简单的双向链表的实现,包括在链表头部插入节点、在链表尾部插入节点、在指定位置插入节点、删除指定位置的节点以及打印链表的功能。

双向链表在实际开发中有许多应用场景,例如:

  1. 编辑器中的撤销和重做功能:双向链表可以用于保存操作历史,支持撤销和重做操作。
  2. LRU缓存淘汰算法:双向链表可以用于实现LRU缓存淘汰算法,将最近使用的数据放在链表头部,当缓存满时,淘汰链表尾部的数据。
  3. 浏览器的前进和后退功能:双向链表可以用于保存浏览器的访问历史,支持前进和后退操作。

腾讯云提供了多种云计算相关产品,其中与双向链表相关的产品可能没有直接的对应关系。然而,腾讯云提供了强大的计算、存储和数据库等基础设施服务,可以支持开发者构建和部署各种应用程序。您可以参考腾讯云的官方文档和产品介绍页面,了解更多关于腾讯云的产品和服务:

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

相关·内容

Android双向链表「建议收藏」

1.看源代码必须搞懂Android数据结构。在init源代码双向链表listnode使用非常多,它仅仅有prev和next两个指针,没有不论什么数据成员。...这里须要考虑一个问题是,链表操作都是通过listnode进行,但是那只是是个连接件。...当我们顺着链表取得当中一项listnode结构时,又如何找到其宿主结构呢?在listnode结构并没有指向其宿主结构指针啊。毕竟。我们我真正关心是宿主结构。而不是连接件。...对于这个问题,我们举例内核list_head样例来解决。内核page结构体含有list_head成员,问题是:知道list_head地址。如何获取page宿主地址?...node节点,list始终指向双向链表头部(这个头部仅仅含有prev/next) void list_add_tail(listnode *list,listnode *node) {

66510

链表双向链表实现

前言 ---- 链表数据通过指针连接,添加、插入或删除节点只需要修改指针指向 实现思路 实现一个链表需要具备以下方法 在链表尾部添加节点 获取链表所有节点数据 链表指定位置插入元素 获取链表指定位置节点数据...获取节点在链表位置 更新链表指定位置数据 移除链表指定位置节点 移除链表指定节点 判断链表是否为空 获取链表长度 链表内部需要定义head指针和链表长度 实现代码 定义head指针和length...) { current = current.next } //返回指定位置节点数据 return current.data } 获取节点在链表位置 indexOf(data)...(linkedList.size()) 双向链表 双向链表指针是双向,前指针指向上一个节点,后指针指向下一个节点 head指向第一个节点,tail指向最后一个节点 双向链表实现思路 需要具备以下方法...尾部插入元素 任意位置插入元素 获取所有节点数据 正向遍历链表获取节点数据 反向遍历链表获取节点数据 获取指定位置节点数据 获取指定数据在链表位置 更新指定位置节点数据 移除指定位置节点 移除指定数据节点

68540

单向链表双向链表区别的意义 - Java

众所周知,链表是常用数据结构,在Java中有很多基于链表容器实现类,例如HashMap、LinkedList。但是这些链表有的是单向链表,有的是双向链表,那么他俩有什么不同呢?...(以下源码均属于jdk1.8.0_101) 双向链表有前后两个节点指针,可以回溯指针,方便节点删除,移动,在做删除操作时只需要将索引节点前后两个节点连接即可,但是相比单向链表会耗费额外资源。...单向链表只有后一节点指针,在节点删除,移动时候,需要暂存前一节点,删除时候将前一节点和后一节点连接,因为比双向链表少维护一个前节点,只在删除时候暂存,所以比单向链表节省资源,但是增加了操作复杂性...单向链表 ? image.png 双向链表 ? image.png 源码分析 1....LinkedList - 双向链表 直接连接前后节点 Node private static class Node { E item; Node next; Node

1.1K20

链表问题——长整数加法运算题解【双向链表

长整数加法运算 图片 问题描述 假设2个任意长度整数x、y分别用链表A和B存储,现要求设计一个算法,实现x+y。计算结果存储在链表C。...说明: 链表A、B、C可以是单向链表双向链表,但由于A和B输出时需要从头至尾遍历,而做加法时需要从尾至头遍历,因此推荐使用双向链表存储。...链表每个结点数据域可以选择以下三种设计方式: (1)链表每个结点存储长整数一位(不推荐); (2)链表每个结点从长整数低位开始拆分(4位为一组,存到一个结点中,即结点数据域为不超过9999...非负整数),依次存放在链表每个结点; (3)链表每个结点从长整数低位开始拆分(4位为一组,存到一个结点中,即结点数据域为1-4位字符串),依次存放在链表每个结点。...在异号相加【减法】计算,考虑与头部符号异号那组数符号纠正,考虑向前借位。

22920

循环双向链表

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

27410

Linux内核双向链表经典实现

概要 本文对双向链表进行探讨,介绍内容是Linux内核双向链表经典实现和用法。其中,也会涉及到Linux内核中非常常用两个经典宏定义offsetof和container_of。...将offsetof看作一个数学问题来看待,问题就相当简单了:已知'整体'和该整体'某一个部分',要根据该部分地址,计算出整体地址。...Linux双向链表经典实现 1.Linux双向链表介绍 Linux双向链表定义主要涉及到两个文件: include/linux/types.h include/linux/list.h Linux...双向链表使用思想 它是将双向链表节点嵌套在其它结构体;在遍历链表时候,根据双链表节点指针获取"它所在结构体指针",从而再获取数据。...3.Linux双向链表使用示例 双向链表代码(list.h): 1 #ifndef _LIST_HEAD_H 2 #define _LIST_HEAD_H 3 // 双向链表节点 4 struct

2.6K30

数据结构Java实现:循环链表双向链表

上篇教程给大家分享了单链表概念,以及如何用 Java 实现一个单链表结构:数据结构Java实现:单链表。...单链表是最基础一种链表结构,在实际开发使用有一些局限性,比如只能单向往后查找节点,如果需要找到某元素前驱节点,单链表是无法实现,今天来给大家分享另外两个复杂一些链表结构:循环链表双向链表。...接下来用 Java 实现一个循环链表结构,只需要在原有单链表基础上稍作修改即可,如下所示。...双向链表是相对单链表来讲,区别在于单链表只有一个指针指向下一个节点,是单向连接,只能从当前节点访问它后继节点。...如果是双向链表结构,每一个节点都会记录其前驱节点,可直接获取,所以此时时间复杂度为 O(1)。 ? 搞清楚了双向链表概念,接下来我们用 Java 来实现双向链表结构。

3.4K20

JavaScript 计算机科学:双向链表

DoublyLinkedList 类 与单链表一样,双向链表节点操作最好封装在一个类。...双向链表数据查找 双向链表 get() 方法与单链表 get() 方法完全相同。...双向链表数据删除 从双向链表删除数据与单链表基本相同:首先遍历列表找到需要删除节点(与 get() 相同),然后将其从列表删除。...创建反向迭代器有助于发现问题和避免为了以不同顺序访问数据而重新排列节点。 其他方法 大多数不涉及添加或删除节点其他方法与单向链表相同。...双向链表添加一个节点复杂度从O(n)简化到O(1)。 但是,双向链表其他操作复杂性与单链表相同,基本都需要遍历列表很多节点。

18030

002 Linux内核双向链表经典实现

概要 本文对双向链表进行探讨,介绍内容是Linux内核双向链表经典实现和用法。其中,也会涉及到Linux内核中非常常用两个经典宏定义offsetof和container_of。...将offsetof看作一个数学问题来看待,问题就相当简单了:已知'整体'和该整体'某一个部分',要根据该部分地址,计算出整体地址。...Linux双向链表经典实现 1.Linux双向链表介绍 Linux双向链表定义主要涉及到两个文件: include/linux/types.h include/linux/list.h Linux...双向链表使用思想 它是将双向链表节点嵌套在其它结构体;在遍历链表时候,根据双链表节点指针获取"它所在结构体指针",从而再获取数据。...3.Linux双向链表使用示例 双向链表代码(list.h): 1 #ifndef _LIST_HEAD_H 2 #define _LIST_HEAD_H 3 // 双向链表节点 4 struct

1.8K20

双向链表优雅实现

文中涉及代码可访问 GitHub:https://github.com/UniqueDong/algorithms.git 上次我们说了「单向链表代码实现,今天带大家一起玩下双向链表双向链表节点比单项多了一个指针引用...双向链表就像渣男,跟「前女友」和「现女友」,还有一个「备胎』都保持联系。前女友就像是前驱节点,现女友就是 「当前 data」,而「next」指针就像是他套住备胎。...使用这样数据结构就能实现「进可攻退可守」灵活状态。 接下来让我们一起实现『渣男双向链表』。...prev; this.item = item; this.next = next; } } 代码实现 定义好渣男节点后,就开始实现我们双向链表...index; } index++; } } return -1; } 判断 链表是否存在

79730

图解Java数据结构之双向链表

上一篇文章说到了单链表,也通过案例具体实现了一下,但是单链表缺点也显而易见。 单向链表查找方向只能是一个方向 单向链表不能自我删除,需要靠辅助节点 而双向链表则能够很轻松地实现上面的功能。...何为双向链表 双向链表也叫双链表,是链表一种,它每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表任意一个结点开始,都可以很方便地访问它前驱结点和后继结点。...虽然只有这点不同,但是双向链表在增删改查实现上还是与单链表有很多不一样之处。...= newHero.nickname; } else { // 没有找到节点 System.out.println("没有找到"); } } // 从双向链表删除一个节点...,关于双向链表操作将非常简单,两者只是有一些细微差别,并无大变化。

1.3K10

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

循环链表   循环链表是一个收尾相接链表,将单链表最后一个指针域改由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

72920

双向链表增删改查

双向链表,我们曾经拿了一幅非常形象图片来形容他,就像几个人手拉手围成一个圈一样。在我们代码呈现就是每个节点都有一个指向下一个节点指针,同时也有一个指向上一个节点指针。...就因为新增了这个指向上一个节点指针特性,它解决了单向循环链表诸多问题,如下: 单链表结点都只有一个指向下一个结点指针 单链表数据元素无法直接访问其前驱元素 逆序访问单链表元素是极其耗时操作...(如图) 双向链表图形表示: 【实现代码】 因为插入和删除节点步骤跟单向循环链表差不多,只是多了一个前驱指针,我们这里值给出代码,具体插入和删除操作示例图就不一一列举了。...(DLinkList* list); //将游标重置指向链表第一个数据元素 DLinkListNode* DLinkList_Reset(DLinkList* list); //将游标移动指向到链表下一个数据元素...打印链表长度 printf(“打印链表长度, Length = %d\n”, DLinkList_Length(dlist)); //销毁双向链表 DLinkList_Destroy(dlist);

12010

JAVA链表回文链表结构

大家好,又见面了,我是你们朋友全栈君。 作为一个java初学者,最近遇到了回文链表结构这个难题,经过一番学习总算搞清楚个大概。 先来说一下什么是回文链表,会问链表在我们生活中经常能够遇到。...会问链表结构就是 例如:1->2->3->2->1。我们将它反转过来还是与原链表相同,这种就称为回文结构。...具体方法:1.先找到链表中间位置 2.然后将中间位置链表反转 3.从两边向中间遍历 代码如图 class Node {...this.data = data; this.next = null; } } public class MyLinkedList { public Node head;//保存单链表头节点引用...//找出链表中间位置 Node fast = this.head; Node slow = this.head; while(fast !

46610

双向链表类模板实现

全部代码加详细注释 List.hpp写法1----将迭代器类,节点类和链表类分开写,变量不统一,书写较麻烦 /***************Node结点定义************/ template...} //******************************************************************* }; /***************链表类模板定义...再调用赋值运算符重载 operator=(l); } //赋值运算符重载 const List& operator=(const List& L); //迭代器转换构造是在...再调用赋值运算符重载 operator=(l); } //赋值运算符重载 const List& operator=(const List& L); //迭代器转换构造是在...,那么在它之前必须加typename(除非是基类列表,或者在类初始化成员列表) 上面部分讲解有误,详细typename用法详情,可以参考下面这篇大佬写文章 typename详细用法

95410

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

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

58930

面试题47:Redislist双向链表

链表特点是高效删除和新增节点来灵活调整链表元素顺序。 由于C语言没有内置链表,所以Redis自己构建了链表实现。...Redis基本数据结构REDIS_LIST,底层实现之一就采用链表。即:当包含了很多元素,或者元素中有比较长字符串时,就会采用链表作为REDIS_LIST底层实现。...源码个注释如下所示: adlist.h /* * 双向链表节点 */ typedef struct listNode { // 前节点 struct listNode *prev;...// 后节点 struct listNode *next; // 本节点值 void *value; } listNode; adlist.h /* * 双向链表...带表头/表尾指针:list结构包含head指针和tail指针,所以获得链表头节点/尾节点复杂度为O(1)。

17910
领券