【数据结构】链表

简介: 【数据结构】链表

一、单链表

1、单链表概述

  1. 链表是以节点的方式来存储,是链式存储
  2. 每个节点包含data域, next 域:指向下一个节点.
  3. 链表的各个节点不一定是连续存储
  4. 链表分带头节点的链表和没有头节点的链表,根据实际的需求来确

2、面试题

1)有效节点个数

/**
 * 有效节点个数(遍历+计数)
 */
public int usedNode() {
   
    int ans = 0;
    heroNode temp = head;
    while (temp.next != null) {
   
        ans++;
        temp = temp.next;
    }
    return ans;
}

2)倒数第K个节点数据

/**
 * 反向输出第k个节点
 */
public void oppoShow(int k) {
   
    int all = usedNode();
    heroNode temp = head.next;
    if (all < k) {
   
        System.out.printf("没有第%d个节点\n", k);
        return;
    }
    int i = 1;
    while (temp != null) {
   
        if (i == (all - k + 1)) {
   
            System.out.println(temp.toString());
            break;
        }
        temp = temp.next;
        i++;
    }
}

3)反向遍历——迭代

/**
 * 反向遍历
 */
public void oppoShow() {
   
    if (head.next == null) {
   
        System.out.println("链表为空");
        return;
    }
    int all = usedNode();
    for (int i = all; i >= 0; i--) {
   
        int j = 1;
        heroNode temp = head.next;
        while (temp != null) {
   
            if (j == i) {
   
                System.out.println(temp.toString());
                break;
            }
            j++;
            temp = temp.next;
        }
    }
}

4)反向遍历——栈

class nodeStact {
   
    int maxSize;
    heroNode[] hn;
    int top;

    /**
     * 栈的构造器
     * 
     * @param maxSize 栈的大小
     */
    nodeStact(int maxSize) {
   
        this.maxSize = maxSize;
        hn = new heroNode[maxSize];
        top = -1;
    }

    /**
     * 判空
     */
    public boolean isEmpty() {
   
        return top == -1;
    }

    /**
     * 判满
     */
    public boolean isFull() {
   
        return top == maxSize - 1;
    }

    /**
     * 弹出
     */
    public heroNode pop() {
   
        if (isEmpty()) {
   
            System.out.println("栈空");
            return null;
        }
        return hn[top--];
    }

    /**
     * 压栈
     */
    public void push(heroNode _hn) {
   
        if (isFull()) {
   
            System.out.println("栈满");
        } else {
   
            hn[++top] = _hn;
        }
    }
}
/**
 * 反向遍历——通过栈实现
 */
public void showByStack() {
   
    if(head.next == null) {
   
        System.out.println("链表为空");
        return;
    }
    nodeStact ns = new nodeStact(usedNode());
    heroNode temp = head.next;
    while(temp != null) {
   
        ns.push(temp);
        temp = temp.next;
    }
    while(!ns.isEmpty()) {
   
        System.out.println(ns.pop().toString());
    }
}

5)合并单链表

/**
 * 与demo合并
 */
public void mesh() {
   
    singleLinkedList demo = new singleLinkedList();
    demo.add(new heroNode(-1, "小明", "王哥"));
    demo.add(new heroNode(0, "芭芭拉", "芭芭拉冲鸭"));
    heroNode temp = demo.head.next;
    while(temp != null) {
   
        addByNo(new heroNode(temp.getNo(), temp.getName(), temp.getNickName()));
        temp = temp.next;
    }

}

3、代码实现

package work.rexhao.linkedlist;

import java.util.Scanner;

public class singleLinkedListDemo {
   

    public static void main(String[] args) {
   
        singleLinkedList sll = new singleLinkedList();
        boolean loop = true;
        while (loop) {
   
            System.out.println("--------");
            System.out.println("1.在尾部添加");
            System.out.println("2.按编号添加");
            System.out.println("3.遍历单链表");
            System.out.println("4.修改节点");
            System.out.println("5.删除节点");
            System.out.println("6.有效节点个数");
            System.out.println("7.反向输出");
            System.out.println("8.反向遍历");
            System.out.println("0.退出");
            System.out.println("--------");
            Scanner sc = new Scanner(System.in);
            int key = sc.nextInt();
            if (key == 1) {
   
                System.out.println("请输入英雄编号:");
                int no = sc.nextInt();
                System.out.println("请输入英雄姓名:");
                Scanner sc1 = new Scanner(System.in);
                String name = sc1.nextLine();
                System.out.println("请输入英雄昵称:");
                Scanner sc2 = new Scanner(System.in);
                String nickName = sc2.nextLine();
                sll.add(new heroNode(no, name, nickName));
                System.out.println("添加成功!");
            } else if (key == 2) {
   
                System.out.println("请输入英雄编号:");
                int no = sc.nextInt();
                System.out.println("请输入英雄姓名:");
                Scanner sc1 = new Scanner(System.in);
                String name = sc1.nextLine();
                System.out.println("请输入英雄昵称:");
                Scanner sc2 = new Scanner(System.in);
                String nickName = sc2.nextLine();
                sll.addByNo(new heroNode(no, name, nickName));
                System.out.println("添加成功!");
            } else if (key == 3) {
   
                try {
   
                    sll.show();
                } catch (Exception e) {
   
                    System.out.println(e.getMessage());
                }
            } else if (key == 4) {
   
                System.out.println("请输入英雄编号:");
                int no = sc.nextInt();
                System.out.println("请输入英雄新的姓名:");
                Scanner sc1 = new Scanner(System.in);
                String name = sc1.nextLine();
                System.out.println("请输入英雄新的昵称:");
                Scanner sc2 = new Scanner(System.in);
                String nickName = sc2.nextLine();
                sll.change(no, name, nickName);
            } else if (key == 5) {
   
                System.out.println("请输入英雄编号:");
                int no = sc.nextInt();
                sll.delete(no);
            } else if (key == 6) {
   
                System.out.println("有效节点个数:" + sll.usedNode());
            } else if (key == 7) {
   
                int k = sc.nextInt();
                sll.oppoShow(k);
            } else if (key == 8) {
   
                System.out.println("通过反向遍历实现:");
                sll.oppoShow();
                System.out.println("通过栈实现:");
                sll.showByStack();
            } else if (key == 9) {
   
                System.out.println("与demo链表合并");
                sll.mesh();
            } else if (key == 0) {
   
                loop = false;
            } else {
   
                System.out.println("输入有误!");
            }
        }
    }
}

/**
 * 管理英雄
 */
class singleLinkedList {
   
    /**
     * 定义一个头结点
     */
    private heroNode head = new heroNode(0, "", "");

    /**
     * 添加节点的方法(尾插法) 将最后的next域指向新的node
     */
    public void add(heroNode hn) {
   
        // 需要一个辅助变量
        heroNode temp = head;
        // 遍历单链表
        while (temp.next != null) {
   
            temp = temp.next;
        }
        // 退出循环时,temp指向最后
        temp.next = hn;
    }

    /**
     * 按照编号大小添加
     * 
     * @param hn
     */
    public void addByNo(heroNode hn) {
   
        /**
         * 空链表:直接放后面
         */
        if (head.next == null) {
   
            head.next = hn;
            return;
        }
        heroNode temp = head.next;
        /**
         * 如果只有一个节点,且大于hn
         */
        if (hn.getNo() < temp.getNo()) {
   
            head.next = hn;
            hn.next = temp;
            return;
        }
        while (true) {
   
            /**
             * 如果no相等:报错
             */

            if (hn.getNo() == temp.getNo()) {
   
                throw new RuntimeException("编号重复!");
            }
            if (temp.next != null) {
   
                if (hn.getNo() == temp.next.getNo()) {
   
                    throw new RuntimeException("编号重复!");
                }
            }

            /**
             * 找到:大于前一个节点且(小于后一个节点或者后一个节点为null)的节点
             */
            if (hn.getNo() > temp.getNo() && (temp.next == null || hn.getNo() < temp.next.getNo())) {
   
                hn.next = temp.next;
                temp.next = hn;
                break;
            }
            if (temp.next != null) {
   
                temp = temp.next;
            } else {
   
                break;
            }
        }
    }

    /**
     * 遍历
     */
    public void show() {
   
        // 判空
        if (head.next == null) {
   
            throw new RuntimeException("链表为空");
        }
        // 遍历
        heroNode temp = head.next;
        while (temp != null) {
   
            System.out.println(temp.toString());
            temp = temp.next;
        }
    }

    /**
     * 修改节点
     */
    public void change(int no, String name, String nickName) {
   
        // 判空
        if (head.next == null) {
   
            System.out.println("链表为空");
            return;
        }
        // 遍历:找no节点
        heroNode temp = head.next;
        while (temp != null) {
   
            if (temp.getNo() == no) {
   
                temp.setName(name);
                temp.setNickName(nickName);
                System.out.println("修改成功!");
                return;
            }
            temp = temp.next;
        }
        System.out.printf("未找到编号为%d的节点\n", no);
        return;
    }

