• 学习数据结构Day4


    链表

     

    之前看过了动态数组,栈和队列,虽然我们把第一个叫做动态数组,但是,他们的底层实质上还是静态数组。靠

    resize来实现动态数组。而链表是真正的数据结构

    • 链表需要一个节点。
    • 数据存储在链表中

    相当于是一串火车,将数据放在车厢中,两个车厢之间还需要一个个节点来相互串联。

    优点:实现了真正的动态。

    缺点:无法进行随机访问

    public class LinkedList<E> {
    
        private class Node {
    
            public E e;
            public Node next;
    
            public Node(E e) {
                this(e, null);
            }
    
            public Node(E e, Node next) {
                this.e = e;
                this.next = next;
            }
    
            public Node() {
                this(null, null);
            }
    
            @Override
            public String toString() {
                return e.toString();
            }
        }
    
        private Node head;
        private int size;
    
        public LinkedList(Node head, int size) {
            head = null;
            this.size = 0;
        }
    
        //获取链表中的元素个数
        public int getSize() {
            return size;
        }
    
        //返回链表是否为空
        public boolean isEmpty() {
            return size == 0;
        }
    
        //链表添加新的元素
        public void addFirst(E e) {
    //        Node newNode = new Node((E) node);
    //        newNode.next = head;
    //        head = newNode;
    
            head = new Node(e, head);
            size++;
        }
    
        //在链表的index位置添加新的元素e
        //在链表中不是一个常用的操作 :)
        public void add(int index, E e) {
            if (index < 0 || index > size) {
                throw new IllegalArgumentException("Add failed,Illegal index");
            }
            if (index == 0) {
                addFirst(e);
            } else {
                Node prev = new Node(e);
                for (int i = 0; i < index - 1; i++) {
                    prev.next = prev;
                }
    //            Node node = new Node(e);
    //            prev.next = node.next;
    //            prev.next = node;
                prev.next = new Node(e,prev.next);
    
                size++;
            }
        }
    
        //在末尾添加元素
        public void addLast(E e){
            add(size,e);    
        }
    

    这是自己建立的链表,在此处,一定要注意几点

    • 在增加或删除元素时,不要忘了维护size
    • 再添加链表时,一定不要忘了顺序的问题,一定是先prev.next = node.next.之后才是prev.next = node;
    • 一开始的时候 head = prev

    再添加操作时,由于头结点的上一个节点时null,所以我们需要特殊处理,为了解决这个问题,我们增加了一个虚拟

    头结点。这个节点不存出任何数据。

    public class LinkedList<E> {
    
        private class Node {
    
            public E e;
            public Node next;
    
            public Node(E e) {
                this(e, null);
            }
    
            public Node(E e, Node next) {
                this.e = e;
                this.next = next;
            }
    
            public Node() {
                this(null, null);
            }
    
            @Override
            public String toString() {
                return e.toString();
            }
        }
    
        private Node dummyHead;
        private int size;
    
    
        public LinkedList() {
            dummyHead = new Node(null, null);
            size = 0;
        }
    
        public LinkedList(Node head, int size) {
            head = null;
            this.size = 0;
        }
    
        //获取链表中的元素个数
        public int getSize() {
            return size;
        }
    
        //返回链表是否为空
        public boolean isEmpty() {
            return size == 0;
        }
        //在链表的index位置添加新的元素e
        //在链表中不是一个常用的操作 :)
        public void add(int index, E e) {
            if (index < 0 || index > size) {
                throw new IllegalArgumentException("Add failed,Illegal index");
            }
    
            Node prev = dummyHead;
            for (int i = 0; i < index; i++) {
                prev.next = prev;
            }
    //            Node node = new Node(e);
    //            prev.next = node.next;
    //            prev.next = node;
            prev.next = new Node(e, prev.next);
    
            size++;
    
        }
        //链表添加新的元素
        public void addFirst(E e) {
    //        Node newNode = new Node((E) node);
    //        newNode.next = head;
    //        head = newNode;
    
            add(0,e);
            size++;
        }
        //在末尾添加元素
        public void addLast(E e) {
            add(size, e);
        }
    
    
    }
    

    链表的遍历,增 删 改 查。

    public class LinkedList<E> {
    
        private class Node {
    
            public E e;
            public Node next;
    
            public Node(E e) {
                this(e, null);
            }
    
            public Node(E e, Node next) {
                this.e = e;
                this.next = next;
            }
    
            public Node() {
                this(null, null);
            }
    
            @Override
            public String toString() {
                return e.toString();
            }
        }
    
        private Node dummyHead;
        private int size;
    
    
        public LinkedList() {
            dummyHead = new Node();
            size = 0;
        }
    
    
        //获取链表中的元素个数
        public int getSize() {
            return size;
        }
    
        //返回链表是否为空
        public boolean isEmpty() {
            return size == 0;
        }
    
    
        //在链表的index位置添加新的元素e
        //在链表中不是一个常用的操作 :)
        public void add(int index, E e) {
            if (index < 0 || index > size) {
                throw new IllegalArgumentException("Add failed,Illegal index");
            }
    
            Node prev = dummyHead;
            for (int i = 0; i < index; i++) {
                prev= prev.next ;
            }
    //            Node node = new Node(e);
    //            prev.next = node.next;
    //            prev.next = node;
            prev.next = new Node(e, prev.next);
    
            size++;
    
        }
    
    
        //链表添加新的元素
        public void addFirst(E e) {
    //        Node newNode = new Node((E) node);
    //        newNode.next = head;
    //        head = newNode;
    
            add(0, e);
    
        }
    
    
        //在末尾添加元素
        public void addLast(E e) {
            add(size, e);
        }
    
        /**
         * 遍历整个列表
         * 实际过程中不会这么用
         * 仅供联系
         *
         * @param index
         * @return
         */
        public E get(int index) {
            if (index < 0 || index > size) {
                throw new IllegalArgumentException("Get failed Illegal index");
            }
            Node cur = dummyHead.next;
            for (int i = 0; i < index; i++) {
                cur = cur.next;
            }
            return cur.e;
        }
    
    // 获得链表的第一个元素
    public E getFirst() {
    return get(0);
        }
    //获取链表的最后一个元素
    public E getLast() {
    return get(size - 1);
        }
    //修改链表的第index(0-based)个位置的元素为e
    //在链表中不是一个常用的操作,练习用 :)
    public void set(int index, E e) {
    if (index < 0 || index >= size) {
    throw new IllegalArgumentException("Set Failed,illegal index");
            }
    Node cur = dummyHead.next;
    for (int i = 0; i < index; i++) {
    cur = cur.next;
            }
    cur.e = e;
        }
    //参照链表中是否有元素E
    public boolean contains(E e){
    Node cur = dummyHead.next;
    while (cur != null){
    if(cur.e.equals(e)){
    return true;
                }
    cur = cur.next;
            }
    return  false;
        }
    @Override
    public String toString(){
    StringBuilder res = new StringBuilder();
    Node cur = dummyHead.next;
    while(cur != null){
    res.append(cur+"->");
    cur = cur.next;
            }
    res.append("null");
    return res.toString();
    }
    }
    

    之前这些代码我们写完了增 改 查,下面我们就要写删除操作。

     //删除链表中的一个元素
        public E remove(int index) {
            if (index > 0 || index < size) {
                throw new IllegalArgumentException("remove failed");
            }
            Node prev = dummyHead;
            for (int i = 0; i < index; i++) {
                prev = prev.next;
            }
            Node retNode = prev.next;
            prev.next = retNode.next;
            retNode.next = null;
            size--;
            return retNode.e;
        }
    
        //删除链表中的第一个元素
        public E removeFirst() {
            return remove(0);
        }
    
        //删除链表中最后一个元素
        public E removeLast() {
            return remove(size - 1);
        }

    链表的时间复杂度

    • addLast(e):O(n)
    • addFirst(e):O(1)
    • add(index,e):O(n)
    • setIndex(e):O(n)
    • get(index):O(n)
    • contains(e):O(n)

    如果只对链表头进行操作,那么他的时间复杂度是O(1),所以我们来尝试一下利用链表来做栈的可能性。

    import java.util.List;
    
    /**
     * @author shkstart
     * @create 2019-11-29 13:03
     */
    public class LinkedListStack<E> implements Stack<E>{
    
        private LinkedList<E> list;
    
        public LinkedListStack() {
            list = new LinkedList<E>();
        }
    
        @Override
        public int getSize() {
            return getSize();
        }
    
        @Override
        public void push(E e) {
            list.addFirst(e);
        }
    
        @Override
        public boolean isEmpty() {
            return isEmpty();
        }
    
        @Override
        public E pop() {
            return list.removeFirst();
        }
    
        @Override
        public E peek() {
            return list.getFirst();
        }
    
        @Override
        public String toString(){
            StringBuilder res = new StringBuilder();
            res.append("stack:top");
            res.append(list);
            return res.toString();
        }
    
        public static void main(String[] args) {
            LinkedListStack<Integer> stack = new LinkedListStack<Integer>();
    
            for (int i = 0; i < 5; i++) {
                stack.push(i);
                System.out.println(stack);
            }
    
            stack.pop();
            System.out.println(stack);
        }
    }
    

    做完了栈,同样的 我们试验一下利用链表实现队列。

     private class Node {
    
            public E e;
            public Node next;
    
            public Node(E e, Node next) {
                this.e = e;
                this.next = next;
            }
    
            public Node(E e) {
                this(e, null);
            }
    
            public Node() {
                this(null, null);
            }
    
            @Override
            public String toString() {
                return e.toString();
            }
    
        }
    
        private Node tail, head;
    
        private int size;
    
        public LinkedListQueue(Node tail, Node head, int size) {
            this.tail = null;
            this.head = null;
            this.size = 0;
        }
    
        public LinkedListQueue() {
        }
    
        @Override
        public int getSize() {
            return getSize();
        }
    
        @Override
        public boolean isEmpty() {
            return isEmpty();
        }
    
        @Override
        public void enqueue(E e) {
            if (tail.next == null) {
                Node node = new Node(e);
                tail = head;
            } else {
                tail.next = new Node(e);
                tail = tail.next;
            }
            size++;
        }
    
        @Override
        public E dequeue() {
    
            if (isEmpty()) {
                throw new IllegalArgumentException("dequeue出错!");
            }
    
            Node ret = head;
            head = head.next;
            ret.next = null;
            if (head == null) {
                tail = head;
            }
            size--;
            return ret.e;
        }
    
        @Override
        public E getFront() {
            if (isEmpty()) {
                throw new IllegalArgumentException("Queue is empty");
            }
            return head.e;
        }
    
        @Override
        public String toString() {
            StringBuilder builder = new StringBuilder();
            builder.append("Queue:");
            builder.append("front [");
            Node cur = head;
            while (cur != null) {
                cur = cur.next;
            }
            builder.append("Null tail");
            return builder.toString();
    
        }
    
    
        public static void main(String[] args) {
    LinkedListQueue<Integer> LinkedListQueue = new LinkedListQueue<Integer>();
    for (int i = 0; i < 10; i++) {
    LinkedListQueue.enqueue(i);
    System.out.println(LinkedListQueue);
    if (i % 3 == 2) {
    LinkedListQueue.dequeue();
    System.out.println(LinkedListQueue);
                }
            }
        }

    在这里的链表我们写了尾指针!

  • 相关阅读:
    扩充Visual Studio 功能
    如何分层啊?
    DirectXInput
    关于分享
    消息机制
    C# 开启一个新进程,IE,打开一个URL,第一次总失败,刷新一下就好了
    远程调试IIS服务器的ASP.NET2.0网站
    IIS 用户 NT AUTHORITY\NETWORK SERVICE 登录失败解决方法
    SharePoint 2010微软Technet讲座第一讲笔记(2011年3月9日发布)
    IIS 未能加载文件或程序集 system.web.extensions解决方法
  • 原文地址:https://www.cnblogs.com/xiaobaoa/p/11960642.html
Copyright © 2020-2023  润新知