Java數(shù)據(jù)結構之雙向鏈表的實現(xiàn)
1 雙向鏈表
1.1 雙向鏈表介紹
相較單鏈表,雙向鏈表除了data與next域,還多了一個pre域用于表示每個節(jié)點的前一個元素。這樣做給雙向鏈表帶來了很多優(yōu)勢:
單向鏈表查找的方向只能是一個方向,而雙向鏈表可以向前或者向后查找;
單鏈表如果想要實現(xiàn)刪除操作,需要找到待刪除節(jié)點的前一個節(jié)點。而雙向鏈表可以實現(xiàn)自我刪除。
雙向鏈表結構示意圖如下:
1.2 雙向鏈表實現(xiàn)思路
與單鏈表實現(xiàn)類似,交集部分不再贅述,詳情可參考文章:Java數(shù)據(jù)結構:單鏈表的實現(xiàn)與面試題匯總
遍歷:
與單鏈表遍歷方式一樣,同時,雙向鏈表可以支持向前和向后兩種查找方式
添加:
添加到末尾
- 先找到雙向鏈表最后一個節(jié)點
- cur.next = newNode;
- newNode.pre = cur;
按照no順序添加
- 先判斷該鏈表是否為空,如果為空則直接添加
- 如果不為空則繼續(xù)處理
- 根據(jù)no遍歷鏈表,找到合適的位置
- newNode.next = cur.next;
- cur.next = newNode;
- newNode.pre = cur;
修改操作與單鏈表實現(xiàn)步驟一致
刪除操作:
- 雙向鏈表可以實現(xiàn)自我刪除
- 直接找到待刪除的節(jié)點
- cur.pre.next = cur.next;
- cur.next.pre = cur.pre;
- 需要特別注意是否為最后一個元素,如果為最后一個元素,cur.next為null,此時使用cur.next.pre會出現(xiàn)空指針異常,所以,如果為最后一個元素,則該步驟可以省略,cur.next為null即可。
以刪除紅色的2號節(jié)點為例:
2 雙向鏈表實現(xiàn)完整代碼
2.1 節(jié)點類 Student.java
/** * @author 興趣使然黃小黃 * @version 1.0 * 學生類節(jié)點 */ public class StudentNode { public String no; //學號 public String name; //姓名 public int age; //年齡 public StudentNode pre; //指向前一個節(jié)點 public StudentNode next; //指向下一個節(jié)點 //構造器 public StudentNode(String no, String name, int age ){ this.no = no; this.name = name; this.age = age; } //為了顯示方便 @Override public String toString() { return "StudentNode{" + "no='" + no + '\'' + ", name='" + name + '\'' + ", age=" + age + '}'; } }
2.2 雙向鏈表實現(xiàn)類 StudentDoubleLinkedList.java
/** * @author 興趣使然黃小黃 * @version 1.0 * 學生雙向鏈表的具體實現(xiàn) */ public class StudentDoubleLinkedList { //定義頭節(jié)點 private StudentNode head = new StudentNode("", "", 0); //獲取頭節(jié)點 public StudentNode getHead(){ return head; } //遍歷雙向鏈表的方法 public void showList(){ //判斷鏈表是否為空 if (head.next == null){ System.out.println("當前鏈表為空"); return; } //遍歷 使用輔助指針 StudentNode temp = head; while (temp != null){ //更新指針 temp = temp.next; if (temp.next == null){ System.out.print(temp); break; } System.out.print(temp + "--->"); } } //添加節(jié)點的方法 //添加到尾部 public void add(StudentNode newNode){ //先找到最后一個節(jié)點 StudentNode cur = head; while (true){ //到達最后退出循環(huán) if (cur.next == null){ break; } //更新指針 cur = cur.next; } //添加操作 newNode.next = cur.next; //也可以省略,因為恒為null cur.next = newNode; newNode.pre = cur; } //添加節(jié)點的方法 //根據(jù)學號順序添加 public void addByOrder(StudentNode newNode){ //如果當前鏈表為空,則直接添加 if (head.next == null){ head.next = newNode; newNode.pre = head; return; } //按照學號找到對應位置 StudentNode cur = head; boolean flag = false; //標識待添加的no是否存在 while (true){ if (cur.next == null){ //已經(jīng)到達鏈表的尾部 break; } else if (Integer.parseInt(cur.next.no) == Integer.parseInt(newNode.no)){ //已經(jīng)存在 flag = true; break; }else if (Integer.parseInt(cur.next.no) > Integer.parseInt(newNode.no)){ //位置找到 break; } cur = cur.next; } if (flag){ System.out.println("當前no已經(jīng)存在,無法添加!"); }else { //添加操作 newNode.next = cur.next; cur.next = newNode; newNode.pre = cur; } } //根據(jù)no學號修改學生信息 public void update(StudentNode studentNode){ if (head.next == null){ System.out.println("當前鏈表為空, 無法修改"); return; } StudentNode temp = head.next; boolean flag = false; //表示是否找到節(jié)點 while (true){ if (temp == null){ break; } if (temp.no == studentNode.no){ flag = true; break; } temp = temp.next; } if (flag){ temp.name = studentNode.name; temp.age = studentNode.age; System.out.println("更新成功!"); }else { System.out.println("沒有找到"); } } //從雙向鏈表中刪除節(jié)點 public void delete(String no){ //直接找到對應no的節(jié)點直接刪除 StudentNode cur = head.next; boolean flag = false; //標記是否找到 while (true){ if (cur == null){ break; } if (cur.no.equals(no)){ flag = true; //找到了 break; } cur = cur.next; } if (flag){ //刪除操作 //注意考慮最后一個節(jié)點后一個為空的情況 if (cur.next != null) { cur.next.pre = cur.pre; } cur.pre.next = cur.next; System.out.println("刪除成功!"); }else { System.out.println( no + "節(jié)點不存在,無法刪除!"); } } }
2.3 測試類 StudentDoubleLinkedListDemo.java
/** * @author 興趣使然黃小黃 * @version 1.0 * 雙向鏈表測試類 */ public class DoubleLinkedListDemo { public static void main(String[] args) { StudentDoubleLinkedList doubleLinkedList = new StudentDoubleLinkedList(); doubleLinkedList.addByOrder(new StudentNode("1", "黃小黃", 20)); doubleLinkedList.addByOrder(new StudentNode("3", "懶羊羊", 20)); doubleLinkedList.addByOrder(new StudentNode("2", "沸羊羊", 25)); doubleLinkedList.addByOrder(new StudentNode("4", "美羊羊", 15)); System.out.println("遍歷:"); doubleLinkedList.showList(); //測試更新方法 System.out.println("\n更新編號為4的信息后:"); doubleLinkedList.update(new StudentNode("4", "禰豆子", 14)); doubleLinkedList.showList(); //測試刪除方法 System.out.println("\n刪除第一個和最后一個:"); doubleLinkedList.delete("1"); doubleLinkedList.delete("4"); doubleLinkedList.showList(); } }
2.4 結果
遍歷:
StudentNode{no='1', name='黃小黃', age=20}--->StudentNode{no='2', name='沸羊羊', age=25}--->StudentNode{no='3', name='懶羊羊', age=20}--->StudentNode{no='4', name='美羊羊', age=15}
更新編號為4的信息后:
更新成功!
StudentNode{no='1', name='黃小黃', age=20}--->StudentNode{no='2', name='沸羊羊', age=25}--->StudentNode{no='3', name='懶羊羊', age=20}--->StudentNode{no='4', name='禰豆子', age=14}
刪除第一個和最后一個:
刪除成功!
刪除成功!
StudentNode{no='2', name='沸羊羊', age=25}--->StudentNode{no='3', name='懶羊羊', age=20}
Process finished with exit code 0
3 雙向鏈表小結
單向鏈表查找的方向只能為一個方向,雙向鏈表解決了這個缺點,可以實現(xiàn)雙向查找;
單鏈表進行刪除操作必須找到待刪除元素的前一個元素,才能完成刪除操作。而雙向鏈表就簡單多了,只需要找到待刪除的節(jié)點,進行自我刪除;
本節(jié)介紹了雙向鏈表的遍歷、添加、按順序添加、更新、刪除方法的實現(xiàn),可以嘗試像單鏈表篇一樣,嘗試求有效節(jié)點數(shù)量,以及如何逆序輸出雙向鏈表加強練習!
以上就是Java數(shù)據(jù)結構之雙向鏈表的實現(xiàn)的詳細內(nèi)容,更多關于Java數(shù)據(jù)結構雙向鏈表的資料請關注腳本之家其它相關文章!
相關文章
Java中區(qū)別.toString() ,(String),valueOf()方法
這篇文章主要介紹了Java中區(qū)別.toString() ,(String),valueOf()方法,需要的朋友可以參考下2017-01-01Java如何基于EasyExcel實現(xiàn)導入數(shù)據(jù)校驗并生成錯誤信息Excel
這篇文章主要介紹了Java如何基于EasyExcel實現(xiàn)導入數(shù)據(jù)校驗并生成錯誤信息Excel,為了優(yōu)化項目中的文件導入功能,考慮構建一個基于EasyExcel的通用Excel導入框架,主要解決導入數(shù)據(jù)的校驗問題,避免業(yè)務代碼中堆積大量校驗邏輯,需要的朋友可以參考下2024-09-09SpringIOC?BeanDefinition的加載流程詳解
這篇文章主要為大家介紹了SpringIOC?BeanDefinition的加載流程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-10-10SpringBoot Swagger2 接口規(guī)范示例詳解
Swagger(在谷歌、IBM、微軟等公司的支持下)做了一個公共的文檔風格來填補上述問題,在本文中,我們將會學習怎么使用Swagger的 Swagger2注解去生成REST API文檔,感興趣的朋友一起看看吧2023-12-12