数据结构与算法----双向链表

本文详细介绍了双向链表的创建、初始化、插入、删除、修改和查找等操作,并通过图解方式展示了各种情况下的具体实现步骤,帮助读者深入理解双向链表的工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

PS:前面已经说过线性表的两种表现形式,一种是顺序,另一种是链式,链式的一种普通表现形式就是加入一个指针,前一个的指针指向后一个结点的地址,那么还有一种形式就是双向链表,里面又加上了一个指针变量,让前指针变量指向直接前驱,后指针变量指向直接后继。

/**
 * 创建结构体
 * */
typedef struct DoubleLink {
    int data;
    struct DoubleLink *prior;
    struct DoubleLink *next;
} DoubleLink, *DoubleLinkL;

创建双向链表并初始化

注:这里我们是只创建了一个空的链表,内部无数据,所以首结点的两个指针变量要为NULL。

/**
 * 初始化
 * */
DoubleLinkL initLink() {
    DoubleLinkL L = (DoubleLinkL) malloc(sizeof(DoubleLink));
    L->next = NULL;
    L->prior = NULL;
    return L;
}

开始插入数据

在插入数据之前我们要考虑一个事情就是,链表中有数据和无数据的插入是否一样,也就是说指针改变是否一致,在左右都有值的时候平时要改变4条线,那么如果只有首结点的话移动几条呢。

其实可以说是移动3条,但画图的话就看到两条。

如图:

::|::

 

首先当只要一个首结点或者在最后一个结点插入的情况下,如第一个图,

    
 s->next = p->next;
        s->prior = p;
        p->next = s;

当前后都有结点的时候,如第二个图

   
  s->next = p->next;
        s->prior = p;
        p->next = s;
        s->next->prior = s;

整体插入代码就是

int insertLink(DoubleLinkL &L, int pos, int e) {
    DoubleLinkL p = L;
    int i = 0;
    while (p && i < pos-1) {
        p = p->next;
        i++;
    }
    if (!p || i > pos-1) {
        printf("插入失败,下标问题\n");
        return -1;
    }
    DoubleLinkL s = (DoubleLinkL) malloc(sizeof(DoubleLink));
    s->data = e;
    if (p->next == NULL) {
        s->next = p->next;
        s->prior = p;
        p->next = s;
    } else {
        s->next = p->next;
        s->prior = p;
        p->next = s;
        s->next->prior = s;
    }
    return 0;
}

删除图解

对于删除比较简单,在前后都有结点的情况下,如图一,如果本来只要一个结点,前面是首结点的情况下,直接把首结点的next指向NULL即可。(本人画图不怎么样不要在意)

 

p->next->next->prior=p;//一定要写在该位置。
p->next=p->next->next;

如果首结点后只有一个结点

p->next=NULL;

删除全部代码

int deleteLink(DoubleLinkL &L,int pos,int e){
    DoubleLinkL p = L;
    int i = 0;
    while (p && i < pos-1) {
        p = p->next;
        i++;
    }
    if (!p || i > pos-1) {
        printf("插入失败,下标问题\n");
        return -1;
    }
    if(p->next==NULL){
        p->next=NULL;
    }else{
        p->next->next->prior=p;//一定要写在该位置。
        p->next=p->next->next;
    }
    return 0;
 }

修改和查找

这个修改和查找是比较简单的,直接找到知道该结点修改就完事了,干就对了。

int getElem(DoubleLinkL L,int pos){
     DoubleLinkL p = L;
     int i = 0;
     while (p && i < pos) {
         p = p->next;
         i++;
     }
     if (!p || i > pos) {
         printf("查找失败,下标问题\n");
         return -1;
     }
     printf("查找的数据:%d\n",p->data);
     return 0;
 }
 int updataLink(DoubleLinkL &L,int pos,int e){
     DoubleLinkL p = L;
     int i = 0;
     while (p && i < pos) {
         p = p->next;
         i++;
     }
     if (!p || i > pos) {
         printf("修改失败,下标问题\n");
         return -1;
     }
     p->data=e;
     return 0;
 }

总结:双向链表主要是插入和删除复杂点,其他的和单链表都差不多,双向链表存在着4条指向线先后顺序,如果连接顺序不正确,断开后的数据就会丢失。

 

### 链表的概念 链表是一种线性数据结构,其中的元素不是连续存储在内存中的。相反,这些元素通过指针链接在一起形成一个序列。每个节点包含两部分:一部分用于保存实际的数据;另一部分是一个指向下一个节点的引用(即指针)。这种特性使得向列表中插入新项变得非常容易。 对于单向链表而言,每个结点只含有向前遍历到下一结点的信息[^1]。而双向链表则允许更灵活的操作因为它不仅有前驱还有后继两个方向上的连接关系[^3]。 ### 存储方式 链表采用的是链式存储的方式,这意味着它并不像数组那样依赖于固定的地址空间来容纳所有的元素。因此当涉及到频繁增删操作时效率更高因为不需要移动其他位置上已有的记录就可以完成调整工作[^2]。 ### 应用场景 由于其独特的性质,链表被广泛应用于各种编程任务当中: - **实现 LRU 缓存淘汰算法**:最近最少使用的页面会被标记为可替换目标并最终移除; - 文件系统内的文件块分配机制可以借助链表来进行管理; - 数据流处理过程中充当临时储存容器的角色以应对突发性的大量输入/输出请求等情形下的缓冲需求。 ### Python 中简单链表的实现 以下是使用Python编写的简易版单项链表类定义及其基本功能展示: ```python class Node: def __init__(self, data=None): self.data = data self.next = None class LinkedList: def __init__(self): self.head = None def append(self, data): new_node = Node(data) if not self.head: self.head = new_node return last = self.head while last.next: last = last.next last.next = new_node def display(self): current = self.head elements = [] while current is not None: elements.append(current.data) current = current.next print(elements) # 创建实例对象并测试方法 llist = LinkedList() for i in range(5): llist.append(i * 2) llist.display() ``` 这段代码展示了如何创建一个新的节点以及将其添加至现有链条末端的方法`append()` 和打印整个链条内所有数值组成的列表 `display()` 函数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值