zoukankan      html  css  js  c++  java
  • 手写数据结构-动态数组列表

    1.数组基础

    数组最一种存放数据的线性数据结构 ,最原始的数组是一种静态数组,需要声明数组的容量,一旦new出来数组对象大小不可改变,可以通过索引来进行数据的增删改查。我们可以通过对静态数组的二次封装来进行改进成动态数组。

    • 数组最大的优点:快速查询。

    • 数组最好用于“索引有语意”的情况。

    • 但并非所有有有语意的索引都适用于数组。 例如当用数组存放人员时,用身份证号来充当索引,此时能够区别人员,但身份证号太长,极大浪费内存空间得不偿失。

    • 数组也可以处理索引没有语意的情况。

    2.手写基于静态数组的动态数组链表(可对比与java中的ArrayList)
    package com.tc.javabase.datastructure.array;
    
    
    import java.util.Arrays;
    
    /**
     * @Classname ArrayList
     * @Description 动态列表  对静态数组的二次封装
     *
     * 时间复杂度分析:
     *        增加一个元素
     *        在数组的首位增加一个元素       O(n)
     *        在数组的末尾增加一个元素       O(1)
     *        在指定位置的下标增加一个元素    O(n)
     *
     *        查询元素
     *        查询首位元素        O(1)
     *        查询末尾元素        O(1)
     *        查询指定下标元素    O(1)
     *        是否包含该元素      O(n)
     *        查询元素的下标       O(n)
     *
     *        删除一个元素
     *        删除头元素         O(n)
     *        删除尾元素         O(1)
     *        删除指定下标元素      O(n)
     *
     *        更新一个元素
     *        更新头元素     O(1)
     *        更新尾元素     O(1)
     *        更新指定元素    O(1)
     *
     *   综上所述:
     *   增:O(n)  addLast(): O(1)
     *   删:O(n)  removeLast(): O(1)
     *   改:知道索引: O(1)  不知道索引: O(n)
     *   查: 知道索引: O(1)  不知道索引: O(n)
     *
     *    所以用动态列表这种数据结构 最好用于索引有语义的情况,适合做查询和更新操作(在知道索引的情况下)
     *    时间复杂度均为O(1).
     *
     * @Date 2020/7/15 19:53
     * @Created by zhangtianci
     */
    public class ArrayList<E> {
        private E[] data;
        private int size;
    
        /**
         * 默认构造函数
         * 初始数组容量为8
         */
        public ArrayList() {
            this.data = (E[]) new Object[8];
            this.size = 0;
        }
    
        public ArrayList(int capacity) {
            this.data = (E[]) new Object[capacity];
            this.size = 0;
        }
    
        public ArrayList(E[] arr){
            data = (E[])new Object[arr.length];
            for(int i = 0 ; i < arr.length ; i ++)
                data[i] = arr[i];
            size = arr.length;
        }
    
    
        /**
         * 增加一个元素
         * 在数组的首位增加一个元素
         * 在数组的末尾增加一个元素
         * 在指定位置的下标增加一个元素
         */
    
        /**
         * 在数组的首位增加一个元素
         *
         * 时间复杂度:O(n)
         */
        public void addFirst(E e) {
            add(0, e);
        }
    
        /**
         * 在数组的末尾增加一个元素
         *
         * 时间复杂度:O(1)
         */
        public void addLast(E e) {
            //考虑边界情况
            //当数组已经装满时
    //        if (size == getArrayLength()){
    //            throw new IllegalArgumentException("数组已经装满,不能够继续添加元素!");
    //        }
    //
    //        array[size] = e;
    //        size++;
    
    
            //复用方法add(int index,int e)
            add(size, e);
        }
    
        /**
         * 在指定位置的下标增加一个元素
         *
         *
         * 时间复杂度:O(n)
         * @param index
         * @param e
         */
        public void add(int index, E e) {
            //考虑边界情况
            //1.当数组已经装满时
    //        if (size == getArrayLength()){
    //            throw new IllegalArgumentException("数组已经装满,不能够继续添加元素!");
    //        }
    
            //2.指定的下标不合法 index < 0 || index >= getArrayLength() || index > size
            if (index < 0 || index > size) {
                throw new IllegalArgumentException("指定下标不合法!");
            }
    
            // 扩容
            if (size == getCapacity()) {
                resize(data.length * 2);
            }
    
            for (int i = size - 1; i >= index; i--) {
                data[i + 1] = data[i];
            }
            data[index] = e;
            size++;
        }
    
        private void resize(int capacity) {
            E[] newData = (E[]) new Object[capacity];
            for (int i = 0; i < size; i++) {
                newData[i] = data[i];
            }
            data = newData;
        }
    
    
        /**
         * 查询元素
         * 查询首位元素
         * 查询末尾元素
         * 查询指定下标元素
         */
    
        /**
         * 查询首位元素
         *
         * 时间复杂度:O(1)
         * @return
         */
        public E getFirst() {
            return get(0);
        }
    
        /**
         * 查询末尾元素
         *
         * 时间复杂度:O(1)
         * @return
         */
        public E getLast() {
            return get(size - 1);
        }
    
        /**
         * 查询指定下标元素
         *
         * 时间复杂度:O(1)
         * @param index
         * @return
         */
        public E get(int index) {
            //考虑边界情况
            //  指定下标不合法 index < 0 || index >= size
            if (index < 0 || index >= size) {
                throw new IllegalArgumentException(" 指定下标不合法!");
            }
            return data[index];
        }
    
        /**
         * 删除一个元素
         * 删除头元素
         * 删除尾元素
         * 删除指定下标元素
         */
    
        /**
         * 删除头元素
         *
         * 时间复杂度:O(n)
         */
        public E removeFirst() {
            return remove(0);
        }
    
        /**
         * 删除尾元素
         *
         * 时间复杂度:O(1)
         */
        public E removeLast() {
            return remove(size - 1);
        }
    
        /**
         * 删除指定下标元素
         *
         *时间复杂度:O(n)
         * @param index
         */
        public E remove(int index) {
            //考虑边界情况
            //指定下标不合法  index < 0 || index >= size
            if (index < 0 || index >= size) {
                throw new IllegalArgumentException("指定下标不合法");
            }
    
            E e = get(index);
            for (int i = index; i < size - 1; i++) {
                data[i] = data[i + 1];
            }
            size--;
            data[size] = null;
    
            //缩容
            if (size == data.length / 4 && data.length / 2 != 0) {
                resize(data.length / 2);
            }
            return e;
        }
    
        /**
         * 更新一个元素
         * 更新头元素
         * 更新尾元素
         * 更新指定元素
         *
         */
    
        /**
         * 更新头元素
         *
         * 时间复杂度:O(1)
         * @param e
         */
        public void setFirst(E e) {
            set(0, e);
        }
    
        /**
         * 更新尾元素
         *
         * 时间复杂度:O(1)
         * @param e
         */
        public void setLast(E e) {
            set(size - 1, e);
        }
    
        /**
         * 更新指定元素
         *
         * 时间复杂度:O(1)
         * @param index
         * @param e
         */
        public void set(int index, E e) {
            //考虑边界
            //指定下标不合法  index < 0 || index >= size
            if (index < 0 || index >= size) {
                throw new IllegalArgumentException("指定下标不合法 !");
            }
            data[index] = e;
        }
    
    
        /**
         * 是否包含该元素
         *
         * 时间复杂度:O(n)
         */
        public boolean contain(E e) {
            for (int i = 0; i < size; i++) {
                if (data[i].equals(e)) {
                    return true;
                }
            }
            return false;
        }
    
        /**
         * 查询元素的下标
         *
         * 时间复杂度:O(n)
         */
        public int find(int e) {
            for (int i = 0; i < size; i++) {
                if (data[i].equals(e)) {
                    return i;
                }
            }
            return -1;
        }
    
        /**
         * 获得数组中的元素的个数
         *
         * @return
         */
        public int getSize() {
            return size;
        }
    
        /**
         * 获取数组的长度
         *
         * @return
         */
        public int getCapacity() {
            return data.length;
        }
    
    
        public boolean isEmpty(){
            return size == 0 ? true : false;
        }
    
        public void swap(int i, int j){
    
            if(i < 0 || i >= size || j < 0 || j >= size)
                throw new IllegalArgumentException("Index is illegal.");
    
            E t = data[i];
            data[i] = data[j];
            data[j] = t;
        }
    
        /**
         * 重写toString
         *
         */
        @Override
        public String toString() {
            return "ArrayList{" +
                    "array=" + Arrays.toString(data) +
                    ", size=" + size +
                    '}';
        }
    
    
    
    
        public static void main(String[] args) {
    
    
            int i = 1;
    
            while (i == 1){
    
            }
    
            /**
             *  测试添加一个元素
             */
            ArrayList<Integer> arrayList = new ArrayList(5);
            arrayList.addFirst(1);
            arrayList.addFirst(2);
            ;
            arrayList.addFirst(3);
            System.out.println(arrayList.toString());
            arrayList.add(2, 0);
            System.out.println(arrayList.toString());
            arrayList.addLast(99);
            System.out.println(arrayList.toString());
            arrayList.addLast(99);
            System.out.println(arrayList.toString());
    
    
            /**
             * 测试查询一个元素
             */
            System.out.println("first element: " + arrayList.getFirst());
            System.out.println("last element: " + arrayList.getLast());
            System.out.println("get element index of 1 :" + arrayList.get(1));
    
            /**
             * 测试删除一个元素
             */
            arrayList.removeFirst();
            arrayList.removeLast();
            arrayList.remove(1);
            arrayList.removeLast();
            System.out.println(arrayList.toString());
    
            /**
             * 测试更新一个元素
             */
            arrayList.setFirst(12);
            arrayList.setLast(13);
            arrayList.set(1, 55);
            System.out.println(arrayList.toString());
    
            /**
             * 测试是否包含该元素
             */
            System.out.println(arrayList.contain(12));
            System.out.println(arrayList.contain(55));
            System.out.println(arrayList.contain(515));
    
            /**
             * 测试返回元素的下标
             */
    
            System.out.println(arrayList.find(12));
            System.out.println(arrayList.find(55));
            System.out.println(arrayList.find(515));
        }
    }
    
  • 相关阅读:
    Struts2快速后台验证 使用
    Python发送邮件
    【Python】【Flask】前端调用后端方法
    后台参数验证的几种方式
    使用 jQuery 进行前端验证
    postman接口测试——笔记
    安全测试
    jQuery 是javascript的一个库(常用插件、处理器)
    javascript 的 事件类型(事件)
    JavaScript的 基本数据类型---对象
  • 原文地址:https://www.cnblogs.com/tc971121/p/13443572.html
Copyright © 2011-2022 走看看