柏竹 柏竹
首页
后端
前端
  • 应用推荐
关于
友链
  • 分类
  • 标签
  • 归档

柏竹

奋斗柏竹
首页
后端
前端
  • 应用推荐
关于
友链
  • 分类
  • 标签
  • 归档
  • Java基础

  • JavaWeb

  • 拓展技术

  • 框架技术

  • 数据库

  • 数据结构

    • 队列
    • 二叉树
    • 栈
    • 链表
      • 单向链表
      • 双向链表
      • 循环链表
        • 单向循环链表
        • 双向循环链表
  • Spring

  • SpringMVC

  • SpringBoot

  • SpringClound

  • Ruoyi-Vue-Plus

  • 后端
  • 数据结构
柏竹
2021-02-14
目录

链表

# 链表

链表(linked list),由一系列结点node(链表中每一个元素称为结点)组成,结点可以在运行时 i 动态生成

数据域: 存储数据的元素 指针域: 存储下个节点的地址

# 单向链表

由各个内存结构通过一个 Next 指针链接在一起组成,每一个内存结构都存在后继内存结构(链尾除外),内存结构由数据域和 Next 指针域组成

Main :(执行类)

public class Main {
    public static void main(String[] args) {
        
        //实例 操作对象
        MyLink myLink = new MyLink();
        
        //初始化链表数据
        // 参数: name , id
        Node[] staff = {
                new Node(121,"小爱" , "00001"),
                new Node(112,"可怡"  , "00023"),
                new Node(233,"小黑" , "33123")
        };
        
        //添加链表
        for(Node tmp : staff){
            myLink.addLast(tmp);
        }
        
        //添加单链 (最后)
        myLink.addLast(new Node(232 , "智乃" ,"44221"));
        
        //插入单链(索引)  在 "可怡" 节点 链后添加 "黑猫" 节点
        myLink.addByValue(112 , new Node(234,"黑猫" , "00444"));
        
        // 节点值为121  "可怡" 删除
        myLink.removeNode(112);
        
        //查询数据
        System.out.println("查询节点值 234 的数据 : ["+myLink.getNode(234)+"]");
        
        // 遍历链表
        System.out.println("=================");
        for (Node tmp : myLink.getNodeAll()){
            System.out.println(tmp.toString());
        }
        System.out.println("=================");
        
    }
}

Node :(单链节点类)

/**
 * 单列节点
 * 链表中的节点,
 * data   代表节点的值
 * next   指向下一个节点的引用
 * @author Administrator
 */
public class Node {
    
    /**数据域 (员工数据)
     * name - 姓名
     * id - ID号
     * */
    String name;
    String id;
    
    /**指针域 (链表数据)
     * data - 节点的对象,即内容
     * next - 节点的引用
     */
    int data;
    Node next = null;
    
    //构造方法
    
    public Node() {
    }
    
    public Node(int data) {
        this.data = data;
    }
    
    public Node(int data , Node next) {
        this.data = data;
        this.next = next;
    }
    
    public Node(String name , String id) {
        this.name = name;
        this.id = id;
    }
    
    public Node(int data , String name , String id) {
        this.data = data;
        this.name = name;
        this.id = id;
    }
    
    public Node(int data , Node next , String name , String id ) {
        this.name = name;
        this.id = id;
        this.data = data;
        this.next = next;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    public void setId(String id) {
        this.id = id;
    }
    
    @Override
    public String toString() {
        return "Node{" +
                "name='" + name + '\'' +
                ", id='" + id + '\'' +
                ", data=" + data +
                // ", next=" + next +
                '}';
    }
    
}

MyLink :(链表操作类)

public class MyLink {
    //头节点
    Node head = null;
    
    /**
     * 链表尾部添加节点
     * @param d 节点值
     * @return 是否成功
     */
    public boolean addLast(int d){
        //实例节点
        Node newNode = new Node(d);
        //第一次创建的链头
        if (head == null){
            head = newNode;
            return true;
        }
        Node tmp = head;
        //遍历链表 循环直到最后 Node.next = null 空的节点引用
        while (tmp.next != null){
            //往后移一个节点,指向下一个节点
            tmp = tmp.next;
        }
        //在最后面null节点添加新节点
        tmp.next = newNode;
        return true;
    }
    
