双向链表的应用实例

管理单向链表的缺点分析:

  1. 单向链表,查找的方向只能是一个方向,而双向链表可以向前或者向后查找。
  2. 单向链表不能自我删除,需要靠辅助节点 ,而双向链表,则可以自我删除,所以前面我们单链表删除节点时,总是找到 temp,temp 是待删除节点的前一个节点。

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

 

 

  1) 遍历 :和单链表一样,只是可以向前,也可以向后查找
  2) 添加 (默认添加到双向链表的最后)
    (1)先找到双向链表的最后这个节点
    (2) temp.next = newNode; 
    (3) newNode.pre = temp; 
  3) 修改 思路和原来的单向链表一样
  4) 删除
    (1) 因为是双向链表,因此,我们可以实现自我删除某个节点
    (2) 直接找到要删除的这个节点,比如 temp
       temp.pre.next = temp.next; 
       temp.next.pre = temp.pre;//若删除的是最后一个节点,会有空指针异常 

 

代码实现

1. class doublelinkedlist {  
2.     //先初始化一个头节点,头节点不能动,不存放具体数据  
3.     private hero head = new hero(-1, "", "");  
4.   
5.     //添加节点  
6.     public void add(hero h) {  
7.         //因为head节点不能动,因此我们需要一个辅助变量temp  
8.         hero temp = head;  
9.         //遍历链表,找到最后一个节点  
10.         while (true) {  
11.             if (temp.getNext() == null) {  
12.                 break;  
13.             }  
14.             //如果没有到最后,将temp后移  
15.             temp = temp.getNext();  
16.         }  
17.         //当退出while循环时,temp就指向了链表的最后  
18.         //将链表的最后一个节点的next指向要添加的这个节点  
19.         //将要添加的这个节点的pre指向链表的最后一个节点  
20.         temp.setNext(h);  
21.         h.setPre(temp);  
22.     }  
23.   
24.     //第二种方式在添加英雄时,根据排名将英雄插入到指定位置  
25.     //(如果有这个排名,则添加失败,并给出提示)  
26.     public void addByOrder(hero h) {  
27.         //因为头节点不能动,因此我们仍然通过一个辅助指针(变量)来帮助找到添加的位置  
28.         hero temp = head;  
29.         boolean flag = false;// flag 标志添加的编号是否存在,默认为 false  
30.         while (true) {  
31.             if (temp.getNext() == null) {//说明 temp 已经在链表的最后  
32.                 break;  
33.             } else if (temp.getNext().getNum() > h.getNum()) {//位置找到,就在 temp 的后面插入  
34.                 break;  
35.             } else if (temp.getNext().getNum() == h.getNum()) {//说明希望添加的 heroNode 的编号已然存在  
36.                 flag = true;  
37.                 break;  
38.             }  
39.             temp = temp.getNext();//后移,遍历当前链表  
40.         }  
41.         if (flag) { //不能添加,说明编号存在  
42.             System.out.println("添加的序号为" + h.getNum() + "的英雄序号已经存在,添加失败。");  
43.             return;  
44.         }  
45.   
46.         //插入到链表中, temp 的后面  
47.         // (注意,先连两个节点之间的pre和next,再连另外两个节点的pre和next,否则会出错!!)  
48.         if (temp.getNext() != null) temp.getNext().setPre(h);  
49.         h.setNext(temp.getNext());//将h与temp的下一个节点相连(pre和next指针)  
50.   
51.         h.setPre(temp);  
52.         temp.setNext(h);//再将h与temp节点相连(pre和next指针)  
53.     }  
54.   
55.     //显示链表(遍历)  
56.     public void show() {  
57.         //判断链表是否为空  
58.         if (head.getNext() == null) {  
59.             System.out.println("show():链表为空。。。。");  
60.             return;  
61.         }  
62.         //因为头节点,不能动,因此我们需要一个辅助变量来遍历  
63.         hero temp = head.getNext();  
64.         while (true) {  
65.             //判断是否到链表最后  
66.             if (temp == null) {  
67.                 break;  
68.             }  
69.             //输出节点的信息  
70.             System.out.println(temp.toString());  
71.             //将 temp 后移, 一定小心  
72.             temp = temp.getNext();  
73.         }  
74.     }  
75.   
76.     //修改节点的信息, 根据 no 编号来修改,即 no 编号不能改.  
77.     //说明  
78.     //1.  根据 newHeroNode  的 no 来修改即可  
79.     public void update(hero h) {  
80.         hero temp = head.getNext();//定义一个辅助变量  
81.         boolean flag = false;//表示是否找到该节点  
82.         //判断链表是否空  
83.         if (head.getNext() == null) {  
84.             System.out.println("update():链表为空。。。。");  
85.             return;  
86.         }  
87.         //找到需要修改的节点, 根据 num值  
88.         while (true) {  
89.             if (temp == null) {  
90.                 break;//已经遍历完链表  
91.             }  
92.             if (temp.getNum() == h.getNum()) {  
93.                 flag = true;  
94.                 break;  
95.             }  
96.             temp = temp.getNext();  
97.         }  
98.         if (flag) {  
99.             temp.setName(h.getName());  
100.             temp.setNikname(h.getNikname());  
101.         } else {//没有找到  
102.             System.out.printf("没有找到 编号 %d  的节点,不能修改\n", h.getNum());  
103.         }  
104.     }  
105.   
106.     //删除节点  
107.     //思路  
108.     //1. head  不能动,因此我们需要一个 temp 辅助节点找到待删除节点的前一个节点  
109.     //2. 双向链表中我们在比较时,是 temp.no 和需要删除的节点的 no 比较  
110.     public void delete(int n) {  
111.         if (head.getNext() == null) {  
112.             System.out.println("delete():链表为空。。。。");  
113.             return;  
114.         }  
115.         hero temp = head.getNext();// 辅助变量(指针)  
116.         boolean flag = false;// 标志是否找到待删除节点的  
117.         while (true) {  
118.             if (temp == null) {//已经到链表的最后  
119.                 break;  
120.             }  
121.             if (temp.getNum() == n) {//找到的待删除节点 temp  
122.                 flag = true;  
123.                 break;  
124.             }  
125.             temp = temp.getNext();//temp 后移,遍历  
126.         }  
127.         if (flag) {  
128.             temp.getPre().setNext(temp.getNext());  
129.             if (temp.getNext() != null) {  
130.                 temp.getNext().setPre(temp.getPre());  
131.             }  
132.         } else {  
133.             System.out.printf("没有找到 编号 %d  的节点,不能删除\n", n);  
134.         }  
135.     }   
136. }  

 

posted @ 2020-10-15 21:59  白刃天使  阅读(930)  评论(0编辑  收藏  举报