数据结构和算法

DSA 主页 DSA 概述 DSA 环境设置 DSA 算法基础 DSA 渐近分析

数据结构

DSA 数据结构基础 DSA 数据结构和类型 DSA 数组数据结构

链接列表

DSA 链接列表数据结构 DSA 双向链接列表数据结构 DSA 循环链表数据结构

堆栈 &队列

DSA 堆栈数据结构 DSA 表达式解析 DSA 队列数据结构

搜索算法

DSA 搜索算法 DSA 线性搜索算法 DSA 二分搜索算法 DSA 插值搜索 DSA 跳跃搜索算法 DSA 指数搜索 DSA 斐波那契搜索 DSA 子列表搜索 DSA 哈希表

排序算法

DSA 排序算法 DSA 冒泡排序算法 DSA 插入排序算法 DSA 选择排序算法 DSA 归并排序算法 DSA 希尔排序算法 DSA 堆排序 DSA 桶排序算法 DSA 计数排序算法 DSA 基数排序算法 DSA 快速排序算法

图形数据结构

DSA 图形数据结构 DSA 深度优先遍历 DSA 广度优先遍历 DSA 生成树

树数据结构

DSA 树数据结构 DSA 树遍历 DSA 二叉搜索树 DSA AVL 树 DSA 红黑树 DSA B树 DSA B+ 树 DSA 伸展树 DSA 尝试 DSA 堆数据结构

递归

DSA 递归算法 DSA 使用递归的汉诺塔 DSA 使用递归的斐波那契数列

分而治之

DSA 分而治之 DSA 最大最小问题 DSA 施特拉森矩阵乘法 DSA Karatsuba 算法

贪婪算法

DSA 贪婪算法 DSA 旅行商问题(贪婪方法) DSA Prim 最小生成树 DSA Kruskal 最小生成树 DSA Dijkstra 最短路径算法 DSA 地图着色算法 DSA 分数背包问题 DSA 作业排序截止日期 DSA 最佳合并模式算法

动态规划

DSA 动态规划 DSA 矩阵链乘法 DSA Floyd Warshall 算法 DSA 0-1 背包问题 DSA 最长公共子序列算法 DSA 旅行商问题(动态方法)

近似算法

DSA 近似算法 DSA 顶点覆盖算法 DSA 集合覆盖问题 DSA 旅行商问题(近似方法)

随机算法

DSA 随机算法 DSA 随机快速排序算法 DSA Karger 最小割算法 DSA Fisher-Yates 洗牌算法

DSA 有用资源

DSA 问答 DSA 快速指南


双向链表数据结构

什么是双向链表?

双向链表是链表的一种变体,与单链表相比,它可以轻松地向前和向后导航。以下是理解双向链表概念的重要术语。

  • Link − 链表的每个链接都可以存储一个称为元素的数据。

  • Next − 链表的每个链接都包含一个指向下一个链接的链接,称为"Next"。

  • Prev − 链表的每个链接都包含一个指向上一个链接的链接,称为"Prev"。

  • 链表 −链表包含指向第一个链接(称为 First)和最后一个链接(称为 Last)的连接链接。

双向链表表示

双向链表表示

根据上图,以下是需要考虑的要点。

  • 双向链表包含一个名为 first 和 last 的链接元素。

  • 每个链接都包含一个数据字段和一个称为 next 的链接字段。

  • 每个链接都通过其下一个链接与其下一个链接链接。

  • 每个链接都通过其上一个链接与其上一个链接链接。

  • 最后一个链接包含一个链接,如下所示null 标记列表末尾。

双向链表的基本操作

以下是列表支持的基本操作。

  • 插入 − 在列表开头添加一个元素。

  • 插入最后一个 − 在列表末尾添加一个元素。

  • 插入后 − 在列表的某个元素后添加一个元素。

  • 删除 − 删除列表开头的一个元素。

  • 删除最后一个 −从列表末尾删除一个元素。

  • 删除 − 使用键从列表中删除一个元素。

  • 向前显示 − 以正向方式显示完整列表。

  • 向后显示 − 以反向方式显示完整列表。

双向链表 - 在开头插入

在此操作中,我们创建一个包含三个隔间的新节点,一个包含数据,其他两个包含列表中前一个节点和后一个节点的地址。此新节点将插入到列表的开头。

算法

1. 开始
2. 创建一个包含三个变量的新节点:prev、data、next。
3. 将新数据存储到 data 变量中
4. 如果列表为空,则将新节点设为头节点。
5. 否则,将现有首节点的地址链接到
新节点的 next 变量,并将 prev 变量赋值为 null。
6. 将头节点指向新节点。
7. 结束

示例

以下是此操作在各种编程语言中的实现 −

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
struct node {
   int data;
   int key;
   struct node *next;
   struct node *prev;
};

//此链接始终指向第一个链接
struct node *head = NULL;

//此链接始终指向最后一个链接
struct node *last = NULL;
struct node *current = NULL;

//列表为空
bool isEmpty(){
   return head == NULL;
}

//显示双向链表
void printList(){
   struct node *ptr = head;
   while(ptr != NULL) {
      printf("(%d,%d) ",ptr->key,ptr->data);
      ptr = ptr->next;
   }
}

