链表(Linked List):双向链表

双向链表应用实例 + 代码实现

使用带 head 头的双向链表实现 - 水浒英雄排行榜

  • 管理单向链表的确定分析:

  分析双向链表如何完成遍历,添加,修改和删除的思路:

  1)遍历和单链表一样,只是可以向前,也可以向后查找

  2)添加(默认添加到双向链表的最后)

    ①先找到双向链表最后的这个节点

    ②temp.next = newHeroNode;

    ③newHeroNode.pre = temp;

  3)修改 和单链表思路一样

  4)删除

    ①因为是双向链表,因此,我们可以实现自我删除某个节点

    ②直接找到要删除的这个节点,比如temp

    ③temp.pre.next = temp.next;

    ④temp.next.pre = temp.pre; //主要temp.next要判空,因为有可能删除的是最后一个节点

  • 双向链表的代码实现:
  1 package com.jyj.linkedList;
  2 
  3 public class DoubleLinkedListDemo {
  4     public static void main(String[] args) {
  5         //测试
  6         //先创建节点
  7         HeroNode2 hero1 = new HeroNode2(1,"宋江","及时雨");
  8         HeroNode2 hero2 = new HeroNode2(2,"卢俊义","玉麒麟");
  9         HeroNode2 hero3 = new HeroNode2(3,"吴用","智多星");
 10         HeroNode2 hero4 = new HeroNode2(4,"林冲","豹子头");
 11         System.out.println("~~双向链表测试~~");
 12         
 13         DoubleLinkedList doubleLinkedList = new DoubleLinkedList();
 14         doubleLinkedList.add(hero1);
 15         doubleLinkedList.add(hero2);
 16         doubleLinkedList.add(hero3);
 17         doubleLinkedList.add(hero4);
 18         //显示
 19         doubleLinkedList.list();
 20         HeroNode2 newHero = new HeroNode2(3,"月光","洒满湖面");
 21         //修改
 22         doubleLinkedList.update(newHero);
 23         System.out.println("修改后:");
 24         doubleLinkedList.list();
 25         
 26         //删除
 27         doubleLinkedList.del(5);
 28         System.out.println("删除后:");
 29         doubleLinkedList.list();
 30     }
 31 }
 32 
 33 //定义DoubleLinkedList 管理英雄
 34 class DoubleLinkedList {
 35     //先初始化一个头节点,头节点不要动,不存放具体的数据
 36     private HeroNode2 head = new HeroNode2(0,"","");
 37     
 38     //返回头节点
 39     public HeroNode2 getHead() {
 40         return head;
 41     }
 42     
 43     //显示链表[遍历]
 44     public void list(){
 45         //判断链表是否为空
 46         if(head.next == null) {
 47             System.out.println("链表为空");
 48             return;
 49         }
 50         //因为头节点不能动,因此需要辅助变量来遍历
 51         HeroNode2 temp = head.next;
 52         while(true) {
 53             //判断是否到链表最后:注意是temp == null,不是temp.next == null
 54             if(temp == null) {
 55                 break;
 56             }
 57             //输出节点的信息
 58             System.out.println(temp);
 59             //将temp 后移,不然就是死循环
 60             temp = temp.next;
 61         }
 62     }
 63 
 64     //添加节点到单向链表
 65     //思路:当不考虑编号的顺序时
 66     //1.找到当前链表的最后节点
 67     //2.将最后这个节点的next 指向  新的节点
 68     //  将新节点的pre 指向 最后这个节点的pre
 69     public void add(HeroNode2 newHeroNode) {
 70         //因为head节点不能动,因此我们需要一个辅助节点 temp
 71         HeroNode2 temp = head;
 72         //遍历链表,找到最后
 73         while(true) {
 74             //找到链表的最后
 75             if(temp.next == null) {
 76                 break;
 77             }
 78             //如果没有找到最后,就将temp后移
 79             temp = temp.next;
 80         }
 81         //当退出while循环时,temp就指向了链表的最后
 82         //将最后这个节点的next 指向 新的节点
 83         //将新节点的pre 指向  最后这个节点
 84         temp.next = newHeroNode;
 85         newHeroNode.pre = temp;
 86     }
 87 
 88     //修改节点的信息,根据no编号来修改,即no编号不能改
 89     public void update(HeroNode2 newHeroNode) {
 90         //判空
 91         if(head.next == null) {
 92             System.out.println("链表为空");
 93             return;
 94         }
 95         //找到需要修改的节点,根据no编号
 96         //定义一个辅助变量
 97         HeroNode2 temp = head.next;
 98         boolean flag = false; //表示是否找到该节点
 99         while(true) {
100             if(temp == null) {
101                 break; //已经遍历完链表
102             }
103             if(temp.no == newHeroNode.no) {
104                 //找到
105                 flag = true;
106                 break;
107             }
108             temp = temp.next;
109         }
110         //根据flag 判断是否找到要修改的节点
111         if(flag) {
112             temp.name = newHeroNode.name;
113             temp.nickname = newHeroNode.nickname;
114         }else { //没有找到
115             System.out.printf("编号 %d 不存在,不能修改~",newHeroNode.no);
116         }
117     }
118     
119     //删除链表
120     //思路
121     //1.head 不能动,因此我们需要一个temp辅助节点找到待删除节点的前一个节点
122     //2.说明我们在比较时,是 temp.next.no 和 需要删除的节点的no 比较
123     public void del(int no) {
124         if(head.next == null) {
125             System.out.println("链表为空");
126             return;
127         }
128         //辅助链表
129         HeroNode2 temp = head.next;
130         boolean flag = false; //标志是否找到待删除的节点
131         
132         while(true) {
133             if(temp == null) { //已经到链表最后
134                 break;
135             }
136             if(temp.no == no) {
137                 //找到待删除节点temp
138                 flag = true;
139                 break;
140             }
141             temp = temp.next; //后移
142         }
143         
144         if(flag) {
145             //删除节点
146             temp.pre.next = temp.next;
147             //如果temp是最后一个要删除的,temp.next == null
148             if(temp.next != null) {
149                 temp.next.pre = temp.pre;    
150             }
151         }else {
152             System.out.printf("要删除的 %d 节点不存在\n",no);
153         }
154     }
155 }
156 
157 //定义HeroNode2,每个HeroNode2 对象就是一个节点
158 class HeroNode2 {
159     public int no;
160     public String name;
161     public String nickname;
162     public HeroNode2 next; //指向下一个节点
163     public HeroNode2 pre;  //指向上一个节点
164     
165     //构造器
166     public HeroNode2(int no,String name,String nickname) {
167         this.no = no;
168         this.name = name;
169         this.nickname = nickname;
170     }
171 
172     //为了显示方便,重写toString
173     @Override
174     public String toString() {
175         return "HeroNode2 [no=" + no + ", name=" + name + ", nickname="
176                 + nickname + "]";
177     }
178 }
View Code

以上

猜你喜欢

转载自www.cnblogs.com/jianyingjie/p/12116528.html
今日推荐