Java | 單鏈表

單鏈表介紹

/*
 * 鏈表
 * 1. 鏈表是以節點的方式來存儲的,是鏈式存儲
 * 2. 每個節點包含data域,next域:指向下一個節點
 * 3. 鏈表的各個節點不一定是連續存儲
 * 4. 鏈表分帶頭節點的鏈表和沒有頭節點的鏈表,根據實際的需求來確定
 * <p>
 * 單鏈表的應用舉例
 * 使用帶head頭的單向鏈表實現 -> RunningMan成員管理完成對成員的增刪改查操作:
 * 1. 第一種方法在添加成員時,直接添加到鏈表的尾部
 * 2. 第二種方法在添加成員時,根據年齡將成員插入到指定位置(加入時間相同根據年齡大小排序)
 * 3. 修改節點功能:通過遍歷先找到該節點,再進行修改
 * 4. 刪除節點
 */

MemberNode類

class MemberNode {
    private int id;
    private String name;
    private String info;    // 成員的信息
    private MemberNode next;

    public MemberNode(int id, String name, String info) {
        this.id = id;
        this.name = name;
        this.info = info;
        this.next = null;
    }

    public MemberNode(MemberNode node) {
        this.id = node.getId();
        this.name = node.getName();
        this.info = node.getInfo();
        this.next = null;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }

    public MemberNode getNext() {
        return next;
    }

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

    @Override
    public String toString() {
        return "MemberNode{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", info='" + info + '\'' +
                '}';
    }
}

SingleLinkedList類

public class SingleLinkedList {
    // 先初始化一個頭節點,頭節點不要動,不存放具體的數據
    private MemberNode head = new MemberNode(0, null, null);

    // 添加節點到單向鏈表
    // 1. 找到當前鏈表的最後節點
    // 2. 將最後這個節點的next指向新的節點
    public void add(MemberNode memberNode) {
        MemberNode h = head;
        while (h.getNext() != null) {
            h = h.getNext();
        }
        h.setNext(memberNode);
        System.out.println("添加成功");
        list();
    }

    // 第二種方式在添加英雄時,根據排名將英雄插入到指定位置
    // 如果已有這個id,則添加失敗,並給出提示
    public void addById(MemberNode memberNode) {
        MemberNode h = head;
        while (h.getNext() != null) {
            if (h.getNext().getId() < memberNode.getId()) {
                h = h.getNext();
                continue;
            } else if (h.getNext().getId() == memberNode.getId()) {
                System.out.println("添加失敗,已有該成員!");
                return;
            }
            break;
        }
        memberNode.setNext(h.getNext());
        h.setNext(memberNode);
        System.out.println("添加成功");
        list();
    }

    // 修改成員的信息,根據id來修改,即id不能改
    public void update(MemberNode memberNode) {
        MemberNode h = head;
        while (h.getNext() != null) {
            if (h.getNext().getId() != memberNode.getId()) {
                h = h.getNext();
                continue;
            } else if (h.getNext().getId() == memberNode.getId()) {
                h.getNext().setInfo(memberNode.getInfo());
                System.out.println("修改成功");
                list();
                return;
            }
        }
        System.out.println("修改失敗,未找到該成員!");
    }

    // 刪除節點
    public void del(int id) {
        MemberNode h = head;
        while (h.getNext() != null) {
            if (h.getNext().getId() != id) {
                h = h.getNext();
                continue;
            } else if (h.getNext().getId() == id) {
                h.setNext(h.getNext().getNext());
                System.out.println("刪除成功");
                list();
                return;
            }
        }
        System.out.println("刪除失敗,未找到該成員!");
    }

    // 顯示鏈表(遍歷)
    public void list() {
        MemberNode h = head;
        if (h.getNext() == null){
            System.out.println("當前鏈表爲空!");
            return;
        }
        while (h.getNext() != null) {
            h = h.getNext();
            System.out.println(h.toString());
        }
        System.out.println();
    }
}

