單鏈表的實現-JAVA

來源:互聯網
上載者:User

標籤:col   set   dex   移動   模型   工具   虛擬碼   歸併排序   ddn   

該內容為轉載,原地址: 資料結構(一) 單鏈表的實現-JAVA

 

      資料結構還是很重要的,就算不是那種很牛逼的,但起碼得知道基礎的東西,這一系列就算是複習一下以前學過的資料結構和填補自己在這一塊的知識的空缺。加油。珍惜校園中自由學習的時光。按照鏈表、棧、隊列、排序、數組、樹這種順序來學習資料結構這門課程把。

                            -WH

一、單鏈表的概念

      鏈表是最基本的資料結構,其儲存的你原理圖如所示

          

      上面展示的是一個單鏈表的儲存原理圖,簡單易懂,head為前端節點,他不存放任何的資料,只是充當一個指向鏈表中真正存放資料的第一個節點的作用,而每個節點中都有一個next引用,指向下一個節點,就這樣一節一節往下面記錄,直到最後一個節點,其中的next指向null。

      鏈表有很多種,比如單鏈表,雙鏈表等等。我們就對單鏈表進行學習,其他的懂了原理其實是一樣的。

 

二、用java實現單鏈表

      語言只是一種工具,資料結構真正體會的是那種思想,這句話確實是這樣,不管用什麼寫,其思想是不改變的。以前使用的是C++,現在用的是java,一步步來實現。

      2.1、編寫一個Node類來充當結點的模型。我們知道,其中有兩個屬性,1存放資料的data,2存放下一結點的引用,

          