    /**
     * 链表尾部添加节点
     * @param node 节点对象
     * @return 是否成功
     */
    public boolean addLast(Node node){
        //第一次创建的链头
        if (head == null){
            head = node;
            return false;
        }
        Node tmp = head;
        //遍历链表 循环直到最后 Node.next = null 空的节点引用
        while (tmp.next != null){
            //往后移一个节点,指向下一个节点
            tmp = tmp.next;
        }
        //在最后面null节点添加新节点
        tmp.next = node;
        return true;
    }
    
    /**
     *  指定值 后面添加节点
     * @param value 节点值
     * @param node 单节点
     */
    public boolean addByValue(int value , Node node){
        Node tmp = head;
        //第一次添加则无效
        if (tmp == null){
            return false;
        }
        //遍历链表
        while(tmp != null){
            //data 节点内容 相同为止
            if(tmp.data == value){
                //插入
                //更改指向
                node.next = tmp.next;
                //节点的下一位
                tmp.next = node;
                return true;
            }
            //指向下一节点
            tmp = tmp.next;
        }
        return false;
    }
    
    /**
     *  删除节点
     * @param value
     * @return 是否成功
     */
    public boolean removeNode(int value){
        if (head == null){
            return false;
        }
        //如果要删除头 ,将头的下一个覆盖即可
        if (head.data == value){
            head = head.next;
            return true;
        }
        Node tmp = head;
        //遍历链表
        while (tmp.next != null){
            if (tmp.next.data == value){
                //该节点被 上节点连接至 下下节点
                tmp.next = tmp.next.next;
                return true;
            }
            tmp = tmp.next;
        }
        return false;
    }
    
    /**
     * 获取指定节点
     * @param value
     * @return
     */
    public Node getNode(int value){
        if (head.data == value){
            return head;
        }
        Node tmp = head;
        while (tmp != null){
            if (tmp.data == value){
                return tmp;
            }
            tmp = tmp.next;
        }
        return null;
    }
    
    /**
     * 获取链表全部
     * @return
     */
    public Node[] getNodeAll(){
        if (head == null){
            return null;
        }
        Node tmp = head;
        Node[] arrayNode = new Node[size()];
        int i = 0;
        while (tmp != null){
            arrayNode[i++] = tmp;
            tmp = tmp.next;
        }
        return arrayNode;
    }
    
    /**
     * 获取链表长
     * @return
     */
    public int size(){
        Node tmp  = head;
        int size = 0;
        while (tmp != null){
            size++;
            tmp = tmp.next;
        }
        return size;
    }
    
    /**
     * 是否为空
     * @return
     */
    public boolean isEmpty(){
        return head == null;
    }
    
    /**
     *  获取 头节点
     * @return
     */
    public Node getHead(){
        return head;
    }
    
    /**
     * 获取 尾节点
     * @return
     */
    public Node getTail(){
        if (head == null){
            return head;
        }
        Node tmp = head;
        while (tmp.next != null){
            tmp = tmp.next;
        }
        return tmp;
    }
}

学习来源分享链接:点击 (opens new window)

# 双向链表

由各个内存结构通过指针 Next 和指针 Prev 链接在一 起组成,每一个内存结构都存在前驱内存结构和后继内存结构(链头没有前驱,链尾没有后继),内存结构由数据域、指针域 (Prev , Next)组成

详细图解

Main 执行类:

public class Main {
    public static void main(String[] args) {
        
        MyLink myLink = new MyLink();

        Node[] staff = {
                new Node(111 ,1),
                new Node(222 , 2),
                new Node(444 , 4),
        };
        
        for (Node tmp : staff){
            myLink.addLast(tmp);
        }
        //添加节点值
        myLink.addLast(555);
        
        //插入链表 指定 date 222 后面添加 节点值 333
        myLink.addByValue(222 , new Node(333,3));
        
        //删除链表 指定 date 222 删除
        myLink.removeNode(222);

        /*以下是打印操作 , 可以自定选择
        	打印形式可更改 Node类 中的 toString方法 进行打印
        */
	
        System.out.println(myLink.getByNode(555));
        System.out.println();
       
        //System.out.println(myLink.getTail().getPrev());
        System.out.println(myLink.getHead());
        System.out.println("===============");
        System.out.println(myLink.getTail());
        //System.out.println(myLink.getHead().getNext());

        System.out.println();
        System.out.println("size = "+ myLink.size());
        
    }
}

MyLink 操作类:

public class MyLink {
    
    Node head = null;
    
    /**
     * 添加链表(节点值)
     * @param d
     */
    public void addLast(int d){
        Node newNode = new Node(d);
        if (head == null){
            head = newNode;
            return;
        }
        Node tmp  = head;
        while (tmp.next != null){
            tmp = tmp.next;
        }
        tmp.next = newNode;
        //指向后面
        newNode.prev = tmp;
    }
    