單鏈表面試題

求單鏈表中有效節點的個數

public int size(){
    MemberNode h = head;
    int size = 0;
    if (h.getNext() == null){
        System.out.println("當前鏈表爲空!");
        return 0;
    }
    while (h.getNext() != null) {
        h = h.getNext();
        size ++;
    }
    return size;
}

查找單鏈表中的倒數第k個節點

public MemberNode lastK(int k){
    int size = this.size();
    int count = 0;
    MemberNode h = head;
    if (h.getNext() == null){
        throw new RuntimeException("當前鏈表爲空");
    }
    if (size - k + 1 <= 0){
        throw new RuntimeException("越界!");
    }
    while (h.getNext() != null) {
        h = h.getNext();
        count ++;
        if (count == size - k + 1){
            System.out.println(h.toString());
            return h;
        }
    }
    throw new RuntimeException("越界!");
}

單鏈表的反轉

/*
    思路:
    1. 先定義一個鏈表SingleLinkedList reverseList = new SingleLinkedList()
    2. 從頭到尾遍歷原來的鏈表,每遍歷一個節點,就將其取出,並放在新的鏈表reverseList的最前端
 */
public SingleLinkedList reverse(){
    SingleLinkedList reverseList = new SingleLinkedList();
    MemberNode h = head;
    while (h.getNext() != null){
        h = h.getNext();
        MemberNode temp = new MemberNode(h);
        temp.setNext(reverseList.getHead().getNext());
        reverseList.getHead().setNext(temp);
    }
    return reverseList;
}

從尾到頭打印單鏈表(Stack棧方式)

public void showStack(){
    Stack<MemberNode> stack = new Stack<>();
    MemberNode h = head;
    MemberNode node = null;
    while (h.getNext() != null){
        h = h.getNext();
        node = new MemberNode(h);
        stack.push(node);
    }
    while (!stack.isEmpty()){
        System.out.println(stack.pop());
    }
}

合併兩個有序的單鏈表,合併之後的鏈表依然有序

public SingleLinkedList merge(SingleLinkedList list){
    SingleLinkedList mergeList = new SingleLinkedList();
    MemberNode h1 = head;
    MemberNode h2 = list.getHead();
    MemberNode temp = null;
    while (h1.getNext() !=null && h2.getNext() != null){
        if (h1.getNext().getId() < h2.getNext().getId()){
            h1 = h1.getNext();
            temp = new MemberNode(h1);
        }else if (h1.getNext().getId() > h2.getNext().getId()){
            h2 = h2.getNext();
            temp = new MemberNode(h2);
        }else if (h1.getNext().getId() == h2.getNext().getId()){
            h1 = h1.getNext();
            h2 = h2.getNext();
            temp = new MemberNode(h2);
        }
        mergeList.add(temp);
    }
    if (h1.getNext() != null)
        mergeList.add(h1.getNext());
    if (h2.getNext() != null)
        mergeList.add(h2.getNext());
    return mergeList;
}

測試代碼1

/*
    先後年齡排名:
    1.池石鎮 2.劉在石 3.金鐘國 4.Gary 5.HAHA 6.宋智孝 7.李光洙 8.宋仲基 9.全昭旻 10.梁世燦 11.Lizzy
 */