    /**
     * 删除节点
     */
    public void delete(int no) {
   
        // 判空
        if (head.next == null) {
   
            System.out.println("链表为空");
            return;
        }
        // 遍历找节点
        heroNode temp = head;
        while (temp.next != null) {
   
            if (temp.next.getNo() == no) {
   
                temp.next = temp.next.next;
                System.out.println("删除成功");
                return;
            }
            temp = temp.next;
        }
        System.out.printf("未找到编号为%d的节点\n", no);
        return;
    }

    /**
     * 有效节点个数(遍历+计数)
     */
    public int usedNode() {
   
        int ans = 0;
        heroNode temp = head;
        while (temp.next != null) {
   
            ans++;
            temp = temp.next;
        }
        return ans;
    }

    /**
     * 反向输出第k个节点
     */
    public void oppoShow(int k) {
   
        int all = usedNode();
        heroNode temp = head.next;
        if (all < k) {
   
            System.out.printf("没有第%d个节点\n", k);
            return;
        }
        int i = 1;
        while (temp != null) {
   
            if (i == (all - k + 1)) {
   
                System.out.println(temp.toString());
                break;
            }
            temp = temp.next;
            i++;
        }
        return;
    }

    /**
     * 反向遍历——翻转单链表
     */
    public void oppoShow() {
   
        if (head.next == null) {
   
            System.out.println("链表为空");
            return;
        }
        int all = usedNode();
        for (int i = all; i >= 0; i--) {
   
            int j = 1;
            heroNode temp = head.next;
            while (temp != null) {
   
                if (j == i) {
   
                    System.out.println(temp.toString());
                    break;
                }
                j++;
                temp = temp.next;
            }
        }
    }

    /**
     * 反向遍历——通过栈实现
     */
    public void showByStack() {
   
        if (head.next == null) {
   
            System.out.println("链表为空");
            return;
        }
        nodeStact ns = new nodeStact(usedNode());
        heroNode temp = head.next;
        while (temp != null) {
   
            ns.push(temp);
            temp = temp.next;
        }
        while (!ns.isEmpty()) {
   
            System.out.println(ns.pop().toString());
        }
    }

    /**
     * 与demo合并
     */
    public void mesh() {
   
        singleLinkedList demo = new singleLinkedList();
        demo.add(new heroNode(-1, "小明", "王哥"));
        demo.add(new heroNode(0, "芭芭拉", "芭芭拉冲鸭"));
        heroNode temp = demo.head.next;
        while(temp != null) {
   
            addByNo(new heroNode(temp.getNo(), temp.getName(), temp.getNickName()));
            temp = temp.next;
        }

    }
}

/**
 * 定义heroNode节点
 */
class heroNode {
   
    private int no;
    private String name;
    private String nickName;
    public heroNode next;

    /**
     * 构造器
     * 
     * @param no       编号
     * @param name     姓名
     * @param nickName 昵称
     */
    heroNode(int no, String name, String nickName) {
   
        this.name = name;
        this.no = no;
        this.nickName = nickName;
    }

    /**
     * 重写toString
     */
    @Override
    public String toString() {
   
        return "[no=" + no + ", name=" + name + ", nickName=" + nickName + ", next=" + next + "]";
    }

    public int getNo() {
   
        return no;
    }

    public void setNo(int no) {
   
        this.no = no;
    }

    public String getName() {
   
        return name;
    }

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

    public String getNickName() {
   
        return nickName;
    }

    public void setNickName(String nickName) {
   
        this.nickName = nickName;
    }

}

class nodeStact {
   
    int maxSize;
    heroNode[] hn;
    int top;

    /**
     * 栈的构造器
     * 
     * @param maxSize 栈的大小
     */
    nodeStact(int maxSize) {
   
        this.maxSize = maxSize;
        hn = new heroNode[maxSize];
        top = -1;
    }

    /**
     * 判空
     */
    public boolean isEmpty() {
   
        return top == -1;
    }

    /**
     * 判满
     */
    public boolean isFull() {
   
        return top == maxSize - 1;
    }

    /**
     * 弹出
     */
    public heroNode pop() {
   
        if (isEmpty()) {
   
            System.out.println("栈空");
            return null;
        }
        return hn[top--];
    }

