課程:《程序設計與數據結構》
班級: 1723
姓名: 王禹涵
學號: 20172323
實驗教師:王志強老師
測試日期:2018年9月
必修/選修: 必修php
鏈表練習,要求實現下列功能:
(1)經過鍵盤輸入一些整數,創建一個鏈表;
(2)實現節點插入、刪除、輸出操做;
(3)使用冒泡排序法或者選擇排序法根據數值大小對鏈表進行排序;前端
錯誤的示範:
最開始的思路是藉助上學期曾完成的一個代碼,它實現了一個以整形數爲結點的鏈表,並實現了選擇排序的功能,因此我想就在這串代碼的基礎之上完成。
首先研究的是它已提供的幾個方法
addjava
public void add(Number num) { NumberNode node = new NumberNode(num); NumberNode current; if (list == null) { list = node; } else { current = list; while (current.next != null) { current = current.next; } current.next = node; } }
這裏的add方法至關因而棧裏的Push而不是咱們所須要實現的插入的方法,這裏是我犯的第一個錯誤了。把輸入整數建立一個鏈表與在鏈表中插入整數混爲一談。
但這串代碼提供了輸入整數建立鏈表的功能,我藉助上學期用過的一個方法,將用戶輸入的一串數字經過空格間隔開,再用Integer.parseInt
的方法從新將字符轉化爲int型,再經過add的方法存入鏈表。具體的代碼以下node
LinkedList a = new LinkedList(); Scanner scan = new Scanner(System.in); System.out.println("Input some numbers into the linkedlist: "); String b = scan.nextLine(); StringTokenizer NUM = new StringTokenizer(b, " "); while (NUM.hasMoreTokens()){ a.add(Integer.parseInt(NUM.nextToken())); }
能夠說是很是的麻煩了。
這時又得從新編寫一個插入的方法,既然是要能實如今指定位置的地方插入元素,因而我想到了運用for循環來完成,又由於插入位置的不一樣分紅了兩種狀況:頭插法以及在中間或尾部插入元素。代碼以下git
public NumNode InsertNode(int num, int a) { NumNode Head = list; NumNode node = new NumNode(num); if (a == 1){ node.next = Head; Head = node; } else { NumNode temp = Head; for (int n = 0; n < a - 2; n++){ temp = temp.next; } if (temp.next == null){ temp.next = node; } else { NumNode node1 = temp.next; temp.next = node; node.next = node1; } } return Head; }
測試類的代碼不放在上面,但最終運行的結果出現了問題。雖然在中部和尾部插入沒有出現問題,但在頭部的插入出現了問題,在執行插入操做以後,最終顯示的結果並無插入成功。如圖
web
最後經過debug的調試發如今編寫的類中雖然有return Head,但測試類中並無語句使得Head的值return到鏈表裏。解決的方法就是將鏈表a再賦給a一次,如a = a.InsertNode(c,d);
(c是要插入的數,d是要插入的位置),但仍是會報錯,緣由在於類型的不兼容,如圖
數據結構
一邊a的定義是LinkedList類型,一邊又要調用NumNode的方法。因此方法最終是不可行的。測試
成功的解決
最終我想選擇運用啞結點的方法來解決頭插法的插入問題。this
經過在列表的前端引入哨兵結點或啞結點,能夠去除涉及第一個結點的狀況。哨兵結點能夠做爲一個假的第一個結點,並無真正表示列表中的某個元素。當使用了哨兵結點時,全部的插入和刪除操做都不用考慮太多特殊狀況。debug
一開始我是想真的設置一個哨兵結點,即不在裏面放數字,僅有next的方法連接真正的鏈表。但設置Numnode head1 = null
或者Numnode head1 = ""
彷佛並不能使head1成爲空結點,Numnode定義裏要求必須插入一個數字,因此最後就只有將就着設置一個假的啞結點Numnode head1 = new Numnode(0)
,而後很機智的在toString方法裏修改一下,不顯示第一個結點就能夠了。
public String toString() { String result = ""; NumNode current = head1.next; while (current != null) { result += current.number + " "; current = current.next; } return result; }
toString方法:這裏就設置了一下,使得顯示的時候從head1的下一個head1.next
開始。
private class NumNode{ public int number; public NumNode next; public NumNode(int number) { this.number = number; next = null; } }
Numnode方法:定義告終點的方法,包括一個int型number,和指向下一結點的next。
public void InsertNode(int num, int a) { head1.next = list; NumNode node = new NumNode(num); NumNode temp = head1; for (int x = 0; x < a - 1; x++){ temp = temp.next; } if (temp.next == null){ temp.next = node; } else { NumNode node1 = temp.next; temp.next = node; node.next = node1; } }
InsertNode方法:num表示要插入的數字,a表示要插入的位置。先將num放入一個無連接的元素node,用for循環找到要插入的位置以後,再將前一個位置的next指針指向node,再將node的next指向下一個指針。
若是是直接在鏈表的末端插入的話就是上文提到的add方法了。我編寫的代碼裏有一點小的缺陷就是,沒有將插入和添加的方法分得很開,若是故意用插入的方法將元素添加到鏈表末尾應該是會報錯的吧,由於node的next指針不能指向下一結點。
public void delete(int k){ head1.next = list; NumNode PreNode = null, Currentnode = head1; for (int x = 0; x < k - 1; x++){ if (Currentnode.next != null){ PreNode = Currentnode; Currentnode = Currentnode.next; PreNode.next = Currentnode.next; } else{ PreNode = Currentnode; PreNode.next = null; } } }
delete方法:刪除的代碼實現本質上與插入相差無異,插入的編好刪除也完成了一大半了。
public void sort() { NumNode min; int temp; NumNode numNode = list; while (numNode != null) { min = numNode; NumNode current = min.next; while (current!=null) { if(Integer.parseInt(String.valueOf(min.number)) > Integer.parseInt(String.valueOf(current.number))) { min = current ; } current = current.next; } temp = min.number; min.number = numNode.number; numNode.number = temp; numNode = numNode.next; } }
sort方法:排序的方法是借鑑的上學期的選擇排序法,這大概是惟一沒碰見問題的地方。
node.next = Head
,Head = node
,return Head
,但最後toString並無顯示頭插法的結果。a = a.InsertNode(c,d);
,但在這串代碼裏InsertNode是Numnode的方法,而a是LinkedList型,因此二者類型不兼容,不一樣類型的值的賦值會報錯原本是想這學期每一個測試都能好好作,一篇博客也不要補,即使是本身作的不好勁也不要補博客。嗯...真香 測試實際上是有在好好作,奈何讀題太快,完成做業的心態也比較浮躁,致使最後並無好的結果,因此不得不認認真真地再補一篇博客。一開始仍是抱着想快點了事的心態在作,因此很快就把前半部分寫了出來,後來補代碼遇到瓶頸再仔細審題我才眉頭一皺發現事情並不簡單,特別是涉及到頭結點的問題真是費腦筋,上面的只是一小部分個人記錄,真實狀況遠比這複雜得多,一個星期裏我既抱着個人代碼不放,不想就此打水漂,但問題又始終解決不了,另外一方面我借鑑了數十個同窗的代碼,發現多多少少都有一些問題,想借此矇混過關幾乎不可能。 因此最後獻上的代碼絕對使我絞盡腦汁想了好久好久才寫出來的解決方法,萬望學長學姐多給點分。