@Test
public void test(){
    SingleLinkedList runningMan = new SingleLinkedList();
    runningMan.list();
    System.out.println("RunningMan開始啦!");
    runningMan.add(new MemberNode(1, "池石鎮","王鼻子"));
    runningMan.add(new MemberNode(2, "劉在石","劉姆斯·邦德"));
    runningMan.add(new MemberNode(3, "金鐘國","能力者"));
    runningMan.add(new MemberNode(4, "Gary","狗哥"));
    runningMan.add(new MemberNode(5, "HAHA","時間支配者"));
    runningMan.add(new MemberNode(7, "李光洙","長頸鹿"));
    runningMan.add(new MemberNode(8, "宋仲基","同齡朋友"));
    runningMan.list();
    System.out.println("智孝加入!");
    runningMan.addById(new MemberNode(6, "宋智孝","懵智孝"));
    runningMan.list();
    System.out.println("Lizzy加入!");
    runningMan.addById(new MemberNode(11, "Lizzy","RM的維他命"));
    runningMan.list();
    System.out.println("Lizzy下車");
    runningMan.del(11);
    runningMan.list();
    System.out.println("宋仲基下車");
    runningMan.del(8);
    runningMan.list();
    System.out.println("金鐘國信息修改");
    runningMan.update(new MemberNode(3, "金鐘國","能力者、斯巴達國斯"));
    runningMan.list();
    System.out.println("劉在石信息修改");
    runningMan.update(new MemberNode(2, "劉在石","劉姆斯·邦德、螞蚱"));
    runningMan.list();
    System.out.println("Gary下車");
    runningMan.del(4);
    runningMan.list();
    System.out.println("全昭旻、梁世燦加入");
    runningMan.addById(new MemberNode(10, "梁世燦","小不點"));
    runningMan.addById(new MemberNode(9, "全昭旻","女版李光洙"));
    runningMan.list();
    System.out.println("RunningMan要一直健健康康下去");

    // 錯誤操作測試
    runningMan.addById(new MemberNode(9, "全昭旻","女版李光洙"));
    runningMan.del(100);
    runningMan.update(new MemberNode(0, "全昭旻","女版李光洙"));
    System.out.println("\nRM成員數" + runningMan.size());
    runningMan.lastK(8);
    runningMan.lastK(1);
    //        runningMan.lastK(9); // 越界
    System.out.println("\n鏈表反轉");
    SingleLinkedList reverseList = runningMan.reverse();
    reverseList.list();
    System.out.println("從尾到頭打印單鏈表");
    runningMan.showStack();
}

輸出結果1

當前鏈表爲空!
RunningMan開始啦!
池石鎮添加成功
劉在石添加成功
金鐘國添加成功
Gary添加成功
HAHA添加成功
李光洙添加成功
宋仲基添加成功
MemberNode{id=1, name='池石鎮', info='王鼻子'}
MemberNode{id=2, name='劉在石', info='劉姆斯·邦德'}
MemberNode{id=3, name='金鐘國', info='能力者'}
MemberNode{id=4, name='Gary', info='狗哥'}
MemberNode{id=5, name='HAHA', info='時間支配者'}
MemberNode{id=7, name='李光洙', info='長頸鹿'}
MemberNode{id=8, name='宋仲基', info='同齡朋友'}

智孝加入!
宋智孝添加成功
MemberNode{id=1, name='池石鎮', info='王鼻子'}
MemberNode{id=2, name='劉在石', info='劉姆斯·邦德'}
MemberNode{id=3, name='金鐘國', info='能力者'}
MemberNode{id=4, name='Gary', info='狗哥'}
MemberNode{id=5, name='HAHA', info='時間支配者'}
MemberNode{id=6, name='宋智孝', info='懵智孝'}
MemberNode{id=7, name='李光洙', info='長頸鹿'}
MemberNode{id=8, name='宋仲基', info='同齡朋友'}

Lizzy加入!
Lizzy添加成功
MemberNode{id=1, name='池石鎮', info='王鼻子'}
MemberNode{id=2, name='劉在石', info='劉姆斯·邦德'}
MemberNode{id=3, name='金鐘國', info='能力者'}
MemberNode{id=4, name='Gary', info='狗哥'}
MemberNode{id=5, name='HAHA', info='時間支配者'}
MemberNode{id=6, name='宋智孝', info='懵智孝'}
MemberNode{id=7, name='李光洙', info='長頸鹿'}
MemberNode{id=8, name='宋仲基', info='同齡朋友'}
MemberNode{id=11, name='Lizzy', info='RM的維他命'}