//在第一个位置插入链接
void insertFirst(int key, int data){

   //创建链接
   struct node *link = (struct node*) malloc(sizeof(struct node));
   link->key = key;
   link->data = data;
   if(isEmpty()) {

      //使其成为最后一个链接
      last = link;
   } else {

      //更新第一个上一个链接
      head->prev = link;
   }

   //将其指向旧的第一个链接
   link->next = head;

   //首先指向新的第一个链接
   head = link;
}
void main(){
   insertFirst(1,10);
   insertFirst(2,20);
   insertFirst(3,30);
   insertFirst(4,1);
   insertFirst(5,40);
   insertFirst(6,56);
   printf("
双向链表: ");
   printList();
}

输出

双向链表: (6,56) (5,40) (4,1) (3,30) (2,20) (1,10) 
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdbool>
struct node {
   int data;
   int key;
   struct node *next;
   struct node *prev;
};

//此链接始终指向第一个链接
struct node *head = NULL;

//此链接始终指向最后一个链接
struct node *last = NULL;
struct node *current = NULL;

//列表为空
bool isEmpty(){
   return head == NULL;
}

//显示双向链表
void printList(){
   struct node *ptr = head;
   while(ptr != NULL) {
      printf("(%d,%d) ",ptr->key,ptr->data);
      ptr = ptr->next;
   }
}

//在第一个位置插入链接
void insertFirst(int key, int data){

   //创建链接
   struct node *link = (struct node*) malloc(sizeof(struct node));
   link->key = key;
   link->data = data;
   if(isEmpty()) {

      //使其成为最后一个链接
      last = link;
   } else {

      //更新第一个上一个链接
      head->prev = link;
   }

   //将其指向旧的第一个链接
   link->next = head;

   //首先指向新的第一个链接
   head = link;
}
int main(){
   insertFirst(1,10);
   insertFirst(2,20);
   insertFirst(3,30);
   insertFirst(4,1);
   insertFirst(5,40);
   insertFirst(6,56);
   printf("双向链表: ");
   printList();
   return 0;
}

输出

双向链表: (6,56) (5,40) (4,1) (3,30) (2,20) (1,10) 
//双向链表的Java代码
import java.util.*;
class Node {
    public int data;
    public int key;
    public Node next;
    public Node prev;
    public Node(int data, int key) {
        this.data = data;
        this.key = key;
        this.next = null;
        this.prev = null;
    }
}
public class Main {
    //此链接始终指向第一个链接
    static Node head = null;
    //此链接始终指向最后一个链接
    static Node last = null;
    static Node current = null;
    // 列表为空
    public static boolean is_empty() {
        return head == null;
    }
    //显示双向链表
    public static void print_list() {
        Node ptr = head;
        while (ptr != null) {
            System.out.println("(" + ptr.key + "," + ptr.data + ")");
            ptr = ptr.next;
        }
    }
    //在第一个位置插入链接
    public static void insert_first(int key, int data) {
          //创建链接
        Node link = new Node(data, key);
        if (is_empty()) {
            //使其成为最后一个链接
            last = link;
        } else {
            //更新第一个上一个链接
            head.prev = link;
        }
        //将其指向旧的第一个链接
        link.next = head;
         //首先指向新的第一个链接
        head = link;
    }
    public static void main(String[] args) {
        insert_first(1, 10);
        insert_first(2, 20);
        insert_first(3, 30);
        insert_first(4, 1);
        insert_first(5, 40);
        insert_first(6, 56);
        System.out.println("双向链表: ");
        print_list();
    }
}

输出

双向链表: (6,56)(5,40)(4,1)(3,30)(2,20)(1,10)
#双向链表的Python代码
class Node:
    def __init__(self, data=None, key=None):
        self.data = data
        self.key = key
        self.next = None
        self.prev = None
#此链接始终指向第一个链接
head = None
#此链接始终指向最后一个链接
last = None
current = None
#列表为空
def is_empty():
    return head == None
#显示双向链表
def print_list():
    ptr = head
    while ptr != None:
        print(f"({ptr.key},{ptr.data})")
        ptr = ptr.next
#在第一个位置插入链接
def insert_first(key, data):
    global head, last
    #创建链接
    link = Node(data, key)
    if is_empty():
        #使其成为最后一个链接
        last = link
    else:
        #更新第一个上一个链接
        head.prev = link
    #将其指向旧的第一个链接
    link.next = head
    #首先指向新的第一个链接
    head = link
insert_first(1,10)
insert_first(2,20)
insert_first(3,30)
insert_first(4,1)
insert_first(5,40)
insert_first(6,56)
print("双向链表: ")
print_list()

输出

双向链表: 
(6,56) (5,40) (4,1) (3,30) (2,20) (1,10)

双向链表 - 尾部插入

在此插入操作中,如果链表非空,则将新的输入节点添加到双向链表的尾部。如果链表为空,则将头节点指向新节点。

算法

1. 开始
2. 如果链表为空,则将节点添加到链表并将头节点指向该节点。
3. 如果链表非空,则找到链表的最后一个节点。
4. 在链表的最后一个节点和新节点之间创建链接。
5. 新节点将指向 NULL,因为它是新的最后一个节点。
6. 结束

示例

以下是此操作在各种编程语言中的实现 −

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
struct node {
   int data;
   int key;
   struct node *next;
   struct node *prev;
};

//此链接始终指向第一个链接
struct node *head = NULL;

//此链接始终指向最后一个链接
struct node *last = NULL;
struct node *current = NULL;

//列表为空
bool isEmpty(){
   return head == NULL;
}

//显示双向链表
void printList(){
   struct node *ptr = head;
   while(ptr != NULL) {
      printf("(%d,%d) ",ptr->key,ptr->data);
      ptr = ptr->next;
   }
}

//在第一个位置插入链接
void insertFirst(int key, int data){

   //创建链接
   struct node *link = (struct node*) malloc(sizeof(struct node));
   link->key = key;
   link->data = data;
   if(isEmpty()) {

      //使其成为最后一个链接
      last = link;
   } else {

      //更新第一个上一个链接
      head->prev = link;
   }

   //将其指向旧的第一个链接
   link->next = head;

   //首先指向新的第一个链接
   head = link;
}

//在最后位置插入链接
void insertLast(int key, int data){
   
   //创建链接
   struct node *link = (struct node*) malloc(sizeof(struct node));
   link->key = key;
   link->data = data;
   if(isEmpty()) {

      //使其成为最后一个链接
      last = link;
   } else {

      //使链接成为新的最后一个链接
      last->next = link;

      //将旧的最后一个节点标记为新链接的上一个
      link->prev = last;
   }

   //指向最后一个新的最后一个节点
   last = link;
}
void main(){
   insertFirst(1,10);
   insertFirst(2,20);
   insertFirst(3,30);
   insertFirst(4,1);
   insertLast(5,40);
   insertLast(6,56);
   printf("双向链表: ");
   printList();
}

输出

双向链表: (4,1) (3,30) (2,20) (1,10) (5,40) (6,56)
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdbool>
struct node {
   int data;
   int key;
   struct node *next;
   struct node *prev;
};

//此链接始终指向第一个链接
struct node *head = NULL;

//此链接始终指向最后一个链接
struct node *last = NULL;
struct node *current = NULL;

//列表为空
bool isEmpty(){
   return head == NULL;
}

//显示双向链表
void printList(){
   struct node *ptr = head;
   while(ptr != NULL) {
      printf("(%d,%d) ",ptr->key,ptr->data);
      ptr = ptr->next;
   }
}

//在第一个位置插入链接
void insertFirst(int key, int data){

   //创建链接
   struct node *link = (struct node*) malloc(sizeof(struct node));
   link->key = key;
   link->data = data;
   if(isEmpty()) {

      //使其成为最后一个链接
      last = link;
   } else {

      //更新第一个上一个链接
      head->prev = link;
   }

   //将其指向旧的第一个链接
   link->next = head;

   //首先指向新的第一个链接
   head = link;
}

//在最后位置插入链接
void insertLast(int key, int data){

   //创建链接
   struct node *link = (struct node*) malloc(sizeof(struct node));
   link->key = key;
   link->data = data;
   if(isEmpty()) {

      //使其成为最后一个链接
      last = link;
   } else {

      //使链接成为新的最后一个链接
      last->next = link;

      //将旧的最后一个节点标记为新链接的上一个
      link->prev = last;
   }

   //指向最后一个新的最后一个节点
   last = link;
}
int main(){
   insertFirst(1,10);
   insertFirst(2,20);
   insertFirst(3,30);
   insertFirst(4,1);
   insertLast(5,40);
   insertLast(6,56);
   printf("双向链表: ");
   printList();
   return 0;
}

输出

双向链表: (4,1) (3,30) (2,20) (1,10) (5,40) (6,56) 
import java.util.*;
class Node {
    public int data;
    public int key;
    public Node next;
    public Node prev;
    public Node(int data, int key) {
        this.data = data;
        this.key = key;
        this.next = null;
        this.prev = null;
    }
}
public class Main {
    static Node head = null;
    static Node last = null;
    static Node current = null;
    public static boolean isEmpty() {
        return head == null;
    } 
    public static void printList() {
        Node ptr = head;
        while (ptr != null) {
            System.out.print("(" + ptr.key + "," + ptr.data + ") ");
            ptr = ptr.next;
        }
    }
    public static void insertFirst(int key, int data) {
        Node link = new Node(data, key);
        if (isEmpty()) {
            last = link;
        } else {
            head.prev = link;
        }
        link.next = head;
        head = link;
    }
    public static void insertLast(int key, int data) {
        Node link = new Node(data, key);
        if (isEmpty()) {
            last = link;
        } else {
            last.next = link;
            link.prev = last;
        }
        last = link;
    }
    
    public static void main(String[] args) {
        insertFirst(1,10);
        insertFirst(2,20);
        insertFirst(3,30);
        insertFirst(4,1);
        insertLast(5,40);
        insertLast(6,56);
        System.out.print("双向链表: ");
        printList();
    }
}

输出

双向链表: (4,1) (3,30) (2,20) (1,10) (5,40) (6,56)
class Node:
    def __init__(self, data=None, key=None):
        self.data = data
        self.key = key
        self.next = None
        self.prev = None
head = None
last = None
current = None
def isEmpty():
    return head == None
def printList():
    ptr = head
    while ptr != None:
        print(f"({ptr.key},{ptr.data})", end=" ")
        ptr = ptr.next
def insertFirst(key, data):
    global head, last
    link = Node(data, key)
    if isEmpty():
        last = link
    else:
        head.prev = link
    link.next = head
    head = link
def insertLast(key, data):
    global head, last
    link = Node(data, key)
    if isEmpty():
        last = link
    else:
        last.next = link
        link.prev = last
    last = link
insertFirst(1,10)
insertFirst(2,20)
insertFirst(3,30)
insertFirst(4,1)
insertLast(5,40)
insertLast(6,56)
print("双向链表: ", end="")
printList()

输出

双向链表: (4,1) (3,30) (2,20) (1,10) (5,40) (6,56)

双向链表 - 从头删除

此删除操作会删除双向链表中现有的第一个节点。链表头会移至下一个节点,并且链接会被移除。

算法

1. 开始
2. 检查双向链表的状态
3. 如果链表为空,则无法删除
4. 如果链表不为空,则链表头指针会
移至下一个节点。
5. 结束

示例

以下是此操作在各种编程语言中的实现 −

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
struct node {
   int data;
   int key;
   struct node *next;
   struct node *prev;
};

//此链接始终指向第一个链接
struct node *head = NULL;

//此链接始终指向最后一个链接
struct node *last = NULL;
struct node *current = NULL;

//列表为空
bool isEmpty(){
   return head == NULL;
}

//显示双向链表
void printList(){
   struct node *ptr = head;
   while(ptr != NULL) {
      printf("(%d,%d) ",ptr->key,ptr->data);
      ptr = ptr->next;
   }
}

//在第一个位置插入链接
void insertFirst(int key, int data){

   //创建链接
   struct node *link = (struct node*) malloc(sizeof(struct node));
   link->key = key;
   link->data = data;
   if(isEmpty()) {

      //使其成为最后一个链接
      last = link;
   } else {

      //更新第一个上一个链接
      head->prev = link;
   }

   //将其指向旧的第一个链接
   link->next = head;

   //首先指向新的第一个链接
   head = link;
}

//删除第一项
struct node* deleteFirst(){

   //保存对第一个链接的引用
   struct node *tempLink = head;

   //如果只有一个链接
   if(head->next == NULL) {
      last = NULL;
   } else {
      head->next->prev = NULL;
   }
   head = head->next;

   //返回已删除的链接
   return tempLink;
}
void main(){
   insertFirst(1,10);
   insertFirst(2,20);
   insertFirst(3,30);
   insertFirst(4,1);
   insertFirst(5,40);
   insertFirst(6,56);
   printf("双向链表: 
");
   printList();
   printf("
删除第一条记录后的列表:
");
   deleteFirst();
   printList();
}

输出

双向链表: (6,56) (5,40) (4,1) (3,30) (2,20) (1,10) 
删除第一条记录后的列表:(5,40) (4,1) (3,30) (2,20) (1,10) 
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdbool>
struct node {
   int data;
   int key;
   struct node *next;
   struct node *prev;
};

//此链接始终指向第一个链接
struct node *head = NULL;

//此链接始终指向最后一个链接
struct node *last = NULL;
struct node *current = NULL;

//列表为空
bool isEmpty(){
   return head == NULL;
}

//显示双向链表
void printList(){
   struct node *ptr = head;
   while(ptr != NULL) {
      printf("(%d,%d) ",ptr->key,ptr->data);
      ptr = ptr->next;
   }
}

//在第一个位置插入链接
void insertFirst(int key, int data){

   //创建链接
   struct node *link = (struct node*) malloc(sizeof(struct node));
   link->key = key;
   link->data = data;
   if(isEmpty()) {

      //使其成为最后一个链接
      last = link;
   } else {

      //更新第一个上一个链接
      head->prev = link;
   }

   //将其指向旧的第一个链接
   link->next = head;

   //首先指向新的第一个链接
   head = link;
}

//删除第一项
struct node* deleteFirst(){

   //保存对第一个链接的引用
   struct node *tempLink = head;

   //如果只有一个链接
   if(head->next == NULL) {
      last = NULL;
   } else {
      head->next->prev = NULL;
   }
   head = head->next;

   //返回已删除的链接
   return tempLink;
}
int main(){
   insertFirst(1,10);
   insertFirst(2,20);
   insertFirst(3,30);
   insertFirst(4,1);
   insertFirst(5,40);
   insertFirst(6,56);
   printf("双向链表: 
");
   printList();
   printf("
删除第一条记录后的列表:
");
   deleteFirst();
   printList();
   return 0;
}

输出

双向链表: 
(6,56) (5,40) (4,1) (3,30) (2,20) (1,10) 
删除第一条记录后的列表:
(5,40) (4,1) (3,30) (2,20) (1,10) 
//双向链表的Java代码
import java.util.*;
class Node {
    public int data;
    public int key;
    public Node next;
    public Node prev;
    public Node(int data, int key) {
        this.data = data;
        this.key = key;
        this.next = null;
        this.prev = null;
    }
}
public class Main {
    //此链接始终指向第一个链接
    public static Node head = null;
    //此链接始终指向最后一个链接
    public static Node last = null;
    //this link always point to current Link
    public static Node current = null;
    //列表为空
    public static boolean isEmpty() {
        return head == null;
    }
    //显示双向链表
    public static void printList() {
        Node ptr = head;
        while (ptr != null) {
            System.out.print("(" + ptr.key + "," + ptr.data + ") ");
            ptr = ptr.next;
        }
    }
    //在第一个位置插入链接
    public static void insertFirst(int key, int data) {
        //创建链接
        Node link = new Node(data, key);
        if (isEmpty()) {
            //使其成为最后一个链接
            last = link;
        } else {
            //更新第一个上一个链接
            head.prev = link;
        }
        //将其指向旧的第一个链接
        link.next = head;
        head = link;
    }
    //delete the first item
    public static Node deleteFirst() {
        //保存对第一个链接的引用
        Node tempLink = head;
        //如果只有一个链接
        if (head.next == null) {
            last = null;
        } else {
            head.next.prev = null;
        }
        head = head.next;
        //返回已删除的链接
        return tempLink;
    }
    public static void main(String[] args) {
        insertFirst(1, 10);
        insertFirst(2, 20);
        insertFirst(3, 30);
        insertFirst(4, 1);
        insertFirst(5, 40);
        insertFirst(6, 56);
        System.out.print("双向链表: 
");
        printList();
        System.out.print("
删除第一条记录后的列表:
");
        deleteFirst();
        printList();
    }
}

输出

双向链表: 
(6,56) (5,40) (4,1) (3,30) (2,20) (1,10) 
删除第一条记录后的列表:
(5,40) (4,1) (3,30) (2,20) (1,10) 
#Python code for doubly linked list
class Node:
    def __init__(self, data=None, key=None):
        self.data = data
        self.key = key
        self.next = None
        self.prev = None
#此链接始终指向第一个链接
head = None
#此链接始终指向最后一个链接
last = None
current = None
#列表为空
def isEmpty():
    return head == None
#显示双向链表
def printList():
    ptr = head
    while ptr != None:
        print(f"({ptr.key},{ptr.data}) ", end="")
        ptr = ptr.next
#在第一个位置插入链接
def insertFirst(key, data):
    #创建链接
    global head, last
    link = Node(data, key)
    if isEmpty():
        #使其成为最后一个链接
        last = link
    else:
        #更新第一个上一个链接
        head.prev = link
    #将其指向旧的第一个链接
    link.next = head
    head = link
#delete first item
def deleteFirst():
     #保存对第一个链接的引用
    global head, last
    tempLink = head
    #if only one link
    if head.next == None:
        last = None
    else:
        head.next.prev = None
    head = head.next
    #返回已删除的链接
    return tempLink
insertFirst(1,10)
insertFirst(2,20)
insertFirst(3,30)
insertFirst(4,1)
insertFirst(5,40)
insertFirst(6,56)
print("双向链表:")
printList()
print("
List after deleting first record:")
deleteFirst()
printList()

输出

双向链表: 
(6,56) (5,40) (4,1) (3,30) (2,20) (1,10) 
删除第一条记录后的列表:
(5,40) (4,1) (3,30) (2,20) (1,10) 

双向链表 - 完整实现

以下是各种编程语言中双向链表的完整实现 −

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
struct node {
   int data;
   int key;
   struct node *next;
   struct node *prev;
};

//此链接始终指向第一个链接
struct node *head = NULL;

//此链接始终指向最后一个链接
struct node *last = NULL;
struct node *current = NULL;

//列表为空
bool isEmpty(){
   return head == NULL;
}

//按从头到尾的顺序显示列表
void displayForward(){

   //从头开始
   struct node *ptr = head;

   //导航至列表末尾
   printf("
[ ");
   while(ptr != NULL) {
      printf("(%d,%d) ",ptr->key,ptr->data);
      ptr = ptr->next;
   }
   printf(" ]");
}

//从最后一个元素到第一个元素显示列表
void displayBackward(){

    //从最后一个元素开始
    struct node *ptr = last;
    
    //导航到列表开头
   printf("
[ ");
   while(ptr != NULL) {

      //打印数据
      printf("(%d,%d) ",ptr->key,ptr->data);

      //移动到下一个项目
      ptr = ptr ->prev;
      printf(" ");
   }
   printf(" ]");
}

//在第一个位置插入链接
void insertFirst(int key, int data){

   //创建链接
   struct node *link = (struct node*) malloc(sizeof(struct node));
   link->key = key;
   link->data = data;
   if(isEmpty()) {

      //使其成为最后一个链接
      last = link;
   } else {

      //更新第一个上一个链接
      head->prev = link;
   }

   //将其指向旧的第一个链接
   link->next = head;

   //首先指向新的第一个链接
   head = link;
}

//在最后位置插入链接
void insertLast(int key, int data){

   //创建链接
   struct node *link = (struct node*) malloc(sizeof(struct node));
   link->key = key;
   link->data = data;
   if(isEmpty()) {

      //使其成为最后一个链接
      last = link;
   } else {

      //使链接成为新的最后一个链接
      last->next = link;

      //将旧的最后一个节点标记为新链接的上一个
      link->prev = last;
   }

   //指向最后一个新的最后一个节点
   last = link;
}

//删除第一项
struct node* deleteFirst(){

   //保存对第一个链接的引用
   struct node *tempLink = head;

   //如果只有一个链接
   if(head->next == NULL) {
      last = NULL;
   } else {
      head->next->prev = NULL;
   }
   head = head->next;

   //返回已删除的链接
   return tempLink;
}

//删除最后一个位置的链接
struct node* deleteLast(){

   //保存对最后一个链接的引用
   struct node *tempLink = last;

   //如果只有一个链接
   if(head->next == NULL) {
      head = NULL;
   } else {
      last->prev->next = NULL;
   }
   last = last->prev;

   //返回已删除的链接
   return tempLink;
}

//删除具有给定键的链接
struct node* delete(int key){

   //从第一个链接开始
   struct node* current = head;
   struct node* previous = NULL;

   //如果列表为空
   if(head == NULL) {
      return NULL;
   }

   //浏览列表
   while(current->key != key) {

      //如果它是最后一个节点
      if(current->next == NULL) {
         return NULL;
      } else {

         //存储对当前链接的引用
         previous = current;

         //移至下一个链接
         current = current->next;
      }
   }

   //找到匹配项,更新链接
   if(current == head) {

      //更改第一个链接以指向下一个链接
      head = head->next;
   } else {

      //绕过当前链接
      current->prev->next = current->next;
   }
   if(current == last) {

      //将最后一个链接更改为指向上一个链接
      last = current->prev;
   } else {
      current->next->prev = current->prev;
   }
   return current;
}
bool insertAfter(int key, int newKey, int data){

   //从第一个链接开始
   struct node *current = head;

   //如果列表为空
   if(head == NULL) {
      return false;
   }

   //浏览列表
   while(current->key != key) {

      //如果它是最后一个节点
      if(current->next == NULL) {
         return false;
      } else {

         //移至下一个链接
         current = current->next;
      }
   }

   //创建链接
   struct node *newLink = (struct node*) malloc(sizeof(struct node));
   newLink->key = key;
   newLink->data = data;
   if(current == last) {
      newLink->next = NULL;
      last = newLink;
   } else {
      newLink->next = current->next;
      current->next->prev = newLink;
   }
   newLink->prev = current;
   current->next = newLink;
   return true;
}
int main(){
   insertFirst(1,10);
   insertFirst(2,20);
   insertFirst(3,30);
   insertFirst(4,1);
   insertFirst(5,40);
   insertFirst(6,56);
   printf("
List (First to Last): ");
   displayForward();
   printf("
");
   printf("
List (Last to first): ");
   displayBackward();
   printf("
List , after deleting first record: ");
   deleteFirst();
   displayForward();
   printf("
List , after deleting last record: ");
   deleteLast();
   displayForward();
   printf("
List , insert after key(4) : ");
   insertAfter(4,7, 13);
   displayForward();
   printf("
List , after delete key(4) : ");
   delete(4);
   displayForward();
}

输出

List (First to Last): 
[ (6,56) (5,40) (4,1) (3,30) (2,20) (1,10)  ]

List (Last to first): 
[ (1,10)  (2,20)  (3,30)  (4,1)  (5,40)  (6,56)   ]
List , after deleting first record: 
[ (5,40) (4,1) (3,30) (2,20) (1,10)  ]
List , after deleting last record: 
[ (5,40) (4,1) (3,30) (2,20)  ]
List , insert after key(4) : 
[ (5,40) (4,1) (4,13) (3,30) (2,20)  ]
List , after delete key(4) : 
[ (5,40) (4,13) (3,30) (2,20)  ]
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdbool>
using namespace std;
struct node {
   int data;
   int key;
   struct node *next;
   struct node *prev;
};

//此链接始终指向第一个链接
struct node *head = NULL;

//此链接始终指向最后一个链接
struct node *last = NULL;
struct node *current = NULL;

//列表为空
bool isEmpty(){
   return head == NULL;
}
//按从头到尾的顺序显示列表
void displayForward(){

   //从头开始
   struct node *ptr = head;

   //导航至列表末尾
   cout << "
[ ";
   while(ptr != NULL) {
      cout << "(" << ptr->key << "," << ptr->data << ")";
      ptr = ptr->next;
   }
   cout << " ]" << endl;
}

//从最后到第一显示列表
void displayBackward(){

   //从最后一个开始
   struct node *ptr = last;

   //导航至列表开头
   cout << "
[ ";
   while(ptr != NULL) {

      //打印数据
      cout << "(" << ptr->key << "," << ptr->data << ")";

      //移动到下一个项目
      ptr = ptr ->prev;
      cout << " ";
   }
   cout << " ]" << endl;
}

//在第一个位置插入链接
void insertFirst(int key, int data){

   //创建链接
   struct node *link = (struct node*) malloc(sizeof(struct node));
   link->key = key;
   link->data = data;
   if(isEmpty()) {

      //使其成为最后一个链接
      last = link;
   } else {

      //更新第一个上一个链接
      head->prev = link;
   }

   //将其指向旧的第一个链接
   link->next = head;

   //首先指向新的第一个链接
   head = link;
}

//在最后位置插入链接
void insertLast(int key, int data){

   //创建链接
   struct node *link = (struct node*) malloc(sizeof(struct node));
   link->key = key;
   link->data = data;
   if(isEmpty()) {

      //使其成为最后一个链接
      last = link;
   } else {

      //使链接成为新的最后一个链接
      last->next = link;

      //将旧的最后一个节点标记为新链接的上一个
      link->prev = last;
   }

   //指向最后一个新的最后一个节点
   last = link;
}

//删除第一项
struct node* deleteFirst(){

   //保存对第一个链接的引用
   struct node *tempLink = head;

   //如果只有一个链接
   if(head->next == NULL) {
      last = NULL;
   } else {
      head->next->prev = NULL;
   }
   head = head->next;

   //返回已删除的链接
   return tempLink;
}

//删除最后一个位置的链接
struct node* deleteLast(){

   //保存对最后一个链接的引用
   struct node *tempLink = last;

   //如果只有一个链接
   if(head->next == NULL) {
      head = NULL;
   } else {
      last->prev->next = NULL;
   }
   last = last->prev;

   //返回已删除的链接
   return tempLink;
}

//删除具有给定键的链接
struct node* deletenode(int key){

   //从第一个链接开始
   struct node* current = head;
   struct node* previous = NULL;

   //如果列表为空
   if(head == NULL) {
      return NULL;
   }

   //浏览列表
   while(current->key != key) {

      //如果它是最后一个节点
      if(current->next == NULL) {
         return NULL;
      } else {

         //存储对当前链接的引用
         previous = current;

         //移至下一个链接
         current = current->next;
      }
   }

   //找到匹配项,更新链接
   if(current == head) {

      //更改第一个链接以指向下一个链接
      head = head->next;
   } else {
      
      //绕过当前链接
      current->prev->next = current->next;
   }
   if(current == last) {

      //将最后一个链接更改为指向上一个链接
      last = current->prev;
   } else {
      current->next->prev = current->prev;
   }
   return current;
}
bool insertAfter(int key, int newKey, int data){

   //从第一个链接开始
   struct node *current = head;

   //如果列表为空
   if(head == NULL) {
      return false;
   }

   //浏览列表
   while(current->key != key) {

      //如果它是最后一个节点
      if(current->next == NULL) {
         return false;
      } else {

         //移至下一个链接
         current = current->next;
      }
   }

   //创建链接
   struct node *newLink = (struct node*) malloc(sizeof(struct node));
   newLink->key = key;
   newLink->data = data;
   if(current == last) {
      newLink->next = NULL;
      last = newLink;
   } else {
      newLink->next = current->next;
      current->next->prev = newLink;
   }
   newLink->prev = current;
   current->next = newLink;
   return true;
}
int main(){
   insertFirst(1,10);
   insertFirst(2,20);
   insertFirst(3,30);
   insertFirst(4,1);
   insertFirst(5,40);
   insertFirst(6,56);
   printf("
List (First to Last): ");
   displayForward();
   printf("
");
   printf("
List (Last to first): ");
   displayBackward();
   printf("
List , after deleting first record: ");
   deleteFirst();
   displayForward();
   printf("
List , after deleting last record: ");
   deleteLast();
   displayForward();
   printf("
List , insert after key(4) : ");
   insertAfter(4, 7, 13);
   displayForward();
   printf("
List , after delete key(4) : ");
   deletenode(4);
   displayForward();
   return 0;
}

输出

List (First to Last):
[ (6, 56) (5, 40) (4, 1) (3, 30) (2, 20) (1, 10) ]

List (Last to First):
[ (1, 10) (2, 20) (3, 30) (4, 1) (5, 40) (6, 56) ]
List, after deleting first record:
[ (5, 40) (4, 1) (3, 30) (2, 20) (1, 10) ]
List, after deleting last record:
[ (5, 40) (4, 1) (3, 30) (2, 20) ]
List, insert after key(4):
[ (5, 40) (4, 1) (7, 13) (3, 30) (2, 20) ]
List, after delete key(4):
[ (5, 40) (7, 13) (3, 30) (2, 20) ]
class Node {
    int data;
    int key;
    Node next;
    Node prev;

    public Node(int key, int data) {
        this.key = key;
        this.data = data;
        this.next = null;
        this.prev = null;
    }
}

class DoublyLinkedList {
    Node head;
    Node last;

    boolean isEmpty() {
        return head == null;
    }

    void displayForward() {
        Node ptr = head;
        System.out.print("[ ");
        while (ptr != null) {
            System.out.print("(" + ptr.key + "," + ptr.data + ") ");
            ptr = ptr.next;
        }
        System.out.println("]");
    }

    void displayBackward() {
        Node ptr = last;
        System.out.print("[ ");
        while (ptr != null) {
            System.out.print("(" + ptr.key + "," + ptr.data + ") ");
            ptr = ptr.prev;
        }
        System.out.println("]");
    }

    void insertFirst(int key, int data) {
        Node link = new Node(key, data);
        if (isEmpty()) {
            last = link;
        } else {
            head.prev = link;
        }
        link.next = head;
        head = link;
    }

    void insertLast(int key, int data) {
        Node link = new Node(key, data);
        if (isEmpty()) {
            last = link;
        } else {
            last.next = link;
            link.prev = last;
        }
        last = link;
    }

    Node deleteFirst() {
        if (isEmpty()) {
            return null;
        }
        Node tempLink = head;
        if (head.next == null) {
            last = null;
        } else {
            head.next.prev = null;
        }
        head = head.next;
        return tempLink;
    }

    Node deleteLast() {
        if (isEmpty()) {
            return null;
        }
        Node tempLink = last;
        if (head.next == null) {
            head = null;
        } else {
            last.prev.next = null;
        }
        last = last.prev;
        return tempLink;
    }

    Node delete(int key) {
        Node current = head;
        Node previous = null;
        if (head == null) {
            return null;
        }
        while (current.key != key) {
            if (current.next == null) {
                return null;
            } else {
                previous = current;
                current = current.next;
            }
        }
        if (current == head) {
            head = head.next;
        } else {
            current.prev.next = current.next;
        }
        if (current == last) {
            last = current.prev;
        } else {
            current.next.prev = current.prev;
        }
        return current;
    }

    boolean insertAfter(int key, int newKey, int data) {
        Node current = head;
        if (head == null) {
            return false;
        }
        while (current.key != key) {
            if (current.next == null) {
                return false;
            } else {
                current = current.next;
            }
        }
        Node newLink = new Node(newKey, data);
        if (current == last) {
            newLink.next = null;
            last = newLink;
        } else {
            newLink.next = current.next;
            current.next.prev = newLink;
        }
        newLink.prev = current;
        current.next = newLink;
        return true;
    }
}

public class Main {
    public static void main(String[] args) {
        DoublyLinkedList dll = new DoublyLinkedList();
        dll.insertFirst(1, 10);
        dll.insertFirst(2, 20);
        dll.insertFirst(3, 30);
        dll.insertFirst(4, 1);
        dll.insertFirst(5, 40);
        dll.insertFirst(6, 56);
        System.out.println("List (First to Last):");
        dll.displayForward();
        System.out.println();
        System.out.println("List (Last to First):");
        dll.displayBackward();
        System.out.println("List, after deleting first record:");
        dll.deleteFirst();
        dll.displayForward();
        System.out.println("List, after deleting last record:");
        dll.deleteLast();
        dll.displayForward();
        System.out.println("List, insert after key(4):");
        dll.insertAfter(4, 7, 13);
        dll.displayForward();
        System.out.println("List, after delete key(4):");
        dll.delete(4);
        dll.displayForward();
    }
}

输出

List (First to Last):
[ (6, 56) (5, 40) (4, 1) (3, 30) (2, 20) (1, 10) ]

List (Last to First):
[ (1, 10) (2, 20) (3, 30) (4, 1) (5, 40) (6, 56) ]
List, after deleting first record:
[ (5, 40) (4, 1) (3, 30) (2, 20) (1, 10) ]
List, after deleting last record:
[ (5, 40) (4, 1) (3, 30) (2, 20) ]
List, insert after key(4):
[ (5, 40) (4, 1) (7, 13) (3, 30) (2, 20) ]
List, after delete key(4):
[ (5, 40) (7, 13) (3, 30) (2, 20) ]
class Node:
    def __init__(self, key, data):
        self.key = key
        self.data = data
        self.next = None
        self.prev = None

class DoublyLinkedList:
    def __init__(self):
        self.head = None
        self.last = None

    def is_empty(self):
        return self.head is None

    def display_forward(self):
        ptr = self.head
        print("[", end=" ")
        while ptr:
            print("({}, {})".format(ptr.key, ptr.data), end=" ")
            ptr = ptr.next
        print("]")

    def display_backward(self):
        ptr = self.last
        print("[", end=" ")
        while ptr:
            print("({}, {})".format(ptr.key, ptr.data), end=" ")
            ptr = ptr.prev
        print("]")

    def insert_first(self, key, data):
        link = Node(key, data)
        if self.is_empty():
            self.last = link
        else:
            self.head.prev = link
        link.next = self.head
        self.head = link

    def insert_last(self, key, data):
        link = Node(key, data)
        if self.is_empty():
            self.last = link
        else:
            self.last.next = link
            link.prev = self.last
        self.last = link

    def delete_first(self):
        if self.is_empty():
            return None
        temp_link = self.head
        if self.head.next is None:
            self.last = None
        else:
            self.head.next.prev = None
        self.head = self.head.next
        return temp_link

    def delete_last(self):
        if self.is_empty():
            return None
        temp_link = self.last
        if self.head.next is None:
            self.head = None
        else:
            self.last.prev.next = None
        self.last = self.last.prev
        return temp_link

    def delete(self, key):
        current = self.head
        while current and current.key != key:
            current = current.next
        if current is None:
            return None
        if current == self.head:
            self.head = self.head.next
        else:
            current.prev.next = current.next
        if current == self.last:
            self.last = current.prev
        else:
            current.next.prev = current.prev
        return current

    def insert_after(self, key, new_key, data):
        current = self.head
        while current and current.key != key:
            current = current.next
        if current is None:
            return False
        new_link = Node(new_key, data)
        if current == self.last:
            new_link.next = None
            self.last = new_link
        else:
            new_link.next = current.next
            current.next.prev = new_link
        new_link.prev = current
        current.next = new_link
        return True

# Example usage
dll = DoublyLinkedList()
dll.insert_first(1, 10)
dll.insert_first(2, 20)
dll.insert_first(3, 30)
dll.insert_first(4, 1)
dll.insert_first(5, 40)
dll.insert_first(6, 56)
print("List (First to Last):")
dll.display_forward()
print()
print("List (Last to First):")
dll.display_backward()
print("List, after deleting first record:")
dll.delete_first()
dll.display_forward()
print("List, after deleting last record:")
dll.delete_last()
dll.display_forward()
print("List, insert after key(4):")
dll.insert_after(4, 7, 13)
dll.display_forward()
print("List, after delete key(4):")
dll.delete(4)
dll.display_forward()	

输出

List (First to Last):
[ (6, 56) (5, 40) (4, 1) (3, 30) (2, 20) (1, 10) ]

List (Last to First):
[ (1, 10) (2, 20) (3, 30) (4, 1) (5, 40) (6, 56) ]
List, after deleting first record:
[ (5, 40) (4, 1) (3, 30) (2, 20) (1, 10) ]
List, after deleting last record:
[ (5, 40) (4, 1) (3, 30) (2, 20) ]
List, insert after key(4):
[ (5, 40) (4, 1) (7, 13) (3, 30) (2, 20) ]
List, after delete key(4):
[ (5, 40) (7, 13) (3, 30) (2, 20) ]