• 用基础Array数组实现动态数组、链表、栈和队列


    代码地址: https://gitee.com/Tom-shushu/Algorithm-and-Data-Structure.git

    一、ArrayList自定义封装

    package com.zhouhong;
    /**
     * @ClassName: array
     * @Description: 二次封装自己的数组类
     * @Author: zhouhong
     * @Create: 2021-03-29 15:47
     **/
    public  class  Array <E> {
    
        private E[] data;
        private int size;
        // 构造函数,传入数组的容量 capacity 构造Array
        public Array(int capacity){
            data = (E[])new Object[capacity];
            size = 0;
        }
        // 无参构造函数,默认数组的容量 capacity = 10
        public  Array(){
            this(10);
        }
        // 获取数组实际长度
        public int getSize(){
            return size;
        }
        // 获取容量
        public int getCapacity(){
            return data.length;
        }
        // 返回数组是否为空
        public boolean isEmpty(){
            return size == 0;
        }
        // 数组最后添加 O(n)
        public void addLast(E e){
            add(size, e);
        }
        // 向数组头部添加元素 O(1)
        public void addFirst(E e){
            add(0, e);
        }
        // 获取某个位置上的元素 O(1)
        public E get(int index){
            if (index < 0 || index > size){
                throw new IllegalArgumentException("index必须大于等于0 ,并且小于等于数组长度size");
            }
            return data[index];
        }
        // 更新元素 O(1)
        void set(int index, E e){
            if (index < 0 || index >= size){
                throw new IllegalArgumentException("index必须大于等于0 ,并且小于等于数组长度size");
            }
            data[index] = e;
        }
        // 向指定位置添加元素 O(n)
        public void add(int index, E e){
            if (index < 0 || index > size){
                throw new IllegalArgumentException("index必须大于等于0 ,并且小于等于数组长度size");
            }
            // 数组已满:扩容
            if (size == data.length){
                // 扩容 2 倍
                resize(data.length * 2);
            }
            for (int i = size - 1; i >= index ; i--) {
                data[i + 1] = data[i];
            }
            data[index] = e;
            size ++;
        }
    
        // 查找数组中是否有元素e O(n)
        public boolean contains(E e){
            for (int i = 0; i < size; i++) {
                if (data[i].equals(e)){
                    return true;
                }
            }
            return false;
        }
        // 查找某个元素对应的索引(重复元素只返回一个索引) O(n)
        public int find(E e){
            for (int i = 0; i < size; i++) {
                if (data[i].equals(e)){
                    return i;
                }
            }
            return -1;
        }
        // 删除某个指定索引上的元素(直接覆盖、前移),返回删除的元素 O(n)
        public E  remove(int index){
            if (index < 0 || index >= size){
                throw new IllegalArgumentException("index必须大于等于0 ,并且小于等于数组长度size");
            }
            E result = data[index];
            for (int i = index; i < size; i++) {
                data[i] = data[i + 1];
            }
            size --;
            data[size] = null;
            // 当长度小于容量的 1/2 把容量自动缩小为原来长度的 1/2
            // 懒加载,当为1/4时缩容
            if (size == data.length >> 2 && data.length >> 1 != 0){
                resize(data.length / 2);
            }
    
            return result;
        }
        // 删除第一个元素 O(n)
        public E removeFirst(){
            return remove(0);
        }
        // 删除最后一个元素 O(1)
        public E removeLast(){
            return remove(size - 1);
        }
        // 如果数组中有某个元素,就删除(相同元素,只删除一个)
        public void removeElenent(E e){
            int index = find(e);
            if (index != -1){
                remove(index);
            }
        }
        // 扩容
        private void resize(int newCapacity){
            E[] newData = (E[]) new Object[newCapacity];
            for (int i = 0; i < size; i++) {
                newData[i] = data[i];
            }
            data = newData;
        }
    
        @Override
        public String toString() {
            StringBuilder result = new StringBuilder();
            result.append(java.lang.String.format("Array: size = %d, capacity = %d
    ", size, data.length));
            result.append('[');
            for (int i = 0; i < size; i++) {
                result.append(data[i]);
                if (i != size - 1){
                    result.append(", ");
                }
            }
            result.append(']');
            return result.toString();
        }
    }

    二、用我们自定义的动态数组实现队列

    package com.zhouhong;
    
    /**
     * @ClassName: array-queue
     * @Description: 基于数组的普通队列
     * @Author: zhouhong
     * @Create: 2021-03-30 23:55
     **/
    
    public class ArrayQueue<E> implements QueueInterface<E> {
        private Array<E> array;
    
        public ArrayQueue(int capacity){
            array = new Array<>(capacity);
        }
    
        public ArrayQueue(){
            array = new Array<>();
        }
    
        @Override
        public void enqueue(E e) {
            array.addLast(e);
        }
    
        @Override
        public E dequeue() {
            return array.removeFirst();
        }
    
        @Override
        public E getFront() {
            return array.getFirst();
        }
    
        @Override
        public int getSize() {
            return array.getSize();
        }
    
        public int getCapacity() {
            return array.getCapacity();
        }
    
        @Override
        public boolean isEmpty() {
            return array.isEmpty();
        }
    
        @Override
        public String toString(){
            StringBuilder res = new StringBuilder();
            res.append("Queue:");
            res.append("front [");
            for (int i = 0; i < array.getSize(); i++) {
                res.append(array.get(i));
                if (i != array.getSize() - 1){
                    res.append(", ");
                }
            }
            res.append("] tail");
            return res.toString();
        }
    
    }

    三、使用动态数组实现栈

    package com.zhouhong;
    
    /**
     * @ClassName: stack
     * @Description: 使用数组实现一个栈
     * @Author: zhouhong
     * @Create: 2021-03-30 22:37
     **/
    
    public class ArrayStack<E> implements StackInterface<E>{
    
        Array<E> array;
        public ArrayStack(int capacity){
            array = new Array<>(capacity);
        }
        public ArrayStack(){
            array = new Array<>();
        }
    
        @Override
        public int getSize() {
            return array.getSize();
        }
    
        @Override
        public boolean isEmpty() {
            return array.isEmpty();
        }
    
        @Override
        public void push(E e) {
            array.addLast(e);
        }
    
        @Override
        public E pop() {
            return array.removeLast();
        }
    
        @Override
        public E peek() {
            return array.getLast();
        }
        public int getCapacity(){
            return array.getCapacity();
        }
    
        @Override
        public String toString(){
            StringBuilder res = new StringBuilder();
            res.append("Stack:");
            res.append('[');
            for (int i = 0; i < array.getSize(); i++) {
                res.append(array.get(i));
                if (i != array.getSize() - 1){
                    res.append(", ");
                }
            }
            res.append("] top");
            return res.toString();
        }
    }

    四、链表常见操作实现

    package com.zhouhong;
    
    /**
     * @ClassName: linkedlist
     * @Description: 链表
     * @Author: zhouhong
     * @Create: 2021-03-31 15:25
     **/
    
    public class LinkedList<E> {
    
        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();
            }
        }
        //使用head,会使得add方法在向首部添加元素时找不到当前元素对应的前一个元素
        // private Node head;
        // 虚拟头结点
        private Node dummyHead;
        private int size;
    
        public LinkedList(){
            dummyHead = new  Node(null, null);
            size = 0;
        }
        // 获取链表中的元素的个数
        public int getSize(){
            return size;
        }
        // 返回链表是否为空
        public boolean isEmpty(){
            return size == 0;
        }
        // 在链表index中间添加元素
        public void add(E e, int index){
            if (index < 0 || index > size){
                throw new IllegalArgumentException("ADD failed, Illegal index.");
            }
            Node pre = dummyHead;
            // 遍历找到所要插入节点的前一个节点
            for (int i = 0; i < index; i++) {
                pre = pre.next;
            }
    //          Node node = new Node(e);
    //          node.next = pre.next;
    //          pre = node;
            pre.next = new Node(e, pre.next);
            size ++;
        }
        // 为链表头部添加元素
        public void addFirst(E e){
    //        Node node = new Node(e);
    //        node.next = head;
    //        head = node;
            add(e,0);
        }
        // 想链表末尾添加元素
        public void addLast(E e){
            add(e, size);
        }
        // 获得链表的第index 个位置的元素
        // 在链表中不是一个常用的操作,练习用
        public E get(int index){
            if (index < 0 || index >= size){
                throw new IllegalArgumentException("ADD 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 个位置的元素为e
        // 在链表中不是一个常用的操作,练习用
        public void set(int index, E e){
            if (index < 0 || index > size){
                throw new IllegalArgumentException("Update 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;
        }
        // 从链表中删除index位置的元素,返回待删除元素
        public E remove(int index){
            if (index < 0 || index > size){
                throw new IllegalArgumentException("remove failed, Illegal index.");
            }
            Node pre = dummyHead;
            // 遍历找到所要删除节点的前一个节点
            for (int i = 0; i < index; i++) {
                pre = pre.next;
            }
            Node node = pre.next;
            pre.next = node.next;
            node.next = null;
            size --;
            return node.e;
        }
        // 从链表中删除第一个元素,返回删除元素
        public E removeFirst(){
            return remove(0);
        }
        // 从链表中删除最后一个元素,返回删除元素
        public E removeLast(){
            return remove(size - 1);
        }
    
        @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();
        }
    }

    输了不可怕,大不了从头再来,我们还年轻---周红

  • 相关阅读:
    你应该知道的4个DSP开发支持库
    你应该知道的4个DSP开发支持库
    Andrew Ng机器学习课程6
    Andrew Ng机器学习课程6
    你应该掌握的四种参数估计技术
    你应该掌握的四种参数估计技术
    李老师教人生道理
    李老师教人生道理
    迟到的间隔年
    迟到的间隔年
  • 原文地址:https://www.cnblogs.com/Tom-shushu/p/14611002.html
Copyright © 2020-2023  润新知