作力扣 的算法題 忽然想到這個數據結構,以爲有必要記錄下來java
1. 定義一個Link類和一個Node類,其中Node類爲Link類的內部類(避免了反覆的getter和setter方法)
Link類的目的是進行節點建立
Node類的目的是進行數據和節點連接,而且Node只能爲Link調用,須要定義爲private
再定義一個Factory類,用來給客戶端調用,返回的是一個Link類的實例node
2. Node類中須要包含有如下屬性:
(1) Object data : 用於存放數據
(2) Node next : 用戶存放指向下一個節點的數據
構造函數就是給data賦值
3. 增長1個追加函數,往鏈表中添加元素
(1) 明確的是,追加數據要在Link類中完成
(2) 須要先在Link類中聲明root根節點
(3) 若是沒有傳入數據,那麼就直接返回,不作操做
(4) 對於存放的數據,那麼就要新建一個節點,新建一個節點對象,而後把這個節點對象交給Node類去處理
(5) 第4步中,存放節點數據應該從root開始,若是root爲空,那麼存放的數據就是root,只要把新建節點賦值給root便可
若是不是,那麼就要把新建節點交由Node類處理,從root節點開始
(6) Node類接收Link類傳過來的newNode對象,作如下處理:
判斷root的next是否爲空值,如果,則把newnode賦值給root.next
若不爲空,那麼遞歸,下個是root.next.next
以上完成增長一個數據,並處理節點關係
測試程序爲:
//
public class TestLinkDemo {
public static void main(String[] args) {
Link all = Factory.getInstance();
all.add("AAA");
all.add("BBB");
all.add("CCC");
}
}
//
4. 增長一個函數,獲取鏈表中的數據個數
(1) 在Link類中定義屬性,統計個數,count
(2) 定義方法,獲取count,就是返回數據個數
(3) 定義isEmpty()方法,判斷鏈表是否爲空
5. 增長一個函數,能夠把鏈表轉換成對象數組
(1) 鏈表就是一個動態數組,返回類型爲Object[] data,每一個數據的取得有前後順序,所以須要定義一個遊標
(2) Link類中,首先須要判斷,鏈表長度是否爲零,若是是零,就返回空值,若是不是0,則須要遍歷整個鏈表,
遊標爲0,從root節點開始調用Node中取出數據的函數(新定義)
(3) Node類中須要獲取每一個節點的數據,並填寫到數組中,若是判斷下個節點還有數據,那麼就要繼續遞歸
6. 增長一個查詢數據的方法
(1) 須要equals方法支持
(2) Node中追加一個方法,用於查找指定元素,並且必須從root節點開始日後找
(3) Link中追加一個方法,用於判斷必須輸入查找內容,以及鏈表不爲空,若正常,就調用Node中的方法,從root開始
7. 根據索引取得數據
(1) 在Node類裏面增長一個索引查找的方法,根據遊標查找
(2) 在Link類中增長一個索引查找方法,目的是保證鏈表有數據,同時初始化遊標,查找的時候從root節點日後找算法
8. 修改指定索引的數據
(1) 首先在Link類中定義一個方法,傳入2個參數,第一個爲索引值,第二個是要修改爲的目標對象值
考慮問題,若是索引超過了鏈表長度,那麼就不修改,結束調用
不然就先設定遊標,而後從root節點開始調用Node中真正修改數據的函數
(2) Node類中定義的方法,首先判斷當前遊標是否爲指定遊標,如果,則修改數據
若不是,判斷當前是否是最後一個節點,若是節點不爲空,那麼繼續日後查找節點,遞歸調用數組
9. 刪除數據
(1) 全部的前提是存在該數據,全部首先由上面定義的查找方法進行查找
若是刪除的是根節點,更換root的操做只須要在Link類中完成便可
若是不是,那麼要把根節點的下一個節點交給Node類中的刪除方法進行
(2) Node類中判斷當前對象的數據是不是要刪除的數據,若是是的話,就把這個對象的上一個next指向下一個next數據結構
若是不是,則繼續遞歸刪除函數
更新一下查找方法,原課程寫的有問題測試
//根據索引取得數據 public Object getNode(int searchIndex) { if (Link.this.index++ == searchIndex) { return this.data; } else { return this.next.getNode(searchIndex); } } class Link { private Node root; //根節點,增長數據函數添加 private int count; //統計元素個數 private Object[] retData; //返回對象數組 private int index = 0; //操做遊標 // 定義Node內部類,表示Node只爲Link類服務 private class Node { //負責 保存數據,節點關係配置 private Object data; private Node next; public Node(Object data) { this.data = data; } //增長數據 public void addNode(Node newNode) { if (this.next == null) { this.next = newNode; } else { this.next.addNode(newNode); } } //轉換成對象數組 public void toArrayNode() { Link.this.retData[Link.this.index ++] = this.data;//先把root節點的數據取出,而後遊標加一 if (this.next != null){ //若是下個節點還有數據,則遞歸獲取 this.next.toArrayNode(); } } //查找數據 public boolean containsNode(Object search) { if (search.equals(this.data)) { return true; //找到數據 } else { if (this.next != null) { //還有後續節點 return this.next.containsNode(search);//遞歸查找 } else { return false; } } } //根據索引取得數據 public Object getNode(int searchIndex) { if (Link.this.index ++ == searchIndex) { return this.data; } else { this.next.getNode(searchIndex); } return null; } //修改指定索引的數據 public void setNode(int searchIndex, Object newData) { if (Link.this.index ++ == searchIndex) { this.data = newData; } else { if (this.next != null) { this.next.setNode(searchIndex,newData); } } } //刪除元素 public void removeDataNode(Node previous, Object data) { if (this.data.equals(data)) { previous.next = this.next; //中間是this,若是this的data是所要刪除的data,那麼把this以前的一個node指向this以後的一個node } else { this.next.removeDataNode(this, data); } } } // ---------如下是Link類定義----------- //增長元素 public void add(Object data) { if ( data == null ) {//不容許存放空值數據 return; } Node newNode = new Node(data); //建立一個新的節點 if (this.root == null) { this.root = newNode; } else { this.root.addNode(newNode); } this.count ++; } //獲取鏈表大小 public int size() { return this.count; } //判斷鏈表是否爲空 public boolean isEmpty() { if (this.root == null && this.count == 0 ) { return false; } else { return true; } } //鏈表轉換成對象數組 public Object[] toArray() { if (this.count == 0) { //若是鏈表沒有數據,那麼就返回null return null; } this.retData = new Object[this.count];//若是count不爲零,那麼開闢指定空間的對象數組 this.index = 0;//遊標初始化爲0 this.root.toArrayNode();//交給Node類進行數據的取出 return this.retData;//返回對象數組 } //查找數據 public boolean contains(Object search) { if (search == null || this.root == null) { return false; } return this.root.containsNode(search); } //根據索引取得數據 public Object get(int searchIndex) { if (searchIndex >= this.count) { return null; } this.index = 0; return this.root.getNode(searchIndex); } //修改指定索引的數據 public void setData(int searchIndex, Object newData) { if (searchIndex >= this.count) { return ; } else { this.index = 0; this.root.setNode(searchIndex, newData); } } //刪除數據 public void removeData(Object data) { if (this.contains(data)) { if (this.root.data.equals(data)) { this.root = this.root.next; } else { this.root.next.removeDataNode(this.root, data); } this.count --; } } } class Factory { public static Link getInstance() { return new Link(); } } public class TestLinkDemo { public static void main(String[] args) { Link all = Factory.getInstance(); // all.add("AAA"); all.add("BBB"); all.add("CCC"); // System.out.println("鏈表大小爲: " + all.size()); // Object[] result = all.toArray(); System.out.println("鏈表轉換成對象數組並輸出: "); for ( Object x : result ) { System.out.println(x); } //查詢數據方法 System.out.println("查詢數據方法: "); System.out.println(all.contains("AAA")); System.out.println(all.contains("D")); //取得索引數據 System.out.println("查找索引爲0的數據: "); System.out.println(all.get(0)); System.out.println("查找索引爲3的數據: "); System.out.println(all.get(3)); //修改索引數據 System.out.println("修改索引數據: "); all.setData(0,"DDD"); Object[] result1 = all.toArray(); System.out.println("修改索引數據並輸出: "); for ( Object x : result1 ) { System.out.println(x); } //刪除數據 System.out.println("刪除數據: "); all.removeData("BBB"); Object[] result2 = all.toArray(); System.out.println("刪除數據並輸出: "); for ( Object x : result2 ) { System.out.println(x); } } }
測試結果:this