單鏈表——基本操作


1.獲取鏈表第i個數據的算法思路

  1. 聲明一個結點p指向鏈表第一個結點,初始化j從1開始
  2. 當j<i時,就遍歷鏈表,讓p的指針向后移動,不斷指向下一結點,j累加1
  3. 若到鏈表末尾p為空,則說明第i個元素不存在
  4. 否則查找成功,返回結點p的數據

2.單鏈表第i個數據插入結點的算法思路

  1. 聲明一結點p指向鏈表第一個結點,初始化j從1開始
  2. 當j<i時,就遍歷鏈表,讓p的指針向后移動,不斷指向下一結點,j累加1
  3. 若到鏈表末尾p為空,則說明第i個元素不存在
  4. 否則查找成功,在系統中生成一個空結點s
  5. 將數據元素e賦值給s->data
  6. 單鏈表的插入標准語句s->next=p->next;p->next=s
  7. 返回成功

3.單鏈表第i個數據刪除結點的算法思路

  1. 聲明一結點p指向鏈表第一個結點,初始化j從1開始
  2. 當j<i時,就遍歷鏈表,讓p的指針向后移動,不斷指向下一結點,j累加1
  3. 若到鏈表末尾p為空,則說明第i個元素不存在
  4. 否則查找成功,將欲刪除的結點p->next賦值給q
  5. 單鏈表的刪除標准語句p->next=q->next
  6. 將q結點中的數據賦值給e,作為返回
  7. 釋放q結點
  8. 返回成功

分析一下剛才我們講解的單鏈表插入和刪除算法,我們發現,它們其實都是由兩部分組成:第一部分就是遍歷查找第i個結點;第二部分就是插入和刪除結點。

4.單鏈表整表創建的算法思路

  1. 聲明一結點p和計數器變量i
  2. 初始化一空鏈表L
  3. 讓L的頭結點的指針指向NULL,即建立一個帶頭結點的單鏈表
  4. 循環:
  • 生成一新結點賦值給p
  • 隨機生成一數字賦值給p的數據域p->data
  • 將p插入到頭結點與前一新節點之間

     頭插法,尾插法

5.單鏈表的整表刪除

  1. 聲明一結點p和q
  2. 將第一個結點賦值給p
  3. 循環:
  • 將下一結點賦值給q
  • 釋放p
  • 將q賦值給p

 

Java代碼實現,以下代碼實現了單鏈表的各種操作  

/**
 * 結點類的描述
 * 
 * 單鏈表是由若干個結點連接而成,要實現單鏈表,首先需要設計結點類
 * 
 * 結點類由data和next組成
 * 
 * data是數據域,用來存放數據元素的值
 * next是指針域,用來存放后繼結點的地址
 * 
 * @author acer
 *
 */
public class Node
{
    private Object data; //存放結點值
    
    private Node next; //后繼結點的引用
    
    //無參數時的構造方法
    public Node()
    {
        this(null, null);
    }
    
    //帶一個參數的構造方法
    public Node(Object data)
    {
        this(data, null);
    }
    
    //帶兩個參數的構造方法
    public Node(Object data, Node next)
    {
        this.data = data;
        this.next = next;
    }

    public Object getData()
    {
        return data;
    }

    public void setData(Object data)
    {
        this.data = data;
    }

    public Node getNext()
    {
        return next;
    }

    public void setNext(Node next)
    {
        this.next = next;
    }
}

創建一個接口

public interface IList
{
    public void clear();
    public boolean isEmpty();
    public int length();
    public Object get(int i) throws Exception;
    public void insert(int i, Object x) throws Exception;
    public void remove(int i) throws Exception;
    public int indexOf(Object x);
    public void display();
}
/**
 * 單鏈表類的描述
 * 
 * 由於單鏈表只需一個頭指針就能唯一的標示它,所以單鏈表類的成員變量只需設置一個頭指針即可
 * 
 * @author acer
 * 
 */
public class LinkList implements IList
{
    //單鏈表的頭指針
    private Node head;

    public LinkList()
    {
        //初始化頭結點
        head = new Node();
    }

    public LinkList(int n, boolean Order) throws Exception
    {
        this();
        if (Order)
        {
            create1(n);
        } else
        {
            create2(n);
        }
    }

    // 用尾插法順序建立單鏈表,其中n為單鏈表的結點個數
    public void create1(int n) throws Exception
    {
        //構造用於輸入對象
        Scanner sc = new Scanner(System.in);
        
        for(int j = 0; j < n; j++)
        {
            //生成新結點,插入到表尾
            insert(length(), sc.next());
        }
    }

    // 用頭插法逆位序建立單鏈表,其中n為單鏈表的結點個數
    public void create2(int n) throws Exception
    {
        /*
         * 構造用於輸入對象
         * 
         * Scanner 使用分隔符模式將其輸入分解為標記,默認情況下該分隔符模式與空白匹配
         * 然后可以使用不同的 next 方法將得到的標記轉換為不同類型的值。
         */
        Scanner sc = new Scanner(System.in);

        for (int j = 0; j < n; j++)
        {
            //生成新結點,插入到表頭
            insert(0, sc.next());
        }
    }

    // 將一個已經存在的帶頭結點單鏈表置為空表
    @Override
    public void clear()
    {
        head.setData(null);
        
        head.setNext(null);
    }

    // 判斷帶頭結點的單鏈表是否為空
    @Override
    public boolean isEmpty()
    {
        return head.getNext() == null;
    }

    // 求帶頭結點的單鏈表的長度
    @Override
    public int length()
    {
        Node p = head.getNext();
        
        int lenth = 0;
        
        while(p != null)
        {
            p = p.getNext();
            
            ++lenth;
        }
        
        return lenth;
    }

    /*
     * 讀取帶頭結點的單鏈表中的第i個結點
     * 
     * 時間復雜度為O(n)
     */
    @Override
    public Object get(int i) throws Exception
    {
        // 初始化,p指向首結點,j為計數器
        Node p = head.getNext();

        int j = 0;

        // 從首結點開始向后查找,直到p指向第i個結點或p為空
        while (p != null && j < i)
        {
            // 指向后繼結點
            p = p.getNext();

            // 極速器加1
            ++j;
        }

        // i小於0或者大於表長減1
        if (j > i || p == null)
        {
            // 拋出異常
            throw new Exception("第" + i + "個元素不存在");
        }

        // 返回結點p的數據域的值
        return p.getData();
    }

    /*
     * 在帶頭結點的單鏈表中的第i個結點之前插入一個值為x的新結點
     * 
     * 時間復雜度為O(n)
     */
    @Override
    public void insert(int i, Object x) throws Exception
    {
        // 初始化,p指向首結點,j為計數器
        Node p = head;

        int j = -1;

        // 尋找第i個結點的前驅
        while (p != null && j < i - 1)
        {
            p = p.getNext();

            // 計數器加1
            ++j;
        }

        // i不合法
        if (j > i - 1 || p == null)
        {
            // 拋出異常
            throw new Exception("插入位置不合法");
        }

        // 生成新結點
        Node s = new Node(x);

        // 修改鏈,使新結點插入到單鏈表中
        s.setNext(p.getNext());

        p.setNext(s);
    }

    /*
     * 在不帶頭結點的單鏈表的第i個結點之前插入一個數據域值為x的新結點
     * 
     * 時間復雜度為O(n)
     */
    public void insert2(int i, Object x) throws Exception
    {
        // 初始化,p指向首結點,j為計數器
        Node p = head;

        int j = 0;

        // 用i = -1\0\1測試
        while (p != null && j < i - 1)
        {
            p = p.getNext();

            ++j;
        }

        if (j > i || p == null)
        {
            throw new Exception("插入位置不合法");
        }

        Node s = new Node(x);

        // 插入位置為表頭時
        if (i == 0)
        {
            s.setNext(head);

            head = s;
        }
        // 插入位置為表的中間或表尾時
        else
        {
            s.setNext(p.getNext());

            p.setNext(s);
        }
    }

    /*
     * 刪除單鏈表中的第i個結點
     * 
     * 時間復雜度為O(n)
     */
    @Override
    public void remove(int i) throws Exception
    {
        // 初始化,p指向首結點,j為計數器
        Node p = head;

        int j = -1;

        // 尋找第i個結點的前驅
        while (p.getNext() != null && j < i - 1)
        {
            p = p.getNext();

            ++j;
        }
        if (j > i - 1 || p.getNext() == null)
        {
            throw new Exception("刪除位置不合法");
        }

        // 修改鏈指針,使待刪除結點從單鏈表中脫離
        p.setNext(p.getNext().getNext());

    }

    /*
     * 在單鏈表中查找值為x的結點
     * 
     * 時間復雜度為O(n)
     */
    @Override
    public int indexOf(Object x)
    {
        // 初始化,p指向首結點,j為計數器
        Node p = head.getNext();

        int j = 0;

        // 下面從單鏈表中的首結點開始查找,直到p.getData()為x或到達單鏈表的表尾
        while (p != null && !p.getData().equals(x))
        {
            // 指向下一個結點
            p = p.getNext();

            // 計數器加1
            ++j;
        }

        // 若p指向單鏈表中的某個結點,返回值為x的結點在單鏈表中的位置
        if (p != null)
        {
            return j;
        } else
        {
            // 值為x的結點不在鏈表中
            return -1;
        }
    }

    // 輸出單鏈表中的所有結點
    @Override
    public void display()
    {
        //取出帶頭結點的單鏈表中的首結點
        Node p = head.getNext();
        
        while(p != null)
        {
            //輸出結點的值
            System.out.print(p.getData() + " ");
            
            //取下一個結點
            p = p.getNext();
        }
        
        //換行
        System.out.println();
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM