java數據結構----鏈表學習

鏈表(單鏈表)

**定義:**單鏈表是一種鏈式存取的數據結構,用一組地址任意的存儲單元存放線性表中的數據元素。
鏈表中的數據是以結點來表示的,
每個結點的構成:元素(數據元素的映象) + 指針(指示後繼元素存儲位置),元素就是存儲數據的存儲單元,
指針就是連接每個結點的地址數據

本篇文章只是記錄一下學習鏈表和使用代碼實現,文章有寫的不好或不對的可以指出,初次寫稿,多多見諒
我們開始吧:
1.首先我們需要理解鏈表的數據結構的組成吧,如下圖
![在這裏插入圖片描述](https://img-blog.csdnimg.cn/2020051921011868.jpg#pic_center)

鏈表中的每一個節點都包含兩個部分: **data(數據域)和next(下一個節點指向)**

2. 鏈表的優缺點
優點:
1. 刪除和修改快(相對於數組數據結構來說)
2. 鏈表存儲是分散的空間地址(數組是連續性的存儲地址,需要-一開始指定存儲大小)
3. 擴展性好,
缺點:
1.查詢慢,因爲查詢需要從頭開始遍歷查詢(不能按索引位置查詢)

3.代碼實現如下

//定義一個鏈表類 基礎類
class HearNode {
    public Integer code;
    public String name;
    public String nickName;//以上是data數據域的屬性
    public HearNode next; //指針域

    public HearNode(Integer code, String name, String nickName) {
        this.code = code;
        this.name = name;
        this.nickName = nickName;
    }

    @Override
    public String toString() {
        return "HearNode{" +
                "code=" + code +
                ", name='" + name + '\'' +
                ", nickName='" + nickName + '\'' +
                '}';
    }
}

再定義一個實現鏈表的curd操作方法類

//封裝方法
class LianBiaoDemo {
    //初始化鏈表 定義頭結點
    HearNode head = new HearNode(null, "", "");

    /**
     * 1 首先需要找到鏈表最後一個節點  將該節點next指向插入的節點數據即可
     *
     * @param hearNode
     */
    public void addList(HearNode hearNode) {
        HearNode hea = head;
        //如果hea 的下一個節點爲null 則表示已經到了尾節點
        while (hea != null) {
            if (hea.next == null) {
                break;
            }
            hea = hea.next;
        }
        hea.next = hearNode;
    }

    /**
     * 獲取頭節點信心
     */
    public HearNode getFirst() {
        if (head.next == null) {
            System.out.println("該鏈表是空的 ~~~");
        }
        System.out.println(head.next);
        return  head.next;
    }

    /**
     * 獲取尾節點信息
     */
    public void getLast() {
        if (head.next == null) {
            System.out.println("該鏈表是空的 ~~~");
        }
        HearNode last = head;
        while (true) {
            if (last.next == null) {
                break;
            }
            last = last.next;
        }
        System.out.println(last);
    }

    /**
     * 獲取鏈表的有效節點數
     *
     * @return
     */
    public int getCount() {
        //首先做鏈表非空判斷
        if (head.next == null) {
            System.out.println("此鏈表爲空的 ~~~");
            return 0;
        }
        HearNode hea = head;
        //獲取鏈表的長度
        int i = 0;
        while (hea.next != null) {
            hea = hea.next;
            i++;
        }
        return i;
    }

    /**
     * 鏈表反轉
     */
    public void revserNodeList() {
        //先判斷節點個數是否爲等於1或者爲空
        if (head.next == null || head.next.next == null) {
            return;
        }
        //定義一個輔助變量指針 來遍歷原始的鏈表
        HearNode hea = head.next;
        //定義一個新的鏈表 只想當前節點【hea】的下一個節點
        HearNode next = null;
        //新的鏈表的頭節點信息
        HearNode newHead = new HearNode(null, "", "");
        //遍歷原來的鏈表,每遍歷一個節點,就將其取出,並放在新的鏈表的newHead 的最前端
        while (hea != null) {
            //記錄鏈表指針 記錄信息
            next = hea.next;
            //新鏈表的頭節點指向取出的數據信息
            hea.next = newHead.next;
            //獲取到最新的節點信息放到變量鏈表的頭節點
            newHead.next = hea;
            //循環遍歷
            hea = next;
        }
        // 將鏈表的頭節點指向變量節點的頭節點   head.next -> newHead.next
        head.next = newHead.next;
    }


    /**
     * 獲取鏈表中的第N個節點信息
     * 1. 首先需要獲取到鏈表的總的長度  需要先遍歷一邊
     * 2.定義一個變量接收要獲取的第幾個節點信息  index
     * 3.得到長度之後  從鏈表的第一個開始遍歷(總長度 - index)個 就可以得到
     * 4.如果找到就返回  沒有找到就返回空
     *
     * @return
     */
    public HearNode getIndex(int index) {
        //首先做鏈表非空判斷
        if (head.next == null) {
            System.out.println("此鏈表爲空的 ~~~");
            return null;
        }
        //獲取鏈表的長度
        int i = getCount();
        //然後判斷  鏈表長度與獲取指定index作比較 如果爲空或者index爲負數 則直接返回
        if (i < index || index <= 0) {
            System.out.println("該index超出鏈表的長度");
            return null;
        }
        HearNode hea = head.next;
        for (int j = 0; j < i - index; j++) {
            hea = hea.next;
        }
        return hea;
    }

    /**
     * 從尾打印鏈表數據
     * @param
     */
    public void  StackInfo(){
         //判斷鏈表是否爲空
        if (head.next ==null){
            return;
        }
        //獲取頭節點信息
        HearNode hea=head;
        Stack stack=new Stack();
        while (hea.next !=null){
            hea=hea.next;
            //進棧
             stack.push(hea);
        }
        while (!stack.empty()){
            // 出棧
            System.out.println("打印出來"+stack.pop());
        }
    }


    /**
     * 鏈表插入時按照大小排序
     * 1 我們採用頭結點的形式進行添加數據  所以需要定義一個頭結點信息  但是這個頭結點不做修改
     * 2. 定義一個輔助變量 flag 來判斷 循環接節點與插入的節點大小比對 如果當前節點的下一個節點比插入節點大  則將插入的節點放置到當前節點下個節點前即可
     *
     * @param hearNode
     */
    public void sortList(HearNode hearNode) {
        //定義一個頭結點
        HearNode hea = head;
        boolean flag = false;
        //hea不爲空則循環繼續
        while (hea != null) {
            //如果hea的下一個節點爲null 則表示到達最後一個節點
            if (hea.next == null) {
                break;
            }
            //這裏也可以做一個判斷  如果節點相同則不讓它添加
            //判斷 如果當前節點code 大於當前code 則將當前的數據放在當前節點之前
            //我們刪除一個節點 需要找到刪除節點的前一個節點
            if (hea.next.code > hearNode.code) {
                flag = true;
                break;
            }
            hea = hea.next;
        }
        //如果flag爲ture 則將當前插入的數據放到當前節點之後
        if (flag) {
            hearNode.next = hea.next;
            hea.next = hearNode;
        } else {
            hea.next = hearNode;
        }
    }

    /**
     * 刪除節點信息
     *
     * @param code
     */
    public void delteNode(int code) {
        //判斷當前鏈表是否爲空
        if (head.next == null) {
            System.out.println("當前鏈表爲空~~");
        }
        //定義一個變量
        HearNode hea = head;
        //定義一個標誌位 記錄查詢到刪除的code
        boolean flag = false;
        while (hea != null) {
            if (hea.next == null) {
                break;
            }
            //如果當前節點的code等於刪除的code 則表示找到了記錄信息
            if (hea.next.code == code) {
                flag = true;
                break;
            }
            hea = hea.next;//後移遍歷
        }
        //判斷標誌位是否爲ture
        if (flag) {
            //表示找到了刪除的數據信息
            hea.next = hea.next.next;
        } else {
            System.out.println("未找到刪除的節點信息");
        }
    }

    /**
     * 查詢連表數據信息
     */
    public void selectList() {
        if (head.next == null) {
            System.out.println("當前鏈表爲空~~");
            return;
        }
        HearNode hea = head.next;
        while (hea != null) {
            System.out.println(hea);
            hea = hea.next;
        }
    }

    /**
     * 修改節點信息
     * 1 首先需要循環遍歷 去匹配找到需要修改的節點信息
     *
     * @param updateCode
     */
    public void updateCode(int code, HearNode updateCode) {
        //判斷頭結點的下一個是否爲空,如果爲空則直接返回
        if (head.next == null) {
            return;
        }
        HearNode hea = head;
        //定義一個輔助變量 記錄是否找到修改信息的數據
        boolean flag = false;
        while (hea != null) {
            if (hea.next == null) {
                break;
            }
            //判斷當前節點的下一個數據的code是否修改的數據信息
            if (hea.next.code == code) {
                flag = true;
                break;
            }
            hea = hea.next;//循環遍歷
        }
        //如果爲ture則表示找到了
        if (flag) {
            hea.next.name = updateCode.name;
            hea.next.nickName = updateCode.nickName;
        } else {
            System.out.println("未找到需要修改的信息數據");
        }
    }


最後我們再對方法進行測試,如下:

public class LianBiao {
    public static void main(String[] args) {
        LianBiaoDemo lianBiaoDemo = new LianBiaoDemo();
		//進行數據添加操作
        HearNode node = new HearNode(9, "wang", "~~~");
        HearNode node01 = new HearNode(15, "li", "~~~");
        HearNode node02 = new HearNode(3, "tang", "~~~");
        HearNode node04 = new HearNode(6, "tang01", "~~~");
        HearNode node05 = new HearNode(6, "tang02", "~~~");

        lianBiaoDemo.sortList(node01);
        lianBiaoDemo.sortList(node);
        lianBiaoDemo.sortList(node02);
        lianBiaoDemo.sortList(node05);
        lianBiaoDemo.sortList(node04);

		//查詢方法
        lianBiaoDemo.selectList();
        //刪除
        System.out.println("刪除錢");
        lianBiaoDemo.delteNode(9);
        lianBiaoDemo.delteNode(15);
        lianBiaoDemo.selectList();
		//修改
        System.out.println("修改前的數據信息~~~~");
        HearNode newHearNode = new HearNode(3, "修改", "修改成功");
        lianBiaoDemo.updateCode(3, newHearNode);
        lianBiaoDemo.selectList();

        //1.獲取頭節點信息
        System.out.println("頭節點信息爲====》");
        lianBiaoDemo.getFirst();
        //2.獲取尾節點信息
        System.out.println("尾節點信息======》");
        lianBiaoDemo.getLast();
        //3.求單鏈表的有效節點數
        System.out.println("鏈表的有效長度:" + lianBiaoDemo.getCount());
        //4.獲取鏈表的倒數第n個節點信息
        System.out.println("獲取指定indexe鏈表的數據===》" + lianBiaoDemo.getIndex(5));
        //5.單鏈表的反轉  例如  123 ==》 321   123456====》654321 類似與這種反轉
        /**
         * 反轉的思路如下
         * 1.方法有很多 可以利用鏈表 +隊列 來實現反轉操作      
         * 這個方法還是用鏈表來實現   不過需要藉助一個鏈表來進行
         * 2. 定義一個新的鏈表
         */
        System.out.println("反轉鏈表~~");
        lianBiaoDemo.revserNodeList();
        lianBiaoDemo.selectList();
        //6從尾到頭打印單鏈表 (要求方式: 1. 反向遍歷  2. stack棧)
        /**
         * 可以利用棧的先進後出進行實現
         */
        System.out.println("反轉");
        lianBiaoDemo.StackInfo();
    }
}

以上就是鏈表學習的代碼實現,不理解的可以手動敲一敲,現在學習視頻很多,看懂了但是不代表就會寫出來,手擼一下會起到記憶加倍的效果。

當然方法中有很多地方可以提取出來,比如鏈表的長度,我們可以利用一個全局輔助變量來記錄,就不需要單獨寫一個方法來循環一遍了。。。。

以上就是分享的內容,不好之處歡迎提出,謝謝!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章