    /**
     * 压栈
     */
    public void push(heroNode _hn) {
   
        if (isFull()) {
   
            System.out.println("栈满");
        } else {
   
            hn[++top] = _hn;
        }
    }
}

二、双向链表

1、双向链表概述

  1. 遍历方法和单链表一样,不仅可以向前,也可以向后查找
  2. 添加(默认添加到双向链表的最后)
    1. 先找到双向链表的最后这个节点
    2. temp.next = newHeroNode
    3. newHeroNode.pre=temp;
  3. 修改:思路和原来的单向链表一样
  4. 删除
    1. 双向链表可以实现自我删除某个节点
    2. 直接找到要州除的这个节点,比如 temp
    3. temp.pre.next =temp.next
    4. temp.next. pre = temp.pre;

2、代码实现

package work.rexhao.linkedlist;

import java.util.Scanner;

public class doubleLinkedListDemo {
   

    public static void main(String[] args) {
   
        doubleLinkedList dll = new doubleLinkedList();
        boolean loop = true;
        while (loop) {
   
            System.out.println("--------");
            System.out.println("1.在尾部添加");
            System.out.println("2.按编号添加");
            System.out.println("3.遍历双向链表");
            System.out.println("4.修改节点");
            System.out.println("5.删除节点");
            System.out.println("6.有效节点个数");
            System.out.println("0.退出");
            System.out.println("--------");
            Scanner sc = new Scanner(System.in);
            int key = sc.nextInt();
            if (key == 1) {
   
                System.out.println("请输入学生编号:");
                int no = sc.nextInt();
                System.out.println("请输入学生姓名:");
                Scanner sc1 = new Scanner(System.in);
                String name = sc1.nextLine();
                dll.add(new stuNode(no, name));
                System.out.println("添加成功!");
            } else if (key == 2) {
   
                System.out.println("请输入学生编号:");
                int no = sc.nextInt();
                System.out.println("请输入学生姓名:");
                Scanner sc1 = new Scanner(System.in);
                String name = sc1.nextLine();
                dll.addByNo(new stuNode(no, name));
                System.out.println("添加成功!");
            } else if (key == 3) {
   
                dll.show();
            } else if (key == 4) {
   
                System.out.println("请输入学生编号:");
                int no = sc.nextInt();
                System.out.println("请输入学生新的姓名:");
                Scanner sc1 = new Scanner(System.in);
                String name = sc1.nextLine();
                dll.change(new stuNode(no, name));
            } else if (key == 5) {
   
                System.out.println("请输入学生编号:");
                int no = sc.nextInt();
                dll.delete(no);
            } else if (key == 6) {
   
                System.out.println("有效节点个数:" + dll.usedNode());
            } else if (key == 0) {
   
                loop = false;
            } else {
   
                System.out.println("输入有误!");
            }
        }
    }

}

/**
 * 双向链表
 */
class doubleLinkedList {
   
    private stuNode head = new stuNode(0, "wmh");

    /**
     * 有效节点数
     */
    public int usedNode() {
   
        int ans = 0;
        stuNode temp = head.next;
        while (temp != null) {
   
            ans++;
            temp = temp.next;
        }
        return ans;
    }

    /**
     * 插入
     */
    public void add(stuNode sn) {
   
        if (head.next == null) {
   
            head.next = sn;
            sn.pre = head;
            return;
        }
        stuNode temp = head.next;
        while (true) {
   
            if (temp.next == null) {
   
                break;
            }
            temp = temp.next;
        }
        temp.next = sn;
        sn.pre = temp;

    }

    /**
     * 遍历
     */
    public void show() {
   
        if (head.next == null) {
   
            System.out.println("单链表为空");
            return;
        }
        stuNode temp = head.next;
        while (temp != null) {
   
            System.out.println(temp);
            temp = temp.next;
        }
    }

    /**
     * 修改
     */
    public void change(stuNode sn) {
   
        if (head.next == null) {
   
            System.out.println("单链表为空");
            return;
        }
        stuNode temp = head.next;
        while (temp != null) {
   
            if (temp.getNo() == sn.getNo()) {
   
                temp.setName(sn.getName());
                temp.setNo(sn.getNo());
                return;
            }
            temp = temp.next;
        }
        System.out.printf("未找到no=%d的节点\n", sn.getNo());
    }

