线性表 双链表

在这里插入图片描述
单链表:单个指针,单向火车
双链表:双指针,电梯
在这里插入图片描述

typedef struct DNode{ //定义单链表结点类型
	ElemType data; //数据域
	struct DNode *prior,*next; //前驱和后继指针
}DNode, *DLinkList;

插入

1.插入:(方法不唯一)
① s->next=p->next;
② p->next->prior=s;
③ s->prior=p;
④ p->next=s;
在这里插入图片描述

删除

① p->next=q->next;
② q->next->prior=p;
③ free(q);
在这里插入图片描述

### Java 双向链表的实现与操作 #### 1. 双向链表简介 双向链表是一种特殊的线性结构,其中每个节点不仅包含指向下一个节点的指针 `next`,还包含一个指向前驱节点的指针 `prev`。这种设计使得可以在正向和反向上自由遍历链表。 --- #### 2. 节点定义 在 Java 中,通常通过内部类来定义节点: ```java class Node<T> { T data; Node<T> prev; Node<T> next; public Node(T data) { this.data = data; this.prev = null; this.next = null; } } ``` 上述代码展示了如何定义一个通用类型的节点[^1]。 --- #### 3. 链表初始化 为了管理双向链表,可以创建一个外部容器类 `DoubleLinkedList` 来封装所有的功能逻辑: ```java public class DoubleLinkedList<T> { private Node<T> head; private Node<T> tail; public DoubleLinkedList() { head = new Node<>(null); tail = new Node<>(null); head.next = tail; tail.prev = head; } // 添加其他方法... } ``` 这里引入了虚拟头结点 `head` 和尾部哨兵节点 `tail`,简化边界条件处理[^4]。 --- #### 4. 基本操作 ##### (1)前插法(Add First) 从前端插入新节点的操作如下所示: ```java public void addFirst(T value) { Node<T> newNode = new Node<>(value); newNode.prev = head; newNode.next = head.next; head.next.prev = newNode; head.next = newNode; } ``` 此函数实现了将新节点放置到链表头部的功能[^2]。 --- ##### (2)后插法(Add Last) 从末端追加新节点的方法为: ```java public void addLast(T value) { Node<T> newNode = new Node<>(value); newNode.next = tail; newNode.prev = tail.prev; tail.prev.next = newNode; tail.prev = newNode; } ``` 这段代码用于扩展链表长度至最后一位。 --- ##### (3)删除指定节点 移除特定节点的过程涉及调整其前后邻居之间的连接关系: ```java public boolean remove(Node<T> node) { if (node == null || node == head || node == tail) return false; node.prev.next = node.next; node.next.prev = node.prev; return true; } ``` 该片段描述了一种安全的方式去除目标项而不破坏整个列表结构[^3]。 --- ##### (4)反转链表 对于复杂场景下的需求——比如翻转顺序,则需重新排列各单元间的关联方向: ```java public void reverse() { if (head.next == tail) return; Node<T> rh = new Node<>(null); rh.next = tail; Node<T> cur = head.next; Node<T> cn; while (cur != tail) { cn = cur.next; cur.next = rh.next; rh.next.prev = cur; cur.prev = rh; rh.next = cur; cur = cn; } rh.next.prev = head; head.next = rh.next; } ``` 这是基于循环迭代完成的一次完整倒序转换过程[^5]。 --- #### 5. 打印输出 提供两种方式展示当前存储的数据集合状态:一种是从前往后的标准模式;另一种则是借助辅助变量沿逆路径读取记录。 ```java // 正向打印 public void displayForward() { StringBuilder sb = new StringBuilder(); for (Node<T> p = head.next; p != tail; p = p.next) { sb.append(p.data).append(" "); } System.out.println(sb.toString().trim()); } // 反向打印 public void displayBackward() { StringBuilder sb = new StringBuilder(); for (Node<T> p = tail.prev; p != head; p = p.prev) { sb.append(p.data).append(" "); } System.out.println(sb.toString().trim()); } ``` 这两种形式分别对应于不同视角下观察序列内容的需求。 --- ### 总结 以上介绍了有关 Java 编程环境下构建并操控双向链接清单的主要技术要点,涵盖了基础概念、具体编码实践以及若干典型应用场景实例说明等内容。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值