java中的双向链表,数据结构双向链表的实现
双向链表(Doubly linked list)
什么是双向链表?
双向链表,也叫双链表,是链表的一种。它的每个数据节点都有两个指针,分别指向直接后继和直接前任。因此,从双向链表中的任何节点开始,都可以很容易地访问它的前一个和后一个节点。
双向链表与单向链表的主要区别:
搜索方向:单向链表的搜索方向只能是一个方向,双向链表可以向前或向后搜索。删除:单向链表的删除需要辅助指针的帮助,先找到要删除的节点的前身,然后删除。temp . next=temp . next . next;(temp是二级指针)双链表可以自删除。
双向链表与单向链表的优劣:
优点:双链表结构优于单链表结构。
缺点:从存储结构上看,双向链表比单向链表多一个指针,需要额外的线性内存使用。(指针在32位操作系统中是4字节,在64位操作系统中是8字节)。
双向链表的逻辑结构图解:
00-1010添加:插图:
代码:
//添加一个节点到最后一个公共void Add(double node new node){ double node temp=head;while(true){ if(temp.next==null){//当temp . next为空时,证明temp是最后一个元素。temp.next=newNode//temp节点的下一位指向新节点newNode.pre=temp//新节点的前一位指向temp //这两步形成一个双链表断点;} else if(temp . next . id==new node . id){//同一个id证明该学生已经存在。System.out.printf(要插入的学号为%d的学生已经存在。n ,新节点。ID);打破;} temp=temp.next} }//添加节点public void sortaddd(双节点新节点){ double node temp=headwhile(true){ if(temp . next==null){//表示要添加的节点序号是当前链表中最大的,所以直接加在末尾。temp.next=newNode//temp节点的下一位指向新节点newNode.pre=temp//新节点的前一位指向temp //这两步形成一个双链表断点;} else If(temp . next . idnew node . id){//如果当前节点的下一个节点的个数大于要添加的新节点,则证明新节点应该添加在temp newNode.next=temp.next之后;//要添加的节点的下一位指向当前节点的下一位temp . next . pre=new node;//temp当前节点的下一位的前一位指向新节点,形成一个双向链表temp.next=newNode//让当前节点的下一位指向新节点newNode.pre=temp//新节点的前一位指向当前节点temp //这样连接完成后,新节点会插入到原链表break中的temp节点和temp.next节点之间;} else if(temp . next . id==new node . id){//同一个id证明该学生已经存在。System.out.printf(要插入的学号为%d的学生已经存在。n ,新节点。ID);打破;} temp=temp.next}
}删除 :图解:
代码:
//删除一个节点。 //自我删除 public void DoubleDelete(int id) { if (head.next == null) { System.out.println("链表为空!"); return; } DoubleNode temp = head.next; while (true) { if (temp == null) { System.out.printf("要删除的%d节点不存在n", id); break; } else if (temp.ID == id) { //找到要删除节点 // 此时temp 就代表将要被删除节点 //temp.pre.next 指 当前要被删除节点 的前一位 的后一位 // temp.next 指 当前要被删除节点的后一位 temp.pre.next = temp.next; // (当前要被删除节点 的前一位 的后一位)指向 (当前要被删除节点的后一位) //这样就完成了 temp节点的删除操作 // 如果是最后一个节点,就不需要执行下面这句话,否则出现空指针 if (temp.next != null) { temp.next.pre = temp.pre; } break; } temp = temp.next; } }
修改:侃侃:它实际上与单链表的删除是一样。
代码:
//修改链表节点 public void DoubleUpdate(DoubleNode newNode) { if (head.next == null) { System.out.println("链表为空!"); return; } DoubleNode temp = head.next; while (true) { if (temp == null) { break; } else if (temp.ID == newNode.ID) { //找到要修改的节点 temp.name = newNode.name; temp.mark = newNode.mark; return; } temp = temp.next; } System.out.printf("要修改的%d节点不存在n", newNode.ID); }
双向链表实例:
用双向链表创建一个学生信息管理系统,完成对学生信息的添加,删除,修改操作。
package Linkedlist; //双向链表。public class DoubleLinkedListDemo { public static void main(String agrs[]) { DoubleNode stu1 = new DoubleNode(6, "张三", 99); DoubleNode stu2 = new DoubleNode(2, "李四", 99); DoubleNode stu3 = new DoubleNode(3, "王五", 99); DoubleNode stu4 = new DoubleNode(5, "王二", 99); DoubleNode stu5 = new DoubleNode(4, "小红", 99); DoubleNode stu6 = new DoubleNode(1, "小明", 99); DoubleNode stu7 = new DoubleNode(1, "小明", 99); DoubleLinkedlist doubleLinkedlist = new DoubleLinkedlist(); /* doubleLinkedlist.add(stu1); doubleLinkedlist.add(stu2); doubleLinkedlist.add(stu3); doubleLinkedlist.add(stu4); doubleLinkedlist.add(stu5); doubleLinkedlist.add(stu6); doubleLinkedlist.add(stu7);*/ doubleLinkedlist.Sortadd(stu1); doubleLinkedlist.Sortadd(stu2); doubleLinkedlist.Sortadd(stu3); doubleLinkedlist.Sortadd(stu4); doubleLinkedlist.Sortadd(stu5); doubleLinkedlist.Sortadd(stu6); doubleLinkedlist.add(stu7); System.out.println("原链表展示!"); doubleLinkedlist.ShowList(); System.out.println(); doubleLinkedlist.DoubleDelete(6); doubleLinkedlist.DoubleDelete(15); System.out.println("删除后链表展示!"); doubleLinkedlist.ShowList(); System.out.println(); DoubleNode stu8 = new DoubleNode(1, "李思成", 100); DoubleNode stu9 = new DoubleNode(20, "李成", 100); doubleLinkedlist.DoubleUpdate(stu8); doubleLinkedlist.DoubleUpdate(stu9); System.out.println("修改后链表展示!"); doubleLinkedlist.ShowList(); System.out.println(); }} class DoubleLinkedlist { private DoubleNode head = new DoubleNode(0, "", 0); public DoubleNode getHead() { return head; } //添加一个节点到最后 public void add(DoubleNode newNode) { DoubleNode temp = head; while (true) { if (temp.next == null) { // 当temp.next 为空时,证明temp为最后一个元素。 temp.next = newNode; //temp节点的下一位指向新节点 newNode.pre = temp;//新节点的前一位指向temp //这两步构成双向链表 break; }else if (temp.next.ID == newNode.ID) { //ID相同证明 已经存在该学生。 System.out.printf("要插入学号为%d的学生已经存在。n", newNode.ID); break; } temp = temp.next; } } //按学号顺序添加节点 public void Sortadd(DoubleNode newNode) { DoubleNode temp = head; while (true) { if (temp.next == null) { //说明要添加的节点序号在当前链表中最大,因此直接添加在末尾。 temp.next = newNode;//temp节点的下一位指向新节点 newNode.pre = temp;//新节点的前一位指向temp //这两步构成双向链表 break; } else if (temp.next.ID > newNode.ID) { //当前节点的下一位节点的编号大于 要添加的新节点,则证明新节点要添加在temp节点之后 newNode.next = temp.next;//要添加节点的下一位 指向temp当前节点的下一位 temp.next.pre = newNode;//temp当前节点的下一位的前一位 指向 新节点构成双向链表 temp.next = newNode; // 再让当前节点的下一位指向 新节点 newNode.pre = temp;//新节点的前一位 指向 当前节点temp //这样连接完成后就将 新节点插入 到 原本链表的temp节点与temp.next节点之间 break; }else if (temp.next.ID == newNode.ID) { //ID相同证明 已经存在该学生。 System.out.printf("要插入学号为%d的学生已经存在。n", newNode.ID); break; } temp = temp.next; } } //删除一个节点。 //自我删除 public void DoubleDelete(int id) { if (head.next == null) { System.out.println("链表为空!"); return; } DoubleNode temp = head.next; while (true) { if (temp == null) { System.out.printf("要删除的%d节点不存在n", id); break; } else if (temp.ID == id) { //找到要删除节点 // 此时temp 就代表将要被删除节点 //temp.pre.next 指 当前要被删除节点 的前一位 的后一位 // temp.next 指 当前要被删除节点的后一位 temp.pre.next = temp.next; // (当前要被删除节点 的前一位 的后一位)指向 (当前要被删除节点的后一位) //这样就完成了 temp节点的删除操作 // 如果是最后一个节点,就不需要执行下面这句话,否则出现空指针 if (temp.next != null) { temp.next.pre = temp.pre; } break; } temp = temp.next; } } //修改链表节点 public void DoubleUpdate(DoubleNode newNode) { if (head.next == null) { System.out.println("链表为空!"); return; } DoubleNode temp = head.next; while (true) { if (temp == null) { break; } else if (temp.ID == newNode.ID) { //找到要修改的节点 temp.name = newNode.name; temp.mark = newNode.mark; return; } temp = temp.next; } System.out.printf("要修改的%d节点不存在n", newNode.ID); } public void ShowList() { // 判断链表是否为空 if (head.next == null) { System.out.println("链表为空"); return; } // 因为头节点,不能动,因此我们需要一个辅助变量来遍历 DoubleNode temp = head.next; while (true) { // 判断是否到链表最后 if (temp == null) { break; } System.out.println(temp);// 输出节点的信息 temp = temp.next; } }} class DoubleNode { public int ID; // 编号。 public String name; public int mark; public DoubleNode next; public DoubleNode pre;
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。