在单向链表的基础上,理解双向链表就很简单了。
双向链表,又称为双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。
1.节点结构示例:
public class DoublyLinkedNode {
public int num; //编号
public String name; //姓名
public int age; //年龄
public DoublyLinkedNode next; //指向下一个元素
public DoublyLinkedNode pre; //指向上一个元素
public DoublyLinkedNode(int num, String name, int age) {
this.num = num;
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "DoublyLinkedNode{" +
"num=" + num +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
2.链表结构示例
class DoublyLinkedList{
//设置一个头节点
public DoublyLinkedNode head = new DoublyLinkedNode(0,null,0);
//这里只演示添加
/**
* 按照顺序进行插入
* @param doublyLinkedNode
*/
public void addByOrder(DoublyLinkedNode doublyLinkedNode){
// 因为头节点不能动,因此我们仍然通过一个辅助指针(变量)来帮助找到添加的位置
DoublyLinkedNode temp = head;
//判断是否插入成功的标签
int flag = 0;
while (true){
//如果是链表尾部,则跳出循环,直接插入
if (temp.next == null){
break;
}
//如果已经存在,则插入失败
if (temp.next.num == doublyLinkedNode.num){
flag = 1;
break;
}
//按照从小到大插入
if (temp.next.num > doublyLinkedNode.num){
flag =2;
break;
}
temp = temp.next;
}
//如果是尾插
if (flag == 0){
System.out.println(doublyLinkedNode.toString() + "插入成功");
temp.next = doublyLinkedNode;
doublyLinkedNode.pre = temp;
}
//如果是中间插入
if (flag == 2){
System.out.println(doublyLinkedNode.toString() + "插入成功");
//下面这几行的代码注意执行顺序 TODO 检查
doublyLinkedNode.next = temp.next;
temp.next.pre = doublyLinkedNode;
temp.next = doublyLinkedNode;
doublyLinkedNode.pre = temp;
// doublyLinkedNode.next = temp.next;
// doublyLinkedNode.pre = temp;
// temp.next.pre = doublyLinkedNode;
// temp.next = doublyLinkedNode;
}
//如果插入失败
if (flag == 1){
System.out.println(doublyLinkedNode.toString() + "插入失败");
}
}
public void list(){
DoublyLinkedNode temp = head;
while (true){
if (temp.next != null){
System.out.println(temp.next + " 他前一个节点为" + temp.next.pre);
}else {
break;
}
temp = temp.next;
}
}
}
3.测试示例
public class DoublyLinkedList_Test {
public static void main(String[] args) {
DoublyLinkedList doublyLinkedList = new DoublyLinkedList();
//添加元素
doublyLinkedList.addByOrder(new DoublyLinkedNode(3,"张飞",20));
doublyLinkedList.addByOrder(new DoublyLinkedNode(2,"张飞",20));
doublyLinkedList.addByOrder(new DoublyLinkedNode(4,"张飞",20));
doublyLinkedList.addByOrder(new DoublyLinkedNode(1,"张飞",20));
doublyLinkedList.addByOrder(new DoublyLinkedNode(6,"张飞",20));
doublyLinkedList.addByOrder(new DoublyLinkedNode(5,"张飞",20));
//显示链表
System.out.println("___________________________________________________________");
doublyLinkedList.list();
}
}
4.显示结果
DoublyLinkedNode{num=3, name='张飞', age=20}插入成功
DoublyLinkedNode{num=2, name='张飞', age=20}插入成功
DoublyLinkedNode{num=4, name='张飞', age=20}插入成功
DoublyLinkedNode{num=1, name='张飞', age=20}插入成功
DoublyLinkedNode{num=6, name='张飞', age=20}插入成功
DoublyLinkedNode{num=5, name='张飞', age=20}插入成功
___________________________________________________________
DoublyLinkedNode{num=1, name='张飞', age=20} 他前一个节点为DoublyLinkedNode{num=0, name='null', age=0}
DoublyLinkedNode{num=2, name='张飞', age=20} 他前一个节点为DoublyLinkedNode{num=1, name='张飞', age=20}
DoublyLinkedNode{num=3, name='张飞', age=20} 他前一个节点为DoublyLinkedNode{num=2, name='张飞', age=20}
DoublyLinkedNode{num=4, name='张飞', age=20} 他前一个节点为DoublyLinkedNode{num=3, name='张飞', age=20}
DoublyLinkedNode{num=5, name='张飞', age=20} 他前一个节点为DoublyLinkedNode{num=4, name='张飞', age=20}
DoublyLinkedNode{num=6, name='张飞', age=20} 他前一个节点为DoublyLinkedNode{num=5, name='张飞', age=20}
Process finished with exit code 0
5.注意点
对于下面的插入代码一定要注意顺序,熟悉其传递过程,可以画图,或者debug来深入理解,然后在控制台把前一个结点打印出来验证结果。
doublyLinkedNode.next = temp.next;
temp.next.pre = doublyLinkedNode;
temp.next = doublyLinkedNode;
doublyLinkedNode.pre = temp;