    /**
     * 自我删除
     */
    public void delete(int no) {
   
        if (head.next == null) {
   
            System.out.println("链表为空");
            return;
        }
        stuNode temp = head.next;
        while (temp != null) {
   
            if (temp.getNo() == no) {
   
                /*
                 * 找到了
                 */
                temp.pre.next = temp.next;
                if (temp.next != null) {
   
                    temp.next.pre = temp.pre;
                }
                return;
            }
            temp = temp.next;
        }
        System.out.printf("未找到no=%d的节点\n", no);
    }

    /**
     * 按照编号添加
     */
    public void addByNo(stuNode sn) {
   
        /*
         * 判空
         */
        if (head.next == null) {
   
            head.next = sn;
            sn.pre = head;
            return;
        }
        /*
         * 判同
         */
        stuNode temp = head.next;
        while (temp != null) {
   
            if (temp.getNo() == sn.getNo()) {
   
                System.out.println("编号相同");
                return;
            }
            temp = temp.next;
        }
        /*
         * 找位置添加——第一个位置
         */
        if (sn.getNo() < head.next.getNo()) {
   
            sn.next = head.next;
            head.next = sn;
            sn.pre = head;
            sn.next.pre = sn;
            return;
        }
        /*
         * 找位置添加——不是第一个位置
         */
        temp = head.next;
        while (temp != null) {
   
            if (temp.next == null) {
   
                temp.next = sn;
                sn.pre = temp;
                return;
            }
            if (temp.getNo() < sn.getNo() && temp.next.getNo() > sn.getNo()) {
   
                sn.next = temp.next;
                temp.next = sn;
                sn.pre = head;
                sn.next.pre = sn;
                return;
            }
            temp = temp.next;
        }
    }
}

/**
 * 定义stuNode节点
 */
class stuNode {
   
    private int no;
    private String name;
    public stuNode next;
    public stuNode pre;

    /**
     * 构造器
     * 
     * @param no   编号
     * @param name 姓名
     */
    stuNode(int no, String name) {
   
        this.name = name;
        this.no = no;
    }

    public int getNo() {
   
        return no;
    }

    /**
     * 重写toString
     */
    @Override
    public String toString() {
   
        return "[no=" + no + ", name=" + name + "]";
        // 使用双向链表,不能打印next和pre
    }

    public void setNo(int no) {
   
        this.no = no;
    }

    public String getName() {
   
        return name;
    }

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

三、单项循环链表与Josepfu问题

1、约瑟夫环概述

设编号为1,2,⋯n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。

2、解决思想

用一个不带头结点的循环链表来处理 Josephu 问题:先构成一个有口个结点的单循环链表,然后由k结点起从1 开始计数,计到 m 时,对应结点从链表中州除,然后再从被删除结点的下一个结点又从1 开始计数,到最后一个结点从链表中删除算法结束。

3、代码实现

package work.rexhao.linkedlist;

import java.util.Scanner;

public class JosepfuDemo {
   

    public static void main(String[] args) {
   
        Scanner sc = new Scanner(System.in);
        System.out.print("总人数:");
        int n = sc.nextInt();
        System.out.print("报号数:");
        int k = sc.nextInt();
        Josepfu(n, k);
    }

    /**
     * Josepfu问题
     * 
     * @param n 人数
     * @param k 报号数
     */
    public static void Josepfu(int n, int k) {
   
        circleSingleLinkedList csll = new circleSingleLinkedList();
        for(int i = 1; i <= n; i++) {
   
            csll.add(new Node(i));
        }
        Node temp = csll.head;
        int j = 1;
        while(csll.usedNode() != 1) {
   
            if(j == k) {
   
                csll.delete(temp.getNum());
                j = 1;
                temp = temp.next;
                continue;
            }
            j++;
            temp = temp.next;
        }
        csll.show();
    }
}

class circleSingleLinkedList {
   
    public Node head = null;

    /**
     * 添加节点
     */
    public void add(Node n) {
   
        /*
         * 空链表,直接放后面
         */
        if (head == null) {
   
            head = n;
            n.next = head;
            return;
        }
        /*
         * 非空,遍历加在后面
         */
        Node temp = head;
        while (temp.next != head) {
   
            temp = temp.next;
        }
        temp.next = n;
        n.next = head;

    }

    /**
     * 遍历
     */
    public void show() {
   
        Node temp = head;
        boolean loop = true;
        while (loop) {
   
            System.out.println(temp);
            temp = temp.next;
            if (temp == head) {
   
                loop = false;
            }
        }
    }

