zoukankan      html  css  js  c++  java
  • Java 自定义双向链表

    双向链表

    LinkedList其实也就是我们在数据结构中的链表,这种数据结构有这样的特性:

    分配内存空间不是必须是连续的;
    插入、删除操作很快,只要修改前后指针就OK了,时间复杂度为O(1);
    访问比较慢,必须得从第一个元素开始遍历,时间复杂度为O(n);
    在Java中,LinkedList提供了丰富的方法,可以模拟链式队列,链式堆栈等数据结构,为用户带来了极大的方便,下面我们来自定义一个双向链表(目的了解底层实现原理)

    自定义节点结构

     1 // 自定义节点结构
     2 class Node {
     3     Node first;
     4     Node last;
     5     Object element;
     6 
     7     public Node(Node first, Node last, Object element) {
     8         super();
     9         this.first = first;
    10         this.last = last;
    11         this.element = element;
    12     }
    13 
    14     public Node(Node node) {
    15         this.element = node;
    16         node.first = null;
    17         node.last = null;
    18     }
    19 }

    一些常用的方法(代码由我们自定义实现):

    Java为我们提供了很多方法:

    1、add方法

    boolean add(E e):在链表后添加一个元素,如果成功,返回true,否则返回false;
    void addFirst(E e):在链表头部插入一个元素;
    addLast(E e):在链表尾部添加一个元素;
    void add(int index, E element):在指定位置插入一个元素。

     1     public void add(Object obj) {
     2         Node newNode = new Node(obj);
     3         if (first == null) {
     4             // newNode.previous = null;
     5             // newNode.next = null;
     6             first = newNode;
     7             last = newNode;
     8         } else {
     9             newNode.previous = last;
    10             newNode.next = null;
    11 
    12             last.next = newNode;
    13             last = newNode;
    14         }
    15         size++;
    16     }

    2、remove方法

    E remove();移除链表中第一个元素;
    boolean remove(Object o):移除链表中指定的元素;
    E remove(int index):移除链表中指定位置的元素;
    E removeFirst():移除链表中第一个元素,与remove类似;
    E removeLast():移除链表中最后一个元素;
    boolean removeFirstOccurrence(Object o):移除链表中第一次出现所在位置的元素;
    boolean removeLastOccurrence(Object o):移除链表中最后一次出现所在位置的元素;

     1 public void remove(int index) {
     2         checkRange(index);
     3 
     4         Node temp = getNode(index);
     5         if (temp != null) {
     6             Node up = temp.previous;
     7             Node down = temp.next;
     8 
     9             if (up != null) // 不是头结点
    10             {
    11                 up.next = down;
    12             }
    13             if (index == 0) { // 是头结点
    14                 first = down;
    15             }
    16             if (down != null) { // 不是尾节点时
    17                 down.previous = up;
    18             }
    19             if (index == size - 1) {
    20                 last = up;
    21             }
    22             size--;
    23         }
    24     }

    全部代码

    package 测试容器;
    
    public class TestLinkList<E> {
    
        int size;
        Node first;
        Node last;
    
        public static void main(String[] args) {
    
            TestLinkList<String> lst = new TestLinkList<>();
            lst.add("haha");
            lst.add("hehe");
            lst.add("xixi");
            System.out.println(lst);
            System.out.println(lst.get(0));
            lst.remove(0);
            System.out.println(lst);
    
        }
    
        public void add(Object obj) {
            Node newNode = new Node(obj);
            if (first == null) {
                // newNode.previous = null;
                // newNode.next = null;
                first = newNode;
                last = newNode;
            } else {
                newNode.previous = last;
                newNode.next = null;
    
                last.next = newNode;
                last = newNode;
            }
            size++;
        }
    
        public void remove(int index) {
            checkRange(index);
    
            Node temp = getNode(index);
            if (temp != null) {
                Node up = temp.previous;
                Node down = temp.next;
    
                if (up != null) // 不是头结点
                {
                    up.next = down;
                }
                if (index == 0) { // 是头结点
                    first = down;
                }
                if (down != null) { // 不是尾节点时
                    down.previous = up;
                }
                if (index == size - 1) {
                    last = up;
                }
                size--;
            }
        }
    
        public E get(int index) {
            checkRange(index);
    
            Node temp = getNode(index);
            return (E) temp.element;
        }
    
        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder("[");
            Node temp = first;
            while (temp != null) {
                sb.append(temp.element + ",");
                temp = temp.next;
            }
            sb.setCharAt(sb.length() - 1, ']');
            return sb.toString();
        }
    
        public Node getNode(int index) {
            Node temp = null;
            if (index > (size >> 1)) { // 二分,提高效率
                temp = last;
                for (int i = size - 1; i > index; i--) {
                    temp = temp.previous;
                }
            } else {
                temp = first;
                for (int i = 0; i < index; i++) {
                    temp = temp.next;
                }
            }
            return temp;
        }
    
        public void checkRange(int index) {
            if (index < 0 || index > size - 1) {
                throw new RuntimeException("非法索引" + index);
            }
    
        }
    }
    
    // 自定义节点结构
    class Node {
        Node previous;
        Node next;
        Object element;
    
        public Node(Node first, Node last, Object element) {
            super();
            this.previous = first;
            this.next = last;
            this.element = element;
        }
    
        public Node(Object obj) {
            this.element = obj;
        }
    }

    可以参考单链表的实现过程

    参考资料:https://blog.csdn.net/sinat_36246371/article/details/53709625

  • 相关阅读:
    Linux的iptables和netfilter
    adb安装电视apk
    令牌桶实现服务器限流
    观察者模式代码实现
    Windows系统安装Oracle 11g 数据库
    Gitlab安装后 启动之后报错502
    Git两库合并历史记录
    Maven打包时指定对应环境的配置文件
    HierarchicalDataTemplateGridControl
    自定义CommandHandler
  • 原文地址:https://www.cnblogs.com/liuzeyu12a/p/10351184.html
Copyright © 2011-2022 走看看