數據結構(java版)學習筆記(三)——線性表之單鏈表

單鏈表的優勢:

  1. 長度不固定,能夠任意增刪。java

單鏈表的缺點:

  1. 存儲密度小,由於每一個數據元素,都須要額外存儲一個指向下一元素的指針(雙鏈表則須要兩個指針)。node

  2. 要訪問特定元素,只能從鏈表頭開始,遍歷到該元素,時間複雜度爲 $O(n)$。在特定的數據元素以後插入或刪除元素,不涉及到其餘元素的移動,所以時間複雜度爲 $O(1)$。雙鏈表還容許在特定的數據元素以前插入或刪除元素。算法

  3. 存儲空間不連續,數據元素之間使用指針相連,每一個數據元素只能訪問周圍的一個元素(根據單鏈表仍是雙鏈表有所不一樣)。

單鏈表基本運算:

 

1.插入算法(核心)

插入算法是單鏈表的核心算法,掌握了這個,後面的頭插法,尾插法都是so easy編程

下圖就是顯示瞭如何將p結點插入到q的後面ide

2.刪除算法

刪除算法其實很簡單spa

下圖是刪除某個結點的後繼的圖示指針

 

3.創建單鏈表的兩種方法

頭插法和尾插法code

使用頭插法建立出的單鏈表是逆序的, 使用尾插法建立出的單鏈表則是順序的,通常都是採用此尾插法來創建單鏈表
blog

頭插法簡單來講,就是每次插入的結點都是在頭結點的後繼rem

尾插法則是每次插入的結點都是在鏈表的末尾結點的後繼

4.查找算法

查找算法的關鍵在於結束條件

下列代碼中的t!=null則是結束的條件

 

     Lnode t = h.next;
        while(t!=null){
            if(t.data==x){
                System.out.println("找到");
                return t;
            }
            t = t.next;
        }
        return null;

 

 

 

 

單鏈表的實現:

import java.util.Scanner;


public class LinkedList  implements ListIntf{
    Lnode h =null;
    public static String toucha = "頭插法";
    public static String weicha = "尾插法";
    
    public LinkedList(String s){
        //若是參數是頭插法則使用頭插法建立單鏈表,不是則使用尾插法
        if(s.equals(toucha)){
            h=new Lnode();
            h.data = 'f';
            h.next = null;
            Lnode p;
            Scanner scanner = new Scanner(System.in);
            String str = scanner.nextLine();
            for(int i=0;i<str.length();i++){
                
                p = new Lnode();
                p.data = str.charAt(i);
                
                p.next = h.next;
                h.next = p;
            }
            scanner.close();
        }else{
            h=new Lnode();
            h.data = 'f';
            h.next = null;
            
            Lnode p,t;
            t=h; //t用來代替頭結點,同時,也就是
            Scanner scanner = new Scanner(System.in);
            String str = scanner.nextLine();
            for(int i=0;i<str.length();i++){
                
                p = new Lnode();
                p.data = str.charAt(i); //接收String中的char
                
                p.next = t.next;//此條語句與p.next =null 等同
                t.next = p;
                t = p; // t結點一直指向鏈表的末尾
                
                
            }
            scanner.close();
        }
    }
    public void display(){
        Lnode p = h.next;
        while(p!=null){
            System.out.println(p.data);
            p = p.next;
        }
        
    }
    /**
     * 設置頭結點
     * @param _h
     */
    public void setH(Lnode _h){
        h=_h;
    }
    /**
     * 
     * @param p 結點
     * @param x 某個結點的值爲x
     * 將值爲x的結點插入到p結點的後面
     */
    public void insertElementAfter(Lnode p,char x){
        Lnode t = new Lnode(x);
        t.next = p.next; //這裏容易忘記
        p.next=t;                            
    }
    /**
     * 
     * @param x 
     * @return 查找到值爲x的結點
     */
    public Lnode search(char x){
        Lnode t = h.next;
        while(t!=null){
            if(t.data==x){
                System.out.println("找到");
                return t;
            }
            t = t.next;
        }
        return null;
    }
    @Override
    public int size() {
        int i =0;
        Lnode t = h.next;
        while(t!=null){
            i++;
            t = t.next; 
        }
        return i;
    }

    @Override
    public void clear() {
        h.next = null;
        
    }

    @Override
    public boolean isEmpty() {
        if(h.next==null){
            return false;
        }else{
            return true;
        }
    }
    /**
     * 
     * @param i 須要找到的第i個結點
     * @return 第i個結點
     */
    public Lnode getLnode(int i){
        Lnode t = h; //從頭結點算起,j就是從0開始
        int j =0;
        while(j<i){
            t = t.next;
            j++;
        }
        if(t==null){
            return null;
        }else{
            return t;    
        }
    }
    
    @Override
    public String get(int i) {
        //取得第i個結點的值
        Lnode t = h; //從頭結點算起,j就是從0開始
        int j =0;
        while(j<i){
            t = t.next;
            j++;
        }
        //或者從第一個結點開始
        /*Lnode t = h.next; 
        int j =1;
        while(j<i){
            t = t.next;
            j++;
        }*/
        //這裏須要加一個溢出處理
        if(t==null){
            return null;
        }else{
            return String.valueOf(t.data);    
        }
        
    }

    @Override
    public int indexOf(String s) {
        //單鏈表不須要複寫此方法
        return 0;
    }

    @Override
    public String getPre(String s) {
        //單鏈表不須要複寫此方法
        return null;
    }

    @Override
    public String getNext(String s) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void insertElementAt(String s, int i) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public String remove(int i) {
        //先找到第i個結點,以後再將其移出,斌返回其的數值
        Lnode t = getLnode(i);
        Lnode q = getLnode(i-1); //q爲t的前趨
        q.next = t.next;
    
        return String.valueOf(t.data);
    }

    @Override
    public String remove(String s) {
        // TODO Auto-generated method stub
        return null;
    }
    

}

 補充一下:

在Java實現字符窗口的輸入時,不少人更喜歡選擇使用掃描器Scanner,它操做起來比較簡單。在編程的過程當中,我發現用Scanner實現字符串的輸入有兩種方法,一種是next(),另外一種是nextLine(),這兩種有如下區別:

    next()必定要讀取到有效字符後才能夠結束輸入,對輸入有效字符以前遇到的空格鍵、Tab鍵或Enter鍵等結束符,next()方法會自動將其去掉,只有在輸入有效字符以後,next()方法纔將其後輸入的空格鍵、Tab鍵或Enter鍵等視爲分隔符或結束符。

     簡單地說,next()查找並返回來自此掃描器的下一個完整標記。完整標記的先後是與分隔模式匹配的輸入信息,因此next方法不能獲得帶空格的字符串。

    nextLine()方法的結束符只是Enter鍵,即nextLine()方法返回的是Enter鍵以前的全部字符,它是能夠獲得帶空格的字符串的。

相關文章
相關標籤/搜索