鏈表是一種常見的基礎數據結構,它是一種線性表,但在記憶體中它並不是順序存儲的,它是以鏈式進行存儲的,每一個節點里存放的是下一個節點的“指針”。在Java中的數據分為引用數據類型和基礎數據類型,在Java中不存在指針的概念,但是對於鏈表而言的指針,指的就是引用數據類型的地址。 鏈表和數組都是線性的數據結 ...
鏈表是一種常見的基礎數據結構,它是一種線性表,但在記憶體中它並不是順序存儲的,它是以鏈式進行存儲的,每一個節點里存放的是下一個節點的“指針”。在Java中的數據分為引用數據類型和基礎數據類型,在Java中不存在指針的概念,但是對於鏈表而言的指針,指的就是引用數據類型的地址。
鏈表和數組都是線性的數據結構,對於數組而言其長度是固定的,由於在記憶體中其是連續的,因此更適合做查找與遍歷,而鏈表在記憶體中是並不是順序存儲的,但是由於其是通過“指針”構成的,因此在插入、刪除時比較數組更為的方便。
下麵的代碼通過內部類並結合遞歸的方式來實現了一個簡單的用Java語言描述的鏈表的數據結構。
首先來看一下,鏈表數據結構的定義,代碼如下:
1 class NodeManager { 2 private Node root; // 根節點 3 private int currentIndex = 0; // 節點的序號,每次操作從0開始 4 5 public void add(int data) {} 6 public void delNode(int data) {} 7 8 public void print() {} 9 10 public boolean findNode(int data) {} 11 12 public boolean updateNode(int oldData, int newData) {} 13 14 // 向索引之前插入 15 public void insert(int index, int data) {} 16 17 // 誰擁有數據,誰提供方法 18 class Node { 19 private int data; 20 private Node next; // 把當前類型作為屬性 21 22 public Node(int data) { 23 this.data = data; 24 } 25 26 public void setData(int data) { 27 this.data = data; 28 } 29 30 public int getData() { 31 return data; 32 } 33 34 // 添加節點 35 public void addNode(int data) {} 36 37 // 刪除節點 38 public void delNode(int data) {} 39 40 // 輸出所有節點 41 public void printNode() {} 42 43 // 查找節點是否存在 44 public boolean findNode(int data) {} 45 46 // 修改節點 47 public boolean updateNode(int oldData, int newData) {} 48 49 // 插入節點 50 public void insertNode(int index, int data) {} 51 } 52 }
對於鏈表的定義來說,NodeManager類是用來管理鏈表操作的,而成員內部類Node是用於提供鏈表數據與鏈式結構的。對於類的使用者來說,並不直接訪問數據,因此操作的是NodeManager類,而內部類Node提供了真正的數據管理,因此Node類需要提供真正的數據操作方法,對於NodeManager類中也需要提供一套由外部來操作鏈表的方法。因此,在NodeManager類和Node類中都提供了看似相同的方法,但實際的意義並不相同。
下麵來查看NodeManager類和Node類中的add()方法,代碼如下:
1 public void add(int data) { 2 if ( root == null ) { 3 root = new Node(data); 4 } else { 5 root.addNode(data); 6 } 7 } 8 9 // 添加節點 10 public void addNode(int data) { 11 if ( this.next == null ) { 12 this.next = new Node(data); 13 } else { 14 this.next.addNode(data); 15 } 16 }
代碼中上面的方法是NodeManager類中的方法,而下麵的方法是Node類中的方法。
在Manager類中提供了一個root的成員變數,它用於管理鏈表的頭節點,因此在添加節點時,會先判斷root是否為空,如果為空則直接將節點由root來進行保存,如果root不為空,則通過Node類中的addNode()方法來進行添加,添加到思路是找到當前鏈表的最後一個節點,並將新添加到節點賦值給最後一個節點的next成員變數中。
對於鏈表的其他操作也是相同的思路,關於鏈表增刪改查和輸出的完整代碼如下:
1 class NodeManager { 2 private Node root; // 根節點 3 private int currentIndex = 0; // 節點的序號,每次操作從0開始 4 5 public void add(int data) { 6 if ( root == null ) { 7 root = new Node(data); 8 } else { 9 root.addNode(data); 10 } 11 } 12 public void delNode(int data) { 13 if ( root == null ) return ; 14 if ( root.getData() == data ) { 15 Node tmp = root; 16 root = root.next; 17 tmp = null; 18 } else { 19 root.delNode(data); 20 } 21 } 22 23 public void print() { 24 if ( root != null ) { 25 System.out.print(root.getData() + " "); 26 root.printNode(); 27 System.out.println(); 28 } 29 } 30 31 public boolean findNode(int data) { 32 if ( root == null ) return false; 33 if ( root.getData() == data ) { 34 return true; 35 } else { 36 return root.findNode(data); 37 } 38 } 39 40 public boolean updateNode(int oldData, int newData) { 41 if ( root == null ) return false; 42 if ( root.getData() == oldData ) { 43 root.setData(newData); 44 return true; 45 } else { 46 return root.updateNode(oldData, newData); 47 } 48 } 49 50 // 向索引之前插入 51 public void insert(int index, int data) { 52 if ( index < 0 ) return ; 53 currentIndex = 0; 54 if ( index == currentIndex ) { 55 Node newNode = new Node(data); 56 newNode.next = root; 57 root = newNode; 58 } else { 59 root.insertNode(index, data); 60 } 61 } 62 63 // 誰擁有數據,誰提供方法 64 class Node { 65 private int data; 66 private Node next; // 把當前類型作為屬性 67 68 public Node(int data) { 69 this.data = data; 70 } 71 72 public void setData(int data) { 73 this.data = data; 74 } 75 76 public int getData() { 77 return data; 78 } 79 80 // 添加節點 81 public void addNode(int data) { 82 if ( this.next == null ) { 83 this.next = new Node(data); 84 } else { 85 this.next.addNode(data); 86 } 87 } 88 89 // 刪除節點 90 public void delNode(int data) { 91 if ( this.next != null ) { 92 if ( this.next.getData() == data ) { 93 Node tmp = this.next; 94 this.next = this.next.next; 95 tmp = null; 96 } else { 97 this.next.delNode(data); 98 } 99 } 100 } 101 102 // 輸出所有節點 103 public void printNode() { 104 if ( this.next != null ) { 105 System.out.print(this.next.getData() + " "); 106 this.next.printNode(); 107 } 108 } 109 110 // 查找節點是否存在 111 public boolean findNode(int data) { 112 if ( this.next != null ) { 113 if ( this.next.getData() == data ) { 114 return true; 115 } else { 116 return this.next.findNode(data); 117 } 118 } 119 120 return false; 121 } 122 123 // 修改節點 124 public boolean updateNode(int oldData, int newData) { 125 if ( this.next != null ) { 126 if ( this.next.getData() == oldData ) { 127 this.next.setData(newData); 128 return true; 129 } else { 130 return this.next.updateNode(oldData, newData); 131 } 132 } 133 return false; 134 } 135 136 // 插入節點 137 public void insertNode(int index, int data) { 138 currentIndex ++; 139 if ( index == currentIndex ) { 140 Node newNode = new Node(data); 141 newNode.next = this.next; 142 this.next = newNode; 143 } else { 144 this.next.insertNode(index, data); 145 } 146 } 147 } 148 }
以上就是鏈表基本操作的完整代碼,下麵寫一個調用的代碼進行測試,代碼如下:
1 public class LinkList { 2 public static void main(String[] args) { 3 NodeManager nm = new NodeManager(); 4 System.out.println("鏈表的添加(添加5、4、3、2、1)"); 5 nm.add(5); 6 nm.add(4); 7 nm.add(3); 8 nm.add(2); 9 nm.add(1); 10 nm.print(); 11 System.out.println("鏈表的刪除(刪除3)"); 12 nm.delNode(3); 13 nm.print(); 14 System.out.println("鏈表的查找(查找1)"); 15 System.out.println(nm.findNode(1)); 16 System.out.println("鏈表的查找(查找10)"); 17 System.out.println(nm.findNode(10)); 18 System.out.println("鏈表的更新(把1更新為10)"); 19 nm.updateNode(1, 10); 20 nm.print(); 21 System.out.println("鏈表的插入(在第1個位置插入20)"); 22 nm.insert(1, 20); 23 nm.print(); 24 System.out.println("鏈表的插入(在第0個位置插入30)"); 25 nm.insert(0, 30); 26 nm.print(); 27 } 28 }
將代碼編譯、運行,結果如下圖:
對於Java中的集合類中用到了不少的數據結構的知識,等自己狀態好的時候學習學習Java集合類的源碼。我會努力做一個初級程式員!