• 链表(单向链表,双向链表)


    1.链表的基本介绍

       首先链表是以节点的方式存储数据的,每个节点包含数据域(data),节点域(next),链表的每个节点在计算机中存储的位置是不连续的和随机的,优点就是数据的插入和删除比较好,而查找数据效率不是太好(因为链表无法像静态数据一样随机读取数据,必须按照顺序找到对应的数据为止)。

     

     2.单向链表

     2.1.什么是单向链表

       单向链表就像是火车,所有的节点串联成一列,而且指针所指的方向一样,也就是链表中每个节点除了存储原本的数据,还有存储下一个节点的存储地址。如下图所示:

     

     节点类的代码实现

    class SingleNode {
        public Object object; //节点数据
        public SingleNode next; //指向下一个节点
    
        public SingleNode() {
    
        }
    
        public SingleNode(Object object, SingleNode next) {
            this.object = object;
            this.next = next;
    
        }
    }
    

    2.2.单向链表实现(增加,删除,修改,查看)数据

    /**
     * 单链表的实现
     */
    public class SingleLinkList {
        private SingleNode first; //定义头结点
        private SingleNode last;  //定义尾节点
        private int size;   //定义链表的节点数
    
        /**
         * 判断链表是否为空
         * @return
         */
        public boolean isEmpty() {
            return first == null;
        }
    
        /**
         * 在链表的头部和尾部添加元素
    * 思路分析:当链表为空时,就相当于在链表的头部添加数据,所以把新添加的节点赋值给头结点(尾节点),
    * 当链表不为空时,就相当于于在链表的尾部添加数据,这时候我们就是把尾部的指针指向新添加的节点(即last.next=node),然后把新添加的节点赋值到
    * 最后节点 (即last=node) */ public void add(Object object) { SingleNode node = new SingleNode(object, null); if (isEmpty()) { first = node; } else { last.next = node; } last = node; size++; } /** * 在指定的节点增加元素 * 思路分析:首先我们需要判断添加的位置是否满足条件(index>0 && index<size),然后我们需要找到指定索引位置的元素和它的上一个位置的元素,所以用到
    * 两个指针来记录索引位置的元素和它上一个位置的元素,最后把 (before.next=node,node.next=temp),这就相当于把before指向node,node指向当前节点(temp)即可。 * @param index * @param object */ public void addElement(int index, Object object) { SingleNode node = new SingleNode(object, null); if (index > 0 && index < size) { SingleNode temp = first; SingleNode before = null; for (int i = 0; i < index; i++) { before = temp; temp = temp.next; } before.next = node; node.next = temp; size++; } } /** * 展示链表中的节点元素 */ public void show() { if (!isEmpty()) { SingleNode current = first; while (current != null) { System.out.println(current.object); current = current.next; } } } /** * 获得指定节点的元素 * 思路分析:定义一个指针,循环到指定位置,把元素取出即可 * @param index * @return */ public Object get(int index) { if (index > 0 && index < size) { if (!isEmpty()) { SingleNode temp = first; for (int i = 0; i < index; i++) { temp = temp.next; } return temp.object; } } return null; } /** * 删除指定节点的元素 * 思路分析:需要定义两个指针来记录要删除的节点和要删除节点的上一个节点,然后 把before.next=temp.next即可。 * @param index */ public void remove(int index) { if (index > 0 && index < size) { if (!isEmpty()) { SingleNode temp = first; SingleNode beforeTemp = null; for (int i = 0; i < index; i++) { beforeTemp = temp; temp = temp.next; } beforeTemp.next = temp.next; } } } /** * 修改指定节点的指定元素 * * @param index * @param object */ public void update(int index, Object object) { if (index > 0 && index < size) { if (!isEmpty()) { SingleNode temp = first; for (int i = 0; i < index; i++) { temp = temp.next; } temp.object = object; } } } /** * 实现链表的反向打印
    * 思路分析:利用栈先进后出的特点,首先把元素放到栈中,然后再取出,即可。 */ public void rePrint() { Stack<SingleNode> stack = new Stack<SingleNode>(); if (!isEmpty()) { SingleNode current = first; while (current != null) { stack.push(current); current = current.next; } while (stack.size() > 0) { System.out.println(stack.pop().object); } } } /** * 将单链表反转 */ public void reversetList() { SingleNode current = first; SingleNode before = null; while (current != null) { last = before; before = current; current = current.next; before.next = last; } current = before; while (current != null) { System.out.println(current.object); current = current.next; } }
     

     3.双向链表

     3.1.什么是双向链表

       简单的说就是有两个字段存放指针,一个字段存放数据,如下图所示:

     节点类的定义:

    class Node {
        public Object object;
        public Node pre;
        public Node next;
    
        public Node() {
    
        }
    
        public Node(Node pre, Object object, Node next) {
            this.pre = pre;
            this.object = object;
            this.next = next;
        }
    
    
    }
    

      

    3.2.双向链表实现(增加,删除,修改,遍历)

    public class DoubleListDemo {
        private Node first;
        private Node last;
        private int size;
    
        /**
         * 在链表的头部或尾部添加数据
         * 实现思路:和单链表基本一致
         * @param object
         */
        public void add(Object object) {
            Node node = new Node(null, object, null);
            if (isEmpty()) {
                first = node;
            } else {
                last.next = node;
                node.pre = last;
            }
            last = node;
            size++;
    
        }
        
        public boolean isElmentIndex(int index) {
            return index <= 0 && index < size;
        }
    
        /**
         * 在指定节点添加元素
         * 实现思路:与单向链表唯一的不同只需要找到该节点的元素就可以找到上一个节点,然后互相指向即可。
         * @param index
         * @param object
         */
        public void add(int index, Object object) {
            if (!isElmentIndex(index)) {
                //首先找到指定的节点
                Node temp = first; //定义一个指针
                for (int i = 0; i < index; i++) {
                    temp = temp.next;
                }
                Node newNode = new Node(null, object, null);
                Node up = temp.pre;  //temp 节点前的节点(原来的链表)
                up.next = newNode;
                newNode.pre = up;
                temp.pre = newNode;
                newNode.next = temp;
                size++;
            }
        }
    
        /**
         * 删除指定节点的元素
         * 实现思路:同单向链表
         * @param index
         * @return
         */
        public void remove(int index) {
            if (!isElmentIndex(index)) {
                Node temp = first;
                for (int i = 0; i < index; i++) {
                    temp = temp.next;
                }
                Node up = temp.pre;
                Node down = temp.next;
                up.next = down;
                down.pre = up;
                size--;
            }
        }
    
        /**
         * 获得指定节点中的元素
         *
         * @param index
         * @return
         */
        public Object get(int index) {
            if (!isElmentIndex(index)) {
                Node temp = first;
                for (int i = 0; i < index; i++) {
                    temp = temp.next;
                }
                return temp.object;
            }
            return null;
        }
    
        /**
         * 判断节点的个数
         *
         * @return
         */
        public int size() {
            return size;
        }
    
        /**
         * 获得链表中全部的元素
         */
        public void show() {
            Node currentNode = first;
            while (currentNode != null) {
                System.out.println(currentNode.object);
                currentNode = currentNode.next;
            }
            System.out.println();
        }
    
        /**
         * 修改指定节点的元素
         *
         * @param index
         * @return
         */
        public void update(int index, Object object) {
            if (!isElmentIndex(index)) {
                Node temp = first;
                for (int i = 0; i < index; i++) {
                    temp = temp.next;
                }
                temp.object = object;
            }
        }
    
        /**
         * 判断链表是否为空
         *
         * @return
         */
        public boolean isEmpty() {
            return first == null;
        }
    
    }
    

    每天进步一丢丢

    完毕。

     

      

      

       

  • 相关阅读:
    根据group by、count case when 分组分类统计
    Cron表达式
    SQL分页查询 — 不同页面的查询结果有重复数据
    Dockerfile文件语法
    redis获取系统当前时间
    mybatis oracle批量插入数据
    Mysql函数->TRIM(去掉首尾空格、任意字符)
    Oracle函数->TRIM(去掉首尾空格、首尾字符)
    使用redis-list类型 限制用户1分钟内访问次数为100次
    一文了解mysql基础架构
  • 原文地址:https://www.cnblogs.com/xiaofuzi123456/p/12676819.html
Copyright © 2020-2023  润新知