《java常用演算法手冊》 第二章 資料結構 順序表 單鏈表
阿新 • • 發佈:2018-11-11
資料元素:例如單向連結串列的一個節點 擁有 頭指標和資料兩個資料組成
四種儲存方式 :
順序表的實現 :
package LineStructure; //順序表 public class SeqList<T> extends Object { // 表長 private int length; // 節點元素 private Object[] element; // 空構造 預設容量的空表 public SeqList() { this(64); } // 初始化 構造容量為length的空表 public SeqList(int length) { this.length = 0; this.element = new Object[length]; } // 構造有元素的順序表 public SeqList(T ele[]) { this(ele.length); // 複製元素到順序表中 for (int i = 0; i < ele.length; i++) { element[i] = ele[i]; } } // 判斷是否為空表 public boolean isEmpty() { return this.length == 0; } // 返回 長度 public int size() { return this.length; } // 返回順序表所有元素的描述字串,形式為“(,)” 覆蓋toString方法 public String toString() { StringBuffer sb = new StringBuffer(); sb.append("{"); sb.append(this.element[0]); for (int i = 1; i < this.length; i++) { sb.append(","+this.element[i]); } sb.append("}"); return sb.toString(); } // 查詢節點 返回第i個元素 public T get(int i) { if (i > 0 && i < this.length) { return (T) this.element[i]; } else { return null; } } // 修改第i個元素 注意並不是插入元素 public void set(int i, T value) { if (value == null) { throw new NullPointerException("sorry x == null"); } else if (i > 0 && i < this.length) { this.element[i] = value; } else { throw new java.lang.IndexOutOfBoundsException("Sorry your element :" + i + " IndexOutOfBounds"); } } // 插入元素 public String insert(int i, T value) { if (value == null) { throw new NullPointerException("x == null"); } else if (i < 0) {// 插入到最前端 i = 0; // this.element[0] = value; } else if (i > this.length) {// 插入到最後端 i = this.length; // this.element[this.length] = value; } // 由於無法直接擴容 element2臨時存放值錢的元素 Object[] elementTemp = this.element; // 擴容 重新開闢空間存放元素 if (i > this.length) { this.element = new Object[elementTemp.length * (2 / 3)]; } // 賦值插入位置之前的元素 // 前i-1個元素給新的element for (int j = 0; j < i; j++) { this.element[j] = elementTemp[j]; } // 移動插入位置之後的元素 // 插入到中間 i之後的元素後移 順序為從前向後,也可以從後向前 //錯誤 只能從後向前 elementTemp是this.element的引用 不是副本 /*for (int j = i; j < elementTemp.length-1; j++) { this.element[j + 1] = elementTemp[j]; }*/ //從後向前 for(int j=this.length-1;j>=i;j--){ this.element[j+1] = elementTemp[j] ; } // 插入元素 this.element[i] = value; this.length++; return "insert success element" + value + "insert into position: " + i; } // 預設插入 插入到表最後 public String insert(T value) { return insert(this.length, value); } // 移除元素 public String remove(int i) { if (i >= 0 && i < this.length && this.length > 0) { // i之後元素向前移動 for (int j = i; j < this.length - 1; j++) { this.element[j] = this.element[j + 1]; } // 注意:最後一個元素設定為空 this.element[this.length - 1] = null; this.length--; } else { return null; } return "success"; } // 清除 public void clear() { for (int j = 0; j < this.length; j++) { this.element[j] = null; } this.length = 0; } // 查詢元素 返回序號 public int search(T value) { for (int i = 0; i < this.length; i++) { if (value == this.element[i]) { return i; } } return -1; } public boolean contains(T value) { return this.search(value) != -1; } }
單鏈表實現 :
package LineStructure; public class LinkedList<T> extends Object { // 理解java引用 http://zwmf.iteye.com/blog/1738574 // 兩種思路 第一種插入節點(包含資料) // 參考 https://www.cnblogs.com/whgk/p/6589920.html // 第二種插入資料,需要new 節點,感知不到節點的存在 // https://blog.csdn.net/jianyuerensheng/article/details/51200274 // 每一個節點存放下一個節點的引用 public class Node { private Object data; // 存放下一個節點的引用 private Node next; // Node的構造 public Node() { data = null; } // Node的構造 public Node(T data) { this.data = data; } } // 頭節點 的Data 一般是不儲存資料的 private Node head; // 頭引用(指標) private Node rear; // 尾引用(指標) private Node point; // 臨時引用(指標) private int length; // 連結串列長度 // 連結串列類的構造方法,只構造出不含資料的頭結點。 此時尾引用指向頭引用 構成一個完整的連結串列 // 頭節點 的Data 一般是不儲存資料的 public LinkedList() { head = new Node(); rear = head; length = 0; } // 增加節點 public void addNode(Node node) { // 連結串列中已有節點 需要遍歷到最後一個節點 Node temp = head; // 一個移動的指標(遍歷指標)(從頭節點開始遍歷) // 如果連結串列是空的則 temp為head,head之後追加Node while (temp.next != null) { // 遍歷單鏈表,直到遍歷到最後一個則跳出迴圈。 temp = temp.next; // 遍歷指標往後移一個結點,指向下一個結點。 } temp.next = node; // temp為最後一個結點或者是頭結點,將其next指向新結點 這樣頭節點中沒有資料 } // 插入指定位置 // 前一個結點 當前位置 後一個結點 // temp temp.next temp.next.next public void insertNodeByIndex(int index, Node node) { int position = 1; Node temp = head; while (temp.next != null) { if (index == position) { // 插入節點指向之前temp的next node.next = temp.next; // temp的next指向node temp.next = node; return;// 注意return 減少時間複雜度 } position++; temp = temp.next;// 指標後移 對temp的賦值不會影響整個連結串列 } } // 刪除節點 public void delNodeByIndex(int index) { int position = 1; Node temp = head;// 指標 當前節點 // 之前寫法 錯誤: while條件有誤 temp.next 可能為空 /* * while (temp.next != null) { if (index == position) { temp.next = * temp.next.next; // 對temp的賦值不會影響整個連結串列(temp為臨時指標) 但是對temp.next賦值影響了連結串列的指標 * return;// 注意return 減少時間複雜度 } position++; temp = temp.next; // * 對temp的賦值不會影響整個連結串列(temp為臨時指標) 但是對temp.next賦值影響了連結串列的指標 * * } */ // 修改while條件 while (index != position) { position++; temp = temp.next; // 對temp的賦值不會影響整個連結串列(temp為臨時指標) 但是對temp.next賦值影響了連結串列的指標 } temp.next = temp.next.next; // 對temp的賦值不會影響整個連結串列(temp為臨時指標) 但是對temp.next賦值影響了連結串列的指標 return;// 注意return 減少時間複雜度 } // 計算長度 public int getLength() { int position = 0; Node temp = head;// 指標 當前節點 while (temp.next != null) { position++; } temp = temp.next; return position; } // 按下標查詢節點 // 頭節點 的Data 一般是不儲存資料的 public T find(int position) { // 0為頭節點 沒有資料 int start = 0; Node temp = head; while (position != start) { temp = temp.next; start++; } return (T) temp.data; } // 查詢元素的值,返回下標 // 頭節點 的Data 一般是不儲存資料的 public int search(T value) { int start = 1; Node temp = head; // 之前的寫法 錯誤 while條件錯誤 尾節點的temp.next可能為空!! /* * while(temp.next != null) { if(temp.next.data == value) { return start; } * start++; temp = temp.next; * * } */ while (temp.next.data != value) { start++; temp = temp.next; } return start; } // 遍歷單鏈表,列印所有data // 頭節點 的Data 一般是不儲存資料的 public String toString() { Node temp = head; StringBuffer sb = new StringBuffer(); sb.append("headNode"); while (temp.next != null) { sb.append("," + temp.next.data); temp = temp.next; } return sb.toString(); } // 連結串列sort // 關於sort:https://www.cnblogs.com/whgk/p/6596787.html public void selectSort() { Node temp = head;// 外層指標 while (temp.next != null) { Node temp2 = temp;// 內層指標 while (temp2.next != null) { if ((int) temp.next.data > (int) temp2.next.data) { int tempData = (int) temp.next.data; temp.next.data = temp2.next.data; temp2.next.data = tempData; } temp2 = temp2.next; } temp = temp.next; } } }