Java學習筆記之連結串列
阿新 • • 發佈:2018-12-25
連結串列是一種非常常見和重要的資料結構,在java裡也可以通過引用傳遞的方式進行實現。
1、基本概念
什麼是連結串列,通俗的可以理解為一輛貨車,火車頭代表連結串列表頭,後面的每一節車廂表示一個連結串列的結點,每一個結點除了儲存本節點的資料以外,還得帶上下一個結點的引用,也就是除了車尾以外的那些車廂,都必須連線後面的一節車廂。
2、連結串列的實現
要實現連結串列,我們必須定義一個連結串列類,在類中還得有一個屬性,可以儲存下一個節點的引用地址。
每一個節點除了要儲存當前節點的資料,還得帶上下一個結點的引用地址。
class Node{
private String data; // 節點的資料
private Node next; // 下一個節點的引用地址
public Node(String data){ // 建構函式設定節點內容
this.data = data;
}
public Node getNext() {
return this.next; // 獲取下一個節點
}
public void setNext(Node next) {
this.next = next; // 設定下一個節點
}
public String getData(){
return this.data;
}
}
public class LinkDemo {
public static void main(String[] args) {
Node root = new Node("火車頭");
Node node1 = new Node("一號車廂");
Node node2 = new Node("二號車廂");
Node node3 = new Node("三號車廂");
root.setNext(node1) ;
node1.setNext(node2);
node2.setNext(node3);
printNode(root); // 從頭開始輸出
}
public static void printNode(Node node) {
System.out.print(node.getData()+" -> ");
if(node.getNext()!=null){
printNode(node.getNext()); // 遞迴呼叫節點
}
}
}
上述例子中,所有的關係都是使用者手動設定,如果想讓它真正有意義,我們需要加入一個操作的封裝。
2、連結串列的改進
可以看到,上面的實現的連結串列需要人工手動去操作節點,一個個新增,一個個處理引用關係,非常繁瑣,因此我們應該將對節點的操作進行封裝。常見的操作有:增加資料、查詢資料、刪除資料。
注意:刪除資料其實只是改變節點引用地址而已
- 增加節點:在連結串列最後追加
- 查詢節點:遞迴查詢
- 刪除節點:修改引用關係
2.1 新增節點
class Link{ // 連結串列的完成類
class Node{ // 節點類
private String data;
private Node next;
public Node(String data){
this.data = data;
}
public void add(Node newNode){ // 將節點加入到合適的位置
if(this.next==null){ // 如果下一個節點為空,則把新節點設定在next位置
this.next = newNode;
}else{ // 如果下一節點非空,則繼續向後遞迴查詢
this.next.add(newNode);
}
}
public void print(){
System.out.print(this.data + " -> "); // 輸出節點內容
if(this.next!=null){ // 判斷是否為最後一個節點,若不是則繼續遞迴呼叫
this.next.print();
}
}
}
private Node root; // 設定根節點
public void addNode(String data){ // 增加節點
Node newNode = new Node(data); // 定義新的節點
if(this.root==null){ // 如果根節點為空,則設定 newNode 為根節點
this.root = newNode;
}else{ // 如果不是根節點,利用add方法把節點放在合適的位置
this.root.add(newNode);
}
}
public void printNode(){ // 輸出連結串列內容
if(this.root!=null){ // 如果連結串列根元素不為空
this.root.print(); // 呼叫Node類中的輸出操作
}
}
}
public class LinkDemo2 {
public static void main(String[] args) {
Link link = new Link();
link.addNode("A"); // 增加節點
link.addNode("B");
link.addNode("C");
link.addNode("D");
System.out.println("------------------");
link.printNode();
}
}
2.2 查詢節點
class Link{ // 連結串列的完成類
class Node{ // 節點類
private String data;
private Node next;
public Node(String data){
this.data = data;
}
public void add(Node newNode){ // 將節點加入到合適的位置
if(this.next==null){ // 如果下一個節點為空,則把新節點設定在next位置
this.next = newNode;
}else{ // 如果下一節點非空,則繼續向後遞迴查詢
this.next.add(newNode);
}
}
public void print(){
System.out.print(this.data + " -> "); // 輸出節點內容
if(this.next!=null){ // 判斷是否為最後一個節點,若不是則繼續遞迴呼叫
this.next.print();
}
}
public boolean search(String data){ // 內部搜尋方法
if(data.equals(this.data)){ // 判斷當前節點資料和查詢資料是否一致
return true;
}else{ // 繼續向後判斷
if(this.next!=null){ // 如果下一個節點存在,繼續判斷是否資料相等
return this.next.search(data);
}else{ // 否則返回失敗
return false;
}
}
}
}
private Node root; // 設定根節點
public void addNode(String data){ // 增加節點
Node newNode = new Node(data); // 定義新的節點
if(this.root==null){ // 如果根節點為空,則設定 newNode 為根節點
this.root = newNode;
}else{ // 如果不是根節點,利用add方法把節點放在合適的位置
this.root.add(newNode);
}
}
public void printNode(){ // 輸出連結串列內容
if(this.root!=null){ // 如果連結串列根元素不為空
this.root.print(); // 呼叫Node類中的輸出操作
}
}
public boolean contains(String name){ // 判斷元素是否存在
return this.root.search(name);
}
}
public class LinkDemo2 {
public static void main(String[] args) {
Link link = new Link();
link.addNode("A");
link.addNode("B");
link.addNode("C");
link.addNode("D");
System.out.println("------------------");
// link.printNode();
System.out.println(link.contains("X"));
}
}
2.3 刪除節點
class Link{ // 連結串列的完成類
class Node{ // 節點類
private String data;
private Node next;
public Node(String data){
this.data = data;
}
public void add(Node newNode){ // 將節點加入到合適的位置
if(this.next==null){ // 如果下一個節點為空,則把新節點設定在next位置
this.next = newNode;
}else{ // 如果下一節點非空,則繼續向後遞迴查詢
this.next.add(newNode);
}
}
public void print(){
System.out.print(this.data + " -> "); // 輸出節點內容
if(this.next!=null){ // 判斷是否為最後一個節點,若不是則繼續遞迴呼叫
this.next.print();
}
}
public boolean search(String data){ // 內部搜尋方法
if(data.equals(this.data)){ // 判斷當前節點資料和查詢資料是否一致
return true;
}else{ // 繼續向後判斷
if(this.next!=null){ // 如果下一個節點存在,繼續判斷是否資料相等
return this.next.search(data);
}else{ // 否則返回失敗
return false;
}
}
}
public void delete(Node previous, String data){
if(data.equals(this.data)){ // 找到匹配的節點
previous.next = this.next; // 空出當前節點
}else{
if(this.next!=null){ // 還是存在下一個節點
this.next.delete(this, data);
}
}
}
}
private Node root; // 設定根節點
public void addNode(String data){ // 增加節點
Node newNode = new Node(data); // 定義新的節點
if(this.root==null){ // 如果根節點為空,則設定 newNode 為根節點
this.root = newNode;
}else{ // 如果不是根節點,利用add方法把節點放在合適的位置
this.root.add(newNode);
}
}
public void printNode(){ // 輸出連結串列內容
if(this.root!=null){ // 如果連結串列根元素不為空
this.root.print(); // 呼叫Node類中的輸出操作
}
}
public boolean contains(String name){ // 判斷元素是否存在
return this.root.search(name);
}
public void deleteNode(String data){
if(this.contains(data)){ // 判斷節點是否存在
// 一定要判斷此元素是否和根節點相等
if(this.root.data.equals(data)){ // 內容是根節點
this.root = this.root.next; // 修改根節點,把第一個節點設定為根節點
}else{
this.root.next.delete(root, data); // 把下一個節點的前節點和資料傳入繼續判斷
}
}
}
}
public class LinkDemo2 {
public static void main(String[] args) {
Link link = new Link();
link.addNode("A");
link.addNode("B");
link.addNode("C");
link.addNode("D");
System.out.println("--------- 刪除之前 ---------");
link.printNode();
// System.out.println(link.contains("X"));
link.deleteNode("C");
link.deleteNode("B");
link.deleteNode("A");
System.out.println();
System.out.println("--------- 刪除之後 ---------");
link.printNode();
System.out.println();
System.out.println("查詢節點D: " + link.contains("D"));
}
}