    /**
     * 添加链表(节点)
     * @param node
     */
    public void addLast(Node node){
        if (head == null){
            head = node;
            return;
        }
        Node tmp  = head;
        while (tmp.next != null){
            tmp = tmp.next;
        }
        tmp.next = node;
        node.prev = tmp;
    }
    
    /**
     * 插入节点
     * 指定节点值 value 的后面添加 节点
     * @param value
     * @param node
     * @return
     */
    public boolean addByValue(int value , Node node){
        if (head == null){
            return false;
        }
        Node tmp = head;
        while (tmp != null){
            if (tmp.date ==value){
                //反向链 处理
                tmp.next.prev = node;
                node.prev = tmp;
                
                node.next = tmp.next;
                tmp.next = node;
                return true;
            }
            tmp = tmp.next;
        }
        return false;
    }
    
    /**
     * 删除指定节点
     * @return
     */
    public boolean removeNode(int value){
        if (size() == 0 || head == null){
            return false;
        }
        Node tmp = head;
        while (tmp.next != null){
            if (tmp.next.date == value){
                tmp.next.next.prev = tmp;
                //next 跳过指向
                tmp.next = tmp.next.next;
                return true;
            }
            tmp = tmp.next;
        }
        return false;
    }
    
    /**
     * 获取链表长
     * @return
     */
    public int size(){
        Node tmp = head;
        int size = 0;
        while (tmp != null){
            size++;
            tmp = tmp.next;
        }
        return size;
    }
    
    /**
     * 获取 指定节点
     * @param date
     * @return
     */
    public Node getByNode(int date){
        Node tmp = head;
        while (tmp != null){
            if (tmp.date == date){
                return tmp;
            }
            tmp = tmp.next;
        }
        return null;
    }
    
    /**
     *  获取 头节点
     * @return
     */
    public Node getHead(){
        return head;
    }
    
    /**
     * 获取 尾节点
     * @return
     */
    public Node getTail(){
        if (head == null){
            return head;
        }
        Node tmp = head;
        while (tmp.next != null){
            tmp = tmp.next;
        }
        return tmp;
    }
}

Node 单链类:

import java.util.Objects;

public class Node {
    
    //数据域 (内容自定义)
    String name;
    int id;
    
    /**指针域
     *  date - 节点值(数据类型自定义)
     *  prev - 节头 引用
     *  next - 节尾 引用
     */
    int date;
    Node prev;
    Node next;
    
    
    public Node(int date) {
        this.date = date;
    }
    
    public Node(int date, Node prev, Node next) {
        this.date = date;
        this.prev = prev;
        this.next = next;
    }
    
    public Node(String name, int id, int date, Node prev, Node next) {
        this.name = name;
        this.id = id;
        this.date = date;
        this.prev = prev;
        this.next = next;
    }
    
    public Node(int date , int id) {
        this.id = id;
        this.date = date;
    }
    
    public boolean equals(int d) {
        return date == d;
    }
    
    //输出属性 next 或 prev 二选一
    @Override
    public String toString() {
        return "Node{" +
                //"id=" + id +
                "date=" + date +
                //", next= "+next+
                ", prev="+prev+
                '}';
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(date);
    }
}

# 循环链表

循环链表没有链头和链尾的说法,因为是闭环的,所以每一个内存结构都可以充当链头 和链尾

# 单向循环链表

由各个内存结构通过一个指针 Next 链接在一起组成,每一个内存结构都存在后继内存结构,内存结构由数据域和 Next 指针域组成

链尾的 Next 指针直接指向链头,形成一个闭环

# 双向循环链表

由各个内存结构通过指针 Next 和指针 Prev 链接在一起组成,每一个内存结构都存在前驱内存结构和后继内存结构,内存结构由 数据域、Prev 指针域和 Next 指针域组成

链尾的 Next 指针指向链头,再把链头的 Prev 指针指向链尾,形成一个闭环

闭环我就不多写了,头尾连接即可

#数据结构#Java
上次更新: 2023/03/12, 00:43:49

← 栈 Spring→

最近更新
01
HTTPS自动续签
10-21
02
博客搭建-简化版(脚本)
10-20
03
ruoyi-vue-plus-部署篇
07-13
更多文章>
Theme by Vdoing | Copyright © 2019-2024 | 桂ICP备2022009417号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式