    /**
     * 有效元素
     */
    public int usedNode() {
   
        if (head == null) {
   
            return 0;
        }
        if (head.next == head) {
   
            return 1;
        }
        Node temp = head;
        int ans = 1;
        while (temp.next != head) {
   
            temp = temp.next;
            ans++;
        }
        return ans;
    }

    /**
     * 删除节点
     */
    public void delete(int num) {
   
        /*
         * 判空
         */
        if (head == null) {
   
            System.out.println("链表为空");
            return;
        }
        /*
         * 删除head节点
         */
        if (head.getNum() == num) {
   
            if (head.next == head) {
   
                /*
                 * 只有一个head
                 */
                head = null;
            } else {
   
                /*
                 * 还有其他节点
                 */
                // 1.改最后的next
                Node temp = head;
                while (true) {
   
                    if (temp.next == head) {
   
                        temp.next = head.next;
                        break;
                    }
                    temp = temp.next;
                }
                // 2.改head
                head = head.next;
            }
            return;
        }
        /*
         * 删除其他的节点
         */

        Node temp = head.next;
        while (true) {
   
            if (temp.next.getNum() == num) {
   
                temp.next = temp.next.next;
                return;
            }
            temp = temp.next;
        }
    }
}

class Node {
   
    private int num;
    public Node next;

    Node(int num, Node next) {
   
        this.num = num;
        this.next = next;
    }

    Node(int num) {
   
        this.num = num;
        this.next = null;
    }

    @Override
    public String toString() {
   
        return "Node[num=" + num + "]";
    }

    public int getNum() {
   
        return num;
    }

    public void setNum(int num) {
   
        this.num = num;
    }

}
目录
相关文章
|
8天前
|
Java
java数据结构,双向链表的实现
文章介绍了双向链表的实现,包括数据结构定义、插入和删除操作的代码实现,以及双向链表的其他操作方法,并提供了完整的Java代码实现。
java数据结构,双向链表的实现
|
1月前
|
存储 Java 索引
【数据结构】链表从实现到应用,保姆级攻略
本文详细介绍了链表这一重要数据结构。链表与数组不同,其元素在内存中非连续分布,通过指针连接。Java中链表常用于需动态添加或删除元素的场景。文章首先解释了单向链表的基本概念,包括节点定义及各种操作如插入、删除等的实现方法。随后介绍了双向链表,说明了其拥有前后两个指针的特点,并展示了相关操作的代码实现。最后,对比了ArrayList与LinkedList的不同之处,包括它们底层实现、时间复杂度以及适用场景等方面。
44 10
【数据结构】链表从实现到应用,保姆级攻略
|
2月前
|
存储 C语言
【数据结构】c语言链表的创建插入、删除、查询、元素翻倍
【数据结构】c语言链表的创建插入、删除、查询、元素翻倍
【数据结构】c语言链表的创建插入、删除、查询、元素翻倍
|
3月前
【数据结构OJ题】环形链表
力扣题目——环形链表
33 3
【数据结构OJ题】环形链表
|
3月前
【数据结构OJ题】复制带随机指针的链表
力扣题目——复制带随机指针的链表
48 1
【数据结构OJ题】复制带随机指针的链表
|
3月前
【数据结构OJ题】环形链表II
力扣题目——环形链表II
23 1
【数据结构OJ题】环形链表II
|
3月前
【数据结构OJ题】相交链表
力扣题目——相交链表
28 1
【数据结构OJ题】相交链表
|
2月前
【数据结构】双向带头(哨兵位)循环链表 —详细讲解(赋源码)
【数据结构】双向带头(哨兵位)循环链表 —详细讲解(赋源码)
83 4
|
2月前
|
存储 Java 程序员
"揭秘HashMap底层实现:从数组到链表,再到红黑树,掌握高效数据结构的秘密武器!"
【8月更文挑战第21天】HashMap是Java中重要的数据结构,采用数组+链表/红黑树实现,确保高效查询与更新。构造方法初始化数组,默认容量16,负载因子0.75触发扩容。`put`操作通过计算`hashCode`定位元素,利用链表或红黑树处理冲突。`get`和`remove`操作类似地定位并返回或移除元素。JDK 1.8优化了链表转红黑树机制,提升性能。理解这些原理能帮助我们更高效地应用HashMap。
35 0
|
2月前
|
存储 算法
【初阶数据结构篇】顺序表和链表算法题
此题可以先找到中间节点,然后把后半部分逆置,最近前后两部分一一比对,如果节点的值全部相同,则即为回文。