數據結構之鏈表(LinkedList)(二)

數據結構之鏈表(LinkedList)(一)

雙鏈表

上一篇講述了單鏈表是經過next 指向下一個節點,那麼雙鏈表就是指不止能夠順序指向下一個節點,還能夠經過prior域逆序指向上一個節點html

示意圖:數據結構

那麼怎麼來實現雙鏈表的增刪改查操做呢。ide

分析:測試

1) 遍歷 方和 單鏈表同樣,只是能夠向前,也能夠向後查找spa

2) 添加 (默認添加到雙向鏈表的最後)3d

① 先找到雙向鏈表的最後這個節點指針

② temp.next = newStuNodecode

③ newStuNode.prior = temp;htm

3) 修改 思路和 原來的單向鏈表同樣.blog

4) 刪除

①由於是雙向鏈表,所以,咱們能夠實現自我刪除某個節點

② 直接找到要刪除的這個節點,好比temp

③ temp.prior.next = temp.next

④ temp.next.prior= temp.prior;

實現代碼:

添加&遍歷:

默認添加在鏈表最後一個。

 // 添加一個節點到雙向鏈表的最後.
    public void  add(StuNode2 stuNode2){

        // 由於head節點不能動,所以咱們須要一個輔助遍歷 temp
        StuNode2 temp = head;
        // 遍歷鏈表,找到最後
        while (true) {
            // 找到鏈表的最後
            if (temp.next == null) {//
                break;
            }
            // 若是沒有找到最後, 將將temp後移
            temp = temp.next;
        }
        // 當退出while循環時,temp就指向了鏈表的最後
        // 造成一個雙向鏈表
        temp.next = stuNode2;
        stuNode2.prior = temp;
    }
添加代碼
//遍歷雙向列表的方法   和單項列表一致
    //顯示鏈表[遍歷]
    public void list() {
        //判斷鏈表是否爲空
        if(head.next == null) {
            System.out.println("鏈表爲空");
            return;
        }
        //由於頭節點,不能動,所以咱們須要一個輔助變量來遍歷
        StuNode2 temp = head.next;
        while(true) {
            //判斷是否到鏈表最後
            if(temp == null) {
                break;
            }
            //輸出節點的信息
            System.out.println(temp);
            //將temp後移, 必定當心
            temp = temp.next;
        }
    }
遍歷代碼
public static void main(String[] args) {
        //進行測試
        //先建立節點
        StuNode2 stu1 = new StuNode2(1, "張三", "85");
        StuNode2 stu2 = new StuNode2(2, "李四", "87");
        StuNode2 stu3 = new StuNode2(3, "小明", "70");
        StuNode2 stu4 = new StuNode2(4, "小紅", "90");

        //建立要給鏈表
        DoubleLinkedList doubleLinkedList = new DoubleLinkedList();
        //加入
        doubleLinkedList.add(stu1);
        doubleLinkedList.add(stu2);
        doubleLinkedList.add(stu3);
        doubleLinkedList.add(stu4);
        System.out.println("原始雙鏈表數據  " );
        doubleLinkedList.list();;
    }
main
原始雙鏈表數據  
StuNode [stuNo=1, name=張三, mark=85]
StuNode [stuNo=2, name=李四, mark=87]
StuNode [stuNo=3, name=小明, mark=70]
StuNode [stuNo=4, name=小紅, mark=90]
輸出

 根據序號排序添加

上面添加是默認添加到最後一個節點,那麼要求根據序號默認排序添加呢,其實和單鏈表是同樣思路

public  void addByOrder(StuNode2 stuNode2){
        StuNode2 temp = head;
        boolean flag = false;
        while (true){
            if (temp.next == null){
                break;
            }
            if (temp.next.stuNo>stuNode2.stuNo){//位置找到
                break;
            }else if (temp.stuNo == stuNode2.stuNo){
                flag=true;
                break;
            }
            temp =temp.next;
        }
        if (flag){
            System.out.printf("準備插入的學生 %d 已經存在了, 不能加入\n", stuNode2.stuNo);
        }else{
            stuNode2.next=temp.next;
            temp.next=stuNode2;
            stuNode2.prior=temp;
            if(temp.next != null){
                temp.next.prior=stuNode2;
            }
        }
    }
代碼

修改:

// 修改一個節點的內容, 能夠看到雙向鏈表的節點內容修改和單向鏈表同樣
    // 只是 節點類型改爲 StuNode2
    public void update(StuNode2 newStuNode) {
        // 判斷是否空
        if (head.next == null) {
            System.out.println("鏈表爲空~");
            return;
        }
        // 找到須要修改的節點, 根據stuNo編號
        // 定義一個輔助變量
        StuNode2 temp = head.next;
        boolean flag = false; // 表示是否找到該節點
        while (true) {
            if (temp == null) {
                break; // 已經遍歷完鏈表
            }
            if (temp.stuNo == newStuNode.stuNo) {
                // 找到
                flag = true;
                break;
            }
            temp = temp.next;
        }
        // 根據flag 判斷是否找到要修改的節點
        if (flag) {
            temp.name = newStuNode.name;
            temp.mark = newStuNode.mark;
        } else { // 沒有找到
            System.out.printf("沒有找到 學號 %d 的節點,不能修改\n", newStuNode.stuNo);
        }
    }