package com.wuhao.demo01;public class Node {    //為了方便,這兩個變數都使用public,而不用private就不需要編寫get、set方法了。    //存放資料的變數,簡單點,直接為int型    public int data;    //存放結點的變數,預設為null    public Node next;        //構造方法,在構造時就能夠給data賦值    public Node(int data){        this.data = data;    }}
View Code

 

      2.2、單鏈表的簡單操作(增加,刪除,擷取總長度,鏈表元素排序,鏈表遍曆)  

            

         2.2.1、增加結點操作,addNode(Node)

             

           想法:    一開始也會想如果什麼結點也沒有。是不是需要判斷插入的是第一個結點的問題,但寫完後發現沒有必要,是不是第一個結點操作都是一樣的,所以通過移動的指標遍曆整個鏈表,找到最後一個結點,往後添加即可。沒難度。      

    /**     * 增加操作     *         直接在鏈表的最後插入新增的結點即可     *         將原本最後一個結點的next指向新結點     */    public void addNode(Node node){        //鏈表中有結點,遍曆到最後一個結點        Node temp = head;    //一個移動的指標(把頭結點看做一個指向結點的指標)        while(temp.next != null){    //遍曆單鏈表,直到遍曆到最後一個則跳出迴圈。            temp = temp.next;        //往後移一個結點,指向下一個結點。        }        temp.next = node;    //temp為最後一個結點或者是頭結點,將其next指向新結點    }
View Code

         2.2.2、插入結點到鏈表的指定位置。 insertNodeByIndex(int index,Node node)

              

            注意:要知道插入操作需要的前提是什麼,你才好寫代碼,寫完之後,考慮如果在特殊位置上插入,是否也一樣。還有需要進行插入位置是否可行的判斷。

    /**     * insertNodeByIndex:在鏈表的指定位置插入結點。     *         插入操作需要知道1個結點即可,當前位置的前一個結點     * index:插入鏈表的位置,從1開始     * node:插入的結點     */    public void insertNodeByIndex(int index,Node node){        //首先需要判斷指定位置是否合法,        if(index<1||index>length()+1){            System.out.println("插入位置不合法。");            return;        }        int length = 1;            //記錄我們遍曆到第幾個結點了,也就是記錄位置。        Node temp = head;        //可移動的指標        while(head.next != null){//遍曆單鏈表            if(index == length++){        //判斷是否到達指定位置。                //注意,我們的temp代表的是當前位置的前一個結點。                //前一個結點        當前位置        後一個結點                //temp            temp.next     temp.next.next                //插入操作。                node.next = temp.next;                            temp.next = node;                                return;            }            temp = temp.next;        }    }
View Code

 

         2.2.3、刪除指定位置上的結點  delNodeByIndex(int index)

              

    /**     * 通過index刪除指定位置的結點,跟指定位置增加結點是一樣的,先找到準確位置。然後進行刪除操作。     *             刪除操作需要知道1個結點即可:和當前位置的前一個結點。     * @param index:鏈表中的位置,從1開始     *      */    public void delNodeByIndex(int index){        //判斷index是否合理        if(index<1 || index>length()){            System.out.println("給定的位置不合理");            return;        }        //步驟跟insertNodeByIndex是一樣的,只是操作不一樣。            int length=1;        Node temp = head;        while(temp.next != null){            if(index == length++){                //刪除操作。                temp.next = temp.next.next;                    return;            }            temp = temp.next;        }        }
View Code

 

          2.2.4、單鏈表進行選擇排序  selectSortNode()  

                前提要知道什麼是選擇排序,如果不會,請查看我講解排序的文章

              

              分析

              

    /**     * 對鏈表中的結點進行排序,按照從小到大的順序,使用選擇排序。     *         使用雙層遍曆。第一層遍曆,正常遍曆鏈表,第二層遍曆,遍曆第一層遍曆時所用的結點後面所有結點並與之比較     *         選擇排序比較簡單,明白其原理,就能夠寫的出來。     */    public void selectSortNode(){        //判斷鏈表長度大於2,不然只有一個元素,就不用排序了。        if(length()<2){            System.out.println("無需排序");            return;        }        //選擇排序        Node temp = head;            //第一層遍曆使用的移動指標,最處指向頭結點,第一個結點用temp.next表示        while(temp.next != null){    //第一層遍曆鏈表,從第一個結點開始遍曆            Node secondTemp = temp.next;        //第二層遍曆使用的移動指標,secondTemp指向第一個結點,我們需要用到是第二個結點開始,所以用secondNode.next            while(secondTemp.next != null){//第二層遍曆,從第二個結點開始遍曆                if( temp.next.data > secondTemp.next.data){    //第二層中的所有結點依次與第一次遍曆中選定的結點進行比較,                    int t = secondTemp.next.data;                    secondTemp.next.data =  temp.next.data;                    temp.next.data = t;                                }                secondTemp = secondTemp.next;            }            temp = temp.next;        }            }
View Code

 

          2.2.5、單鏈表進行插入排序  insertSortNode()

              前提:要知道什麼是插入排序。這個使用插入排序寫了我好久,懵逼一樣的狀態,並且我認為我自己寫效率不是很高。不管怎樣,是騾子是馬拿出來溜溜

              

              

    /**     * 對鏈表進行插入排序,按從大到小的順序,只要這裡會寫,那麼手寫用數組插入排序     *    也是一樣的。先要明白原理。什麼是插入排序,這樣才好寫代碼。     *    插入排序:分兩組,一組當成有序序列,一組當成無序,將無序組中的元素與有序組中的元素進行比較(如何比較,那麼就要知道插入排序的原理是什麼這裡不過多闡述)     *        這裡我想到的方法是,構建一個空的鏈表當成有序序列,而原先的舊鏈表為無序序列,按照原理,一步步進行編碼即可。     *         */    public void insertSortNode(){        //判斷鏈表長度大於2,不然只有一個元素,就不用排序了。        if(length()<2){            System.out.println("無需排序");            return;        }        //建立新鏈表        Node newHead = new Node(0);    //新鏈表的頭結點        Node newTemp = newHead;        //新鏈表的移動指標        Node temp = head;        //舊鏈表的移動指標        if(newTemp.next == null){        //將第一個結點直接放入新鏈表中。            Node node = new Node(temp.next.data);            newTemp.next = node;            temp = temp.next;    //舊鏈表中指標移到下一位(第二個結點處)。        }        while(temp.next != null){     //    遍曆現有鏈表            while(newTemp.next != null){                //先跟新鏈表中的第一個結點進行比較,如果符合條件則添加到新鏈表,注意是在第一個位置上增加結點                //如果不符合,則跟新鏈表中第二個結點進行比較,如果都不符合,跳出while,判斷是否是到了新鏈表的最後一個結點,如果是則直接在新鏈表後面添加即可                                if(newTemp.next.data < temp.next.data){                    Node node = new Node(temp.next.data);                    node.next = newTemp.next;                    newTemp.next = node;                    break;                }                newTemp = newTemp.next;            }            if(newTemp.next == null){//到達最末尾還沒符合,那麼說明該值是新鏈表中最小的數,直接添加即可到鏈表中即可                //直接在新鏈表後面添加                Node node = new Node(temp.next.data);                newTemp.next = node;            }            //舊鏈表指標指向下一位結點,繼續重複和新鏈表中的結點進行比較。            temp = temp.next;            //新鏈表中的移動指標需要複位,指向頭結點            newTemp = newHead;                    }        //開始使用新鏈表,舊鏈表等待記憶體回收機制將其收回。        head = newHead;    }
View Code

    

          2.2.6、當然還可以使用冒泡排序、歸併排序,等等等,都可以自己去嘗試,我就不寫了。如果不懂這些排序,那麼就看我寫排序的文章把。

          2.2.7、計算單鏈表的長度

              

    /**     * 計算單鏈表的長度,也就是有多少個結點     * @return    結點個數     */    public int length() {        int length=0;        Node temp = head;        while(temp.next != null){            length++;            temp = temp.next;        }        return length;    }
View Code

 

          2.2.8、遍曆單鏈表,列印data

                

 

    /**     * 遍曆單鏈表,列印所有data     */    public void print(){        Node temp = head.next;        while(temp != null){            System.out.print(temp.data+",");            temp = temp.next;        }        System.out.println();    }
View Code

  

三、總結

    基本的單鏈表操作就是上面這些了,自己完全手動寫一寫,會對單鏈表這種資料結構的理解有很大的協助。當然其中比較難的是在於對鏈表的排序上,說難也不難,只要懂的幾種排序的原理,就跟寫虛擬碼一樣,去實現即可。這裡還有一些操作,大家可以動手做一做,我會在下一篇文章中講解這些答案。

    3.1、如何從鏈表中重複資料刪除資料

    3.2、如何找出單鏈表中的倒數第k個元素

    3.3、如何?鏈表的反轉

    3.4、如何從尾到頭輸出單鏈表

    3.5、如何尋找單鏈表的中間結點

    3.6、如何檢測一個鏈表是否有環

    3.7、如何在不知道頭結點的情況下刪除指定結點

    3.8、如何判斷兩個鏈表是否相交

單鏈表的實現-JAVA

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.