Lizzy下車
刪除成功
MemberNode{id=1, name='池石鎮', info='王鼻子'}
MemberNode{id=2, name='劉在石', info='劉姆斯·邦德'}
MemberNode{id=3, name='金鐘國', info='能力者'}
MemberNode{id=4, name='Gary', info='狗哥'}
MemberNode{id=5, name='HAHA', info='時間支配者'}
MemberNode{id=6, name='宋智孝', info='懵智孝'}
MemberNode{id=7, name='李光洙', info='長頸鹿'}
MemberNode{id=8, name='宋仲基', info='同齡朋友'}

宋仲基下車
刪除成功
MemberNode{id=1, name='池石鎮', info='王鼻子'}
MemberNode{id=2, name='劉在石', info='劉姆斯·邦德'}
MemberNode{id=3, name='金鐘國', info='能力者'}
MemberNode{id=4, name='Gary', info='狗哥'}
MemberNode{id=5, name='HAHA', info='時間支配者'}
MemberNode{id=6, name='宋智孝', info='懵智孝'}
MemberNode{id=7, name='李光洙', info='長頸鹿'}

金鐘國信息修改
修改成功
MemberNode{id=1, name='池石鎮', info='王鼻子'}
MemberNode{id=2, name='劉在石', info='劉姆斯·邦德'}
MemberNode{id=3, name='金鐘國', info='能力者、斯巴達國斯'}
MemberNode{id=4, name='Gary', info='狗哥'}
MemberNode{id=5, name='HAHA', info='時間支配者'}
MemberNode{id=6, name='宋智孝', info='懵智孝'}
MemberNode{id=7, name='李光洙', info='長頸鹿'}

劉在石信息修改
修改成功
MemberNode{id=1, name='池石鎮', info='王鼻子'}
MemberNode{id=2, name='劉在石', info='劉姆斯·邦德、螞蚱'}
MemberNode{id=3, name='金鐘國', info='能力者、斯巴達國斯'}
MemberNode{id=4, name='Gary', info='狗哥'}
MemberNode{id=5, name='HAHA', info='時間支配者'}
MemberNode{id=6, name='宋智孝', info='懵智孝'}
MemberNode{id=7, name='李光洙', info='長頸鹿'}

Gary下車
刪除成功
MemberNode{id=1, name='池石鎮', info='王鼻子'}
MemberNode{id=2, name='劉在石', info='劉姆斯·邦德、螞蚱'}
MemberNode{id=3, name='金鐘國', info='能力者、斯巴達國斯'}
MemberNode{id=5, name='HAHA', info='時間支配者'}
MemberNode{id=6, name='宋智孝', info='懵智孝'}
MemberNode{id=7, name='李光洙', info='長頸鹿'}

全昭旻、梁世燦加入
梁世燦添加成功
全昭旻添加成功
MemberNode{id=1, name='池石鎮', info='王鼻子'}
MemberNode{id=2, name='劉在石', info='劉姆斯·邦德、螞蚱'}
MemberNode{id=3, name='金鐘國', info='能力者、斯巴達國斯'}
MemberNode{id=5, name='HAHA', info='時間支配者'}
MemberNode{id=6, name='宋智孝', info='懵智孝'}
MemberNode{id=7, name='李光洙', info='長頸鹿'}
MemberNode{id=9, name='全昭旻', info='女版李光洙'}
MemberNode{id=10, name='梁世燦', info='小不點'}

RunningMan要一直健健康康下去
添加失敗,已有該成員!
刪除失敗,未找到該成員!
修改失敗,未找到該成員!

RM成員數8
MemberNode{id=1, name='池石鎮', info='王鼻子'}
MemberNode{id=10, name='梁世燦', info='小不點'}

鏈表反轉
MemberNode{id=10, name='梁世燦', info='小不點'}
MemberNode{id=9, name='全昭旻', info='女版李光洙'}
MemberNode{id=7, name='李光洙', info='長頸鹿'}
MemberNode{id=6, name='宋智孝', info='懵智孝'}
MemberNode{id=5, name='HAHA', info='時間支配者'}
MemberNode{id=3, name='金鐘國', info='能力者、斯巴達國斯'}
MemberNode{id=2, name='劉在石', info='劉姆斯·邦德、螞蚱'}
MemberNode{id=1, name='池石鎮', info='王鼻子'}

從尾到頭打印單鏈表
MemberNode{id=10, name='梁世燦', info='小不點'}
MemberNode{id=9, name='全昭旻', info='女版李光洙'}
MemberNode{id=7, name='李光洙', info='長頸鹿'}
MemberNode{id=6, name='宋智孝', info='懵智孝'}
MemberNode{id=5, name='HAHA', info='時間支配者'}
MemberNode{id=3, name='金鐘國', info='能力者、斯巴達國斯'}
MemberNode{id=2, name='劉在石', info='劉姆斯·邦德、螞蚱'}
MemberNode{id=1, name='池石鎮', info='王鼻子'}

測試代碼2

@Test
public void mergeTest(){
    SingleLinkedList running = new SingleLinkedList();
    SingleLinkedList man = new SingleLinkedList();
    SingleLinkedList runingMan = new SingleLinkedList();
    System.out.println("合併兩個有序的單鏈表");
    running.add(new MemberNode(1, "池石鎮","王鼻子"));
    man.add(new MemberNode(2, "劉在石","劉姆斯·邦德"));
    man.add(new MemberNode(3, "金鐘國","能力者"));
    running.add(new MemberNode(3, "金鐘國","能力者"));    // 檢驗重複數據
    man.add(new MemberNode(5, "HAHA","時間支配者"));
    running.addById(new MemberNode(6, "宋智孝","懵智孝"));
    running.add(new MemberNode(7, "李光洙","長頸鹿"));
    man.addById(new MemberNode(10, "梁世燦","小不點"));
    running.addById(new MemberNode(9, "全昭旻","女版李光洙"));
    System.out.println("\nrunning");
    running.list();
    System.out.println("\nman");
    man.list();
    System.out.println("\nRuningMan");
    runingMan = running.merge(man);
    runingMan.list();
}

輸出結果2

合併兩個有序的單鏈表
池石鎮添加成功
劉在石添加成功
金鐘國添加成功
金鐘國添加成功
HAHA添加成功
宋智孝添加成功
李光洙添加成功
梁世燦添加成功
全昭旻添加成功

running
MemberNode{id=1, name='池石鎮', info='王鼻子'}
MemberNode{id=3, name='金鐘國', info='能力者'}
MemberNode{id=6, name='宋智孝', info='懵智孝'}
MemberNode{id=7, name='李光洙', info='長頸鹿'}
MemberNode{id=9, name='全昭旻', info='女版李光洙'}


man
MemberNode{id=2, name='劉在石', info='劉姆斯·邦德'}
MemberNode{id=3, name='金鐘國', info='能力者'}
MemberNode{id=5, name='HAHA', info='時間支配者'}
MemberNode{id=10, name='梁世燦', info='小不點'}


RuningMan
池石鎮添加成功
劉在石添加成功
金鐘國添加成功
HAHA添加成功
宋智孝添加成功
李光洙添加成功
全昭旻添加成功
梁世燦添加成功
MemberNode{id=1, name='池石鎮', info='王鼻子'}
MemberNode{id=2, name='劉在石', info='劉姆斯·邦德'}
MemberNode{id=3, name='金鐘國', info='能力者'}
MemberNode{id=5, name='HAHA', info='時間支配者'}
MemberNode{id=6, name='宋智孝', info='懵智孝'}
MemberNode{id=7, name='李光洙', info='長頸鹿'}
MemberNode{id=9, name='全昭旻', info='女版李光洙'}
MemberNode{id=10, name='梁世燦', info='小不點'}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章