修改代碼
public static void main(String[] args) {
        //進行測試
        //先建立節點
        StuNode2 stu1 = new StuNode2(1, "張三", "85");
        StuNode2 stu2 = new StuNode2(2, "李四", "87");
        StuNode2 stu3 = new StuNode2(3, "小明", "70");
        StuNode2 stu4 = new StuNode2(4, "小紅", "90");

        //建立要給鏈表
        DoubleLinkedList doubleLinkedList = new DoubleLinkedList();
        //加入
        doubleLinkedList.add(stu1);
        doubleLinkedList.add(stu2);
        doubleLinkedList.add(stu3);
        doubleLinkedList.add(stu4);
        System.out.println("原始雙鏈表數據  " );
        doubleLinkedList.list();;
        //修改3號的分數
        StuNode2 stu = new StuNode2(3,"小明","99");
        doubleLinkedList.update(stu);
        System.out.println("修改後的鏈表");
        doubleLinkedList.list();;


    }
main
原始雙鏈表數據  
StuNode [stuNo=1, name=張三, mark=85]
StuNode [stuNo=2, name=李四, mark=87]
StuNode [stuNo=3, name=小明, mark=70]
StuNode [stuNo=4, name=小紅, mark=90]
修改後的鏈表
StuNode [stuNo=1, name=張三, mark=85]
StuNode [stuNo=2, name=李四, mark=87]
StuNode [stuNo=3, name=小明, mark=99]
StuNode [stuNo=4, name=小紅, mark=90]
輸出

 刪除:

上篇單鏈表的思路是找到要刪除節點的前一個節點,而後待刪除節點的前一個節點直接指向待刪除節點的後一個節點,隱藏待刪除的節點,從而達到刪除目的。

那麼雙鏈表能夠直接找到待刪除節點temp,經過逆指向 temp.prior 找到待刪除節點的上一個節點,而後順指向temp.prior.next 指向待刪除節點的下一個節點temp.next

也就是 temp.prior.next = temp.next。同時要修改 待刪除節點的下一個節點的逆指向 指向待刪除節點的上一個節點,也就是temp.next.prior= temp.prior;

示意圖:

// 從雙向鏈表中刪除一個節點,
    // 說明
    // 1 對於雙向鏈表,咱們能夠直接找到要刪除的這個節點
    // 2 找到後,自我刪除便可
    public void del(int stuNo) {

        // 判斷當前鏈表是否爲空
        if (head.next == null) {// 空鏈表
            System.out.println("鏈表爲空,沒法刪除");
            return;
        }

        StuNode2 temp = head.next; // 輔助變量(指針)
        boolean flag = false; // 標誌是否找到待刪除節點的
        while (true) {
            if (temp == null) { // 已經到鏈表的最後
                break;
            }
            if (temp.stuNo == stuNo) {
                // 找到的待刪除節點的前一個節點temp
                flag = true;
                break;
            }
            temp = temp.next; // temp後移,遍歷
        }
        // 判斷flag
        if (flag) { // 找到
            // 能夠刪除
            // temp.next = temp.next.next;[單向鏈表]
            temp.prior.next = temp.next;
            // 若是是最後一個節點,就不須要執行下面這句話,不然出現空指針
            if (temp.next != null) {
                temp.next.prior = temp.prior;
            }
        } else {
            System.out.printf("要刪除的 %d 節點不存在\n", stuNo);
        }
    }
刪除代碼
public static void main(String[] args) {
        //進行測試
        //先建立節點
        StuNode2 stu1 = new StuNode2(1, "張三", "85");
        StuNode2 stu2 = new StuNode2(2, "李四", "87");
        StuNode2 stu3 = new StuNode2(3, "小明", "70");
        StuNode2 stu4 = new StuNode2(4, "小紅", "90");

        //建立要給鏈表
        DoubleLinkedList doubleLinkedList = new DoubleLinkedList();
        //加入
        doubleLinkedList.add(stu1);
        doubleLinkedList.add(stu2);
        doubleLinkedList.add(stu3);
        doubleLinkedList.add(stu4);
        System.out.println("原始雙鏈表數據  " );
        doubleLinkedList.list();
        //刪除3號數據
        doubleLinkedList.del(3);
        System.out.println("刪除後的鏈表  " );
        doubleLinkedList.list();

    }
main
原始雙鏈表數據  
StuNode [stuNo=1, name=張三, mark=85]
StuNode [stuNo=2, name=李四, mark=87]
StuNode [stuNo=3, name=小明, mark=70]
StuNode [stuNo=4, name=小紅, mark=90]
刪除後的鏈表  
StuNode [stuNo=1, name=張三, mark=85]
StuNode [stuNo=2, name=李四, mark=87]
StuNode [stuNo=4, name=小紅, mark=90]
輸出
相關文章
相關標籤/搜索