小結前端
單鏈表(帶頭節點)邏輯示意圖
java
使用帶 head頭的單向鏈表實現水滸傳英雄排行榜,管理面試
單鏈表的建立示意圖(添加),顯示單向鏈表的分析
數據結構
public class SingleLinkedListDemo { public static void main(String[] args) { //進項測試 //先建立節點 HeroNode hero1 = new HeroNode(1, "松江", "及時雨"); HeroNode hero2 = new HeroNode(2, "盧俊義", "玉麒麟"); HeroNode hero3 = new HeroNode(3, "吳用", "智多星"); HeroNode hero4 = new HeroNode(4, "林沖", "豹子頭"); //加入 想要建立鏈表 SingleLinkedList singleLinkedList = new SingleLinkedList(); singleLinkedList.add(hero1); singleLinkedList.add(hero4); singleLinkedList.add(hero2); singleLinkedList.add(hero3); //顯示一把 singleLinkedList.list(); } } //定義 SingleLinkedListDemo 管理咱們的英雄 class SingleLinkedList { //先初始化一個頭節點,頭節點不要動,不存放具體的數據 private HeroNode head = new HeroNode(0, "", ""); //添加節點到單向鏈表 /* * 思路:當不考慮編號順序時 * 1. 找到當前鏈表的最後節點, * 2. 將最後這個節點的next 指向 新的節點 * */ public void add(HeroNode heroNode) { //由於 head節點不能動,所以咱們須要一個輔助遍歷 temp HeroNode temp = head; //遍歷鏈表找到最後, while (true) { //找到鏈表的最後 if (temp.next == null) { break; } //若是沒有找到最後 temp = temp.next; } //當退出 while循環時,temp就指向鏈表的最後 //將最後這個節點的 next,指向新的節點 temp.next = heroNode; } //顯示鏈表 遍歷 public void list() { //先判斷鏈表是否爲空 if (head.next == null) { System.out.println("鏈表爲空"); return; } //由於頭節點不能動,所以咱們須要一個輔助變量來遍歷 HeroNode temp = head.next; while (true) { //判斷是否到鏈表最後 if (temp == null) { break; } //輸出節點的信息 System.out.println(temp); //不要忘記 將 temp後移 temp = temp.next; } } } //定義HeroNode,每一個HeroNode 對象就是一個節點 class HeroNode { public int no; public String name; public String nickname; public HeroNode next;//指向下一個節點 //構造器 public HeroNode(int no, String name, String nickname) { this.no = no; this.name = name; this.nickname = nickname; } //爲了顯示方法,咱們重寫 toString next就不要顯示了 @Override public String toString() { return "HeroNode{" + "no=" + no + ", name='" + name + '\'' + ", nickname='" + nickname + '\'' + '}'; } }
//第二種方時在添加英雄時,根據排名將英雄插入到指定位置(若是有這個排名,則添加失敗,並給出提示) public void addByOrder(HeroNode heroNode) { //由於頭節點不能動,所以咱們仍然經過一個輔助指針(變量)來幫助咱們找到添加的位置 //由於單鏈表,由於咱們找到的temp,是位於 添加位置的前一個界定啊,不然插入不了 HeroNode temp = head; boolean flag = false;//flag 標誌添加的編號是否存在,默認爲false while (true) { if (temp.next == null) {//說明 temp已經在鏈表的最後 break;//不管如何都要退出 } if (temp.next.no > heroNode.no) {//位置找到,就在 temp的後面插入 break; } else if (temp.next.no == heroNode.no) {//說明但願添加的 heroNode的編號依然存在 flag = true;//說明編號存在 break; } //若是上面的都沒有成立 temp要後移,遍歷當前鏈表 temp = temp.next; } //判斷 flag的值 if (flag) {//不能添加,說明編號已經存在 System.out.println("準備插入的英雄的編號" + heroNode.no + "已經存在不能添加"); } else { //插入到鏈表中 temp的後面 heroNode.next = temp.next; temp.next = heroNode; } }
思路:ide
//說明 //修改節點的信息,根據no編號修改,即 no編號不能修改 //1.根據 newHeroNode 的 no來修改便可 public void update(HeroNode newHeroNode) { //判斷是否爲空 if (head.next == null) { System.out.println("鏈表爲空"); return; } //找到須要的修改的節點,根據no編號 //先定義一個輔助變量 HeroNode temp = head.next; boolean flag = false;//表示是否找到該節點 while (true) { if (temp == null) { break;//到鏈表的最後==>最後節點的下一個 } if (temp.no == newHeroNode.no) { //找到了 flag = true; break; } temp = temp.next; } //根據 flag判斷是否找到修改的節點 if (flag) { temp.name = newHeroNode.name; temp.nickname = newHeroNode.nickname; } else {//沒有找到 System.out.println("沒有找到編號" + newHeroNode.no + "的節點,不能修改"); } }
//刪除節點 //思路 //1. head 不能動,所以咱們須要一個 temp輔助節點找到待刪除的前一個節點 //2. 說明咱們在比較時,是 temp.next.no 和 須要刪除的節點的no比較 public void del(int no) { HeroNode temp = head; boolean flag = false;//標誌是否找到待刪除節點的前一個節點 while (true) { if (temp.next == null) {//已經到鏈表的最後了 break; } if (temp.next.no == no) { //找到了待刪除節點的前一個節點 temp flag = true; break; } //temp 後移,遍歷 temp = temp.next; } //判斷 flag if (flag) { //能夠刪除 temp.next = temp.next.next; } else {//未找到該節點 System.out.println("找刪除的" + no + "節點未找到"); } }
//方法:獲取單鏈表的節點的個數(若是是帶頭節點的鏈表,須要不統計頭節點) /** * @param head 鏈表的頭節點 * @return int 返回的就是有效節點的個數 */ public static int getLength(HeroNode head) { if (head.next == null) { //空鏈表 return 0; } int length = 0; //定義一個輔助的變量 HeroNode cur = head.next; while (cur != null) { length++; cur = cur.next;//遍歷 } return length; }
//查找單鏈表中的倒數第k個結點 【新浪面試題】 /** * 思路: * 1. 編寫一個方法,接收 head節點,同時接收一個 index * 2. index 表示倒數第 index個節點 * 3. 先把鏈表從到位遍歷,獲得鏈表的總的長度 [調用 getLength方法 獲取單鏈表的個數] * 4. 獲得 size後,咱們從鏈表的第一個開始遍歷(size - index)個,就能夠獲得 * 5. 若是找到,則返回該節點,不然返回 null * * @param head 單鏈表頭節點 * @param index 倒數第n個節點的下標 * @return 倒數第n個節點 */ public static HeroNode findLastIndexNode(HeroNode head, int index) { //判斷若是鏈表爲空,返回null if (head.next == null) { return null;//沒有找到 } //第一個遍歷獲得鏈表的長度(節點個數) int size = getLength(head); //第二次遍歷 size-index 位置,就是咱們倒數的第k個節點 //想作一個index的校驗 if (index <= 0 || index > size) { return null; } //先定義輔助變量,for 循環定義倒數的 index HeroNode cur = head.next; //假如3個有效數據 //3-1=2 for (int i = 0; i < size - index; i++) { cur = cur.next; } return cur; }
//單鏈表的反轉【騰訊面試題,有點難度】 /** * 思路: * 1. 先定義一個節點 reverseHead = new heroNode(); * 2. reverseHead節點;不存放具體的數據;做用就是表示單鏈表頭 next * 3. 從頭到位遍歷原來的鏈表,每遍歷一個節點,就將其取出,並放在新的鏈表 reverseHead的最前端 * 4. 原來的鏈表的 head.next=reverseHead.next * * @param head 須要反轉的頭節點 */ public static void reverseList(HeroNode head) { //若是當前鏈表爲空,或者只有一個節點,無需反轉,直接返回 if (head.next == null || head.next.next == null) { return; } //定義一個輔助的指針(變量),幫助咱們遍歷原來的鏈表 HeroNode cur = head.next; HeroNode next = null;//指向當前節點[cur]的下一個節點 //定義:reverseHead節點;不存放具體的數據;做用就是表示單鏈表頭 next HeroNode reverseHead = new HeroNode(0, "", ""); //遍歷給原來的鏈表 // 並頭到位遍歷原來的鏈表,每遍歷一個節點,就將其取出,並放在新的鏈表 reverseHead的最前端 //動腦筋 while (cur != null) { next = cur.next;//先暫時保存當前節點的下一個節點,由於後面須要使用 cur.next = reverseHead.next;//將cur的下一個節點指向新的鏈表節點的頭部[最前端] reverseHead.next=cur;//將 cur鏈接到新的鏈表上 cur = next;//讓 cur後移 } //將 head.next 指向 reverseHead.next ,實現單鏈表的反轉 head.next = reverseHead.next; }
//從尾到頭打印單鏈表 【百度,要求方式1:反向遍歷 。 方式2:Stack棧】 /** * 思路: * 1. 上面的題的要求就是逆序打印單鏈表 * 2. 方式1: 先將單鏈表進行反轉操做,而後在遍歷便可,這樣作的問題是會破壞原來的單鏈表結構,不建議 * 3. 方式2: 能夠利用棧這個數據結構,將各個節點壓入到棧[先進後出,好比子彈進子彈夾]中,而後 * 利用棧的先進後出的特色,就實現了逆序打印的效果 * 採用方式二 * * @param head 單鏈表頭部 */ public static void reversePrint(HeroNode head) { if (head.next == null) { return;//空鏈表不能打印 } //建立一個棧,將各個節點壓入棧中 //Stack特色; 先進後出 Stack<HeroNode> stack = new Stack<>(); HeroNode cur = head.next; //將鏈表的全部節點壓入棧中 while (cur != null) { stack.push(cur); //必定rur要後移,這樣就能壓入下一個節點 cur = cur.next; } //將棧中的節點打印,pop 出棧 while (stack.size() > 0) { System.out.println(stack.pop());//彈棧 } }
和反轉很像,建立一個新的鏈表發現鏈表中的哪個更小就把他假如到新的鏈表中