用基础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\n", 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();
    }
}

 

posted @ 2021-04-02 15:45  Tom-shushu  阅读(120)  评论(0编辑  收藏  举报