数据结构----7双链表

双链表

目录

单链表&&双链表:

一、双链表的定义与结构

二、双链表的基本操作

1. 初始化

2. 插入操作(后插法)

3. 删除操作(删除后继结点)

4. 遍历操作

三、关键特性与注意事项

四、核心考点总结


单链表&&双链表:

单链表:无法逆向检索,有时候不方便

双链表:可进可退,存储密度更低一丢丢

一、双链表的定义与结构

定义:双链表的每个结点包含数据域`data`、前驱指针`prior`和后继指针`next`。 

  typedef struct DNode {

      ElemType data;         // 数据域

      struct DNode *prior;   // 前驱指针

      struct DNode *next;    // 后继指针

  } DNode, *DLinklist;

与单链表的对比: 

优势:支持双向遍历(前向和后向),可通过前驱指针快速访问前一结点。

劣势:每个结点多存储一个指针,存储密度略低于单链表。

二、双链表的基本操作

1. 初始化

操作目标:创建一个空的带头结点双链表。 

实现逻辑: 

  头结点的`prior`和`next`均指向`NULL`。 

空表判断:头结点的`next`为`NULL`时表示链表为空。 

  bool Empty(DLinklist L) {

      return (L->next == NULL);

  }

2. 插入操作(后插法)

目标:在结点`p`之后插入新结点`s`。 

步骤: 

  1. 新结点`s`的`next`指向`p`的后继结点(`s->next = p->next`)。 

  2. 若`p`的后继结点存在,更新其后继结点的`prior`指向`s`(`p->next->prior = s`)。 

  3. `p`的`next`指向`s`(`p->next = s`)。 

  4. 更新`s`的`prior`指向`p`(`s->prior = p`)。 

代码实现: 

  bool InsertNextDNode(DNode *p, DNode *s) {

      if (p == NULL || s == NULL) return false;

      s->next = p->next;

      if (p->next != NULL) p->next->prior = s;

      s->prior = p;

      p->next = s;

      return true;

  }

边界处理:若`p`为最后一个结点,`p->next`为`NULL`,此时无需更新后继结点的`prior`。

3. 删除操作(删除后继结点)

目标:删除结点`p`的后继结点`q`。 

步骤: 

  1. 找到`p`的后继结点`q`(`q = p->next`)。 

  2. 若`q`存在,将`p`的`next`指向`q`的后继结点(`p->next = q->next`)。 

  3. 若`q`的后继结点存在,更新其后继结点的`prior`指向`p`(`q->next->prior = p`)。 

  4. 释放`q`的内存空间(`free(q)`)。 

代码实现: 

  bool DeleteNextDNode(DNode *p) {

      if (p == NULL) return false;

      DNode *q = p->next;

      if (q == NULL) return false;

      p->next = q->next;

      if (q->next != NULL) q->next->prior = p;

      free(q);

      return true;

  }

边界处理:若`q`为最后一个数据结点,`q->next`为`NULL`,无需更新前驱指针。

4. 遍历操作

前向遍历:从首元结点开始,通过`next`指针依次访问后续结点,终止条件为`p == NULL`。 

  while (p != NULL) {

      // 处理结点p

      p = p->next;

  }

后向遍历:从尾结点开始,通过`prior`指针依次访问前驱结点,终止条件为`p == NULL`(需从尾结点逆向开始)。 

  while (p != NULL) {

      // 处理结点p

      p = p->prior;

  }

三、关键特性与注意事项

1.双向性:双链表支持双向遍历,单链表仅能单向遍历。 

2.指针修改顺序:插入和删除操作中,需先修改后继指针,再修改前驱指针,避免链表断裂。 

3. 存储效率:每个结点额外存储一个指针,空间复杂度为`O(n)`,较单链表略高。 

4. 查找操作:不支持随机存取,按位查找和按值查找均需遍历,时间复杂度为`O(n)`。 

四、核心考点总结

初始化:头结点的指针域初始化为`NULL`。 

插入/删除边界:处理最后一个结点时,需判断后继是否存在(`next == NULL`)。 

遍历逻辑:前向遍历用`next`,后向遍历用`prior`,循环终止条件为指针指向`NULL`。 

与单链表对比:双链表适合需要频繁双向访问的场景,单链表更节省存储空间。 

通过双向指针设计,双链表在某些场景(如双向遍历、删除前驱结点)中效率更高,但实现复杂度略高于单链表。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值