数据结构:单向链表
單鏈表
文章目錄
- 單鏈表
- 前言
- 單向鏈表的結構
- 代碼實現
- 鏈表存儲的節點
- 鏈表初始化
- 鏈表的基本操作
- 增加節點
- 按照編號順序添加節點
- 更新節點中數據
- 遍歷鏈表
- 獲取鏈表長度
- 獲取倒數第n個節點
前言
在鏈表的學習之前,我們已經學過了數組,在數組創建時,其數組長度已經寫死了,因此對于數據的拓展,數組具有一定的局限性。數組有一個很重要的結構就是索引,我們在數組中查詢數據也是用索引去查詢,因此當需要刪除數據時,必須將所有數據進行移動改變索引,性能開銷相當大,而鏈表就可以解決以上問題。
單向鏈表的結構
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Hyce4Vv3-1627915099881)(C:/Users/Supreme%20honor/Desktop/NoteBook/%E9%93%BE%E8%A1%A8.jpg)]
鏈表結構比較簡單,就是一個個節點連接在一起,形成一個完整鏈式結構。每個節點包含兩部分(如圖),一個是用于存儲數據的數據域,一個是用于指向下一個節點的next指針。當刪除數據時,只需要要改變前后節點的next引用關系即可,不需要像數組一次性出發所有數據的移動,速度比數組快很多,也節省了很大的性能開銷。
代碼實現
鏈表存儲的節點
//存儲人物信息 class HeroNode {//人物序號:鏈表操作中有根據序號進行排序的方法,添加此節點以測試鏈表數據的插入public int num;public String name;public String nickname;public HeroNode next;/*** 構造器*/public HeroNode(int num, String name, String nickname) {this.num = num;this.name = name;this.nickname = nickname;}@Overridepublic String toString() {return "HeroNode{" +"num=" + num +", name='" + name + '\'' +", nickname='" + nickname+"}";} }鏈表初始化
class SingleLinkedList {/*** 先初始化一個頭節點,不放具體的數據*/private HeroNode headNode = new HeroNode(0,"",""); }鏈表的基本操作
增加節點
/*** 添加節點到單向鏈表* 思路:當不考慮編號順序時* 1.找到當前鏈表的最后一個節點* 2.將最后節點的next指向新的節點* @param node*/public void add(HeroNode node){//因為head節點不能動,因此我們需要一個輔助遍歷指針tempHeroNode temp = headNode;//遍歷鏈表while (true){if (temp.next == null){break;}//后移指針temp = temp.next;}//退出while循環時,temp就指向了鏈表的最后//將最后的節點指向新的節點//注意:不是headNode.next = node;temp.next = node;}按照編號順序添加節點
/*** 需要按照編號的順序添加* 1.首先要找到新添加的節點的位置,是通過輔助指針遍歷* 2.新的節點.next = temp.next* 3.將temp.next = 新的節點* @param node*/ public boolean addByOrder(HeroNode node) {//頭節點不能動,因此需要使用輔助指針找到應插入的位置//單鏈表:temp要找到添加位置的前一個節點(讓這前一個節點的next域指向新的節點)HeroNode temp = headNode;//編號是否以及存在,如果存在則添加失敗boolean hasExit = false;//遍歷鏈表while (true){//鏈表遍歷完畢if (temp.next == null){break;}//要讓temp指向要添加位置的前一個節點if (temp.next.num > node.num){break;}else if (temp.next.num == node.num){hasExit = true;break;}//向后移動指針temp = temp.next;}//編號已經存在if (hasExit){System.out.println("編號已存在,添加失敗....");return false;}else{//切記順序不可調換node.next = temp.next;temp.next = node;}return true; }更新節點中數據
/*** 修改節點的信息,根據No編號來修改,No編號不能改* @param node*/ public void update(HeroNode node) {//判斷鏈表是否為空if (headNode.next == null){System.out.println("鏈表為空....");return;}//根據編號找到需要修改的節點HeroNode temp = headNode.next;boolean hasFound = false;while (true){//鏈表已經遍歷完畢if (temp == null){break;}//找到待修改節點if (temp.num == node.num){hasFound = true;break;}temp = temp.next;}//找到節點if (hasFound){temp.name = node.name;temp.nickname = node.nickname;}else{System.out.println("沒有找到該編號的節點....");} }遍歷鏈表
/*** 遍歷鏈表*/public void list(){System.out.println("-------------------------------List-------------------------------");//判斷鏈表是否為空if (headNode.next == null){System.out.println("鏈表為空");return;}//頭節點不能動HeroNode temp = headNode.next;while (true){if (temp == null){break;}//輸出節點信息System.out.println(temp);//將temp后移temp = temp.next;}}獲取鏈表長度
/*** 獲取單鏈表的節點個數(帶頭結點的鏈表不需要統計頭節點)* @return 有效節點個數*/ public int getLength() {//空鏈表if (headNode.next == null){return 0;}int length = 0;HeroNode temp = headNode;while (temp.next != null){length++;temp = temp.next;}return length; }獲取倒數第n個節點
/*** 查找單鏈表中的倒數第n個節點* 1.接受index->倒數第index個節點* 2.獲取鏈表長度length* 3.遍歷length-index個節點*/ public HeroNode getLastIndexNode(int index) throws Exception {if (headNode.next == null){return null;}int length = getLength();//對index進行校驗if (index <= 0 || index > length){throw new Exception("輸入索引錯誤!");}HeroNode temp = headNode.next;for (int i = 0; i < length - index; i++){temp = temp.next;}return temp; } 《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
- 上一篇: Ftp实现上传文件至远程服务器
- 下一篇: 数据结构:单向链表的反转