美文网首页数据结构与算法
线性表的顺序存储

线性表的顺序存储

作者: 暮想sun | 来源:发表于2019-12-16 22:38 被阅读0次

    优点:

    1.无须为表示表中元素之间的逻辑关系二增加额外的存储空间
    2.可以快速地存取表中任一位置的元素

    缺点:

    1.插入和删除需要移动大量元素
    2.当线性表长度变化较大时,难以确定存储空间的容量
    3.造成存储空间的'碎片'

    初始化构造函数:

        /**
         * 默认初始化数组大小
         */
        private static final int DEFAULT_CAPACITY = 10;
    
        /**
         * 空数组
         */
        private static final Object[] EMPTY_ELEMENT_DATA = {};
    
        /**
         * 数组
         */
        private Object[] elementData;
    
        private int size;
    
        public OrderList() {
            this.elementData = EMPTY_ELEMENT_DATA;
        }
    
        public OrderList(int initialCapacity) {
            if (initialCapacity == 0) {
                elementData = EMPTY_ELEMENT_DATA;
            } else if (initialCapacity > 0) {
                elementData = new Object[initialCapacity];
            } else {
                throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);
            }
        }
    
        public OrderList(Collection<? extends E> c) {
            elementData = c.toArray();
    
            if ((size = elementData.length) != 0) {
                if (elementData.getClass() != Object[].class) {
                    elementData = Arrays.copyOf(elementData, size, Object[].class);
                }
            } else {
                elementData = EMPTY_ELEMENT_DATA;
            }
    
        }
    

    元素个数:

    public int size() {
            return size;
        }
    

    判断是否为空:

        public Boolean isEmpty() {
            return size == 0;
        }
    

    获取元素下标:

        public int indexOf(Object o) {
            //区分null,相等则返回对应下标。否则返回-1,因为数组下标从0开始
            if (o == null) {
    
                for (int i = 0; i < size; i++) {
                    if (elementData[i] == null) {
                        return i;
                    }
                }
            } else {
                for (int i = 0; i < size; i++) {
                    if (o.equals(elementData[i])) {
                        return i;
                    }
                }
    
            }
            return -1;
        }
    

    判断是否包含某个元素:

        public Boolean contains(Object o) {
            return indexOf(o) >= 0;
        }
    

    获取指定下标数据:

     public Object get(int index) {
            //判断下标是否越界
            if (index < 0 || index > size) {
                throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
            }
            return elementData[index];
        }
    

    插入:

        public void add(E e) {
            //判断是否需要扩容
            ensureCapacityInternal(size + 1);
    
            //将e赋值给当前size, 再执行size+1
            elementData[size++] = e;
        }
    
        private void ensureCapacityInternal(int minCapacity) {
            //判断是否为空数组
            if (elementData == EMPTY_ELEMENT_DATA) {
                //空数组,则确定需要确认的数组大小
                minCapacity = Math.min(DEFAULT_CAPACITY, minCapacity);
            }
    
            //如果数据大小,比当前数据大小大,则需要扩容
            if (minCapacity - elementData.length > 0) {
                grow(minCapacity);
            }
        }
    
        private void grow(int minCapacity) {
            int oldCapacity = elementData.length;
            int newCapacity = oldCapacity + (oldCapacity >> 1);
    
            //如果扩容一次的大小不满足最小需要扩容的大小
            if (newCapacity < minCapacity) {
                newCapacity = minCapacity;
            }
    
            //赋值数组
            elementData = Arrays.copyOf(elementData, newCapacity);
        }
    

    指定下标插入:

        public void add(int index, E e) {
            //判断下标是否越界
            if (index > size || index < 0) {
                throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
            }
    
            //判断是否需要扩容
            ensureCapacityInternal(size + 1);
            
            //数组copy,index以及后的数据需要向后移动
            System.arraycopy(elementData, index, elementData, index + 1, size - index);
            elementData[index] = e;
            size++;
        }
    

    删除:

       public Boolean remove(Object o) {
            //判断元素是否为空,空与非空,判断元素相等有区别。相等则根据下标删除
            if (o == null) {
                for (int i = 0; i < size; i++) {
                    if (elementData[i] == null) {
                        //删除对应下标数据
                        fastRemove(i);
                        return true;
    
                    }
                }
            } else {
                for (int i = 0; i < size; i++) {
                    if (o.equals(elementData[i])) {
                        //删除对应下标数据
                        fastRemove(i);
                        return true;
                    }
                }
            }
    
            return false;
        }
        private void fastRemove(int index) {
            //需要移动的数据,index下标删除。index+1以及以后的数据,需要向前移动
            int numMoved = size - 1 - index;
            if (numMoved > 0) {
                System.arraycopy(elementData, index + 1, elementData, index, numMoved);
            }
    
            //删除元素置空
            elementData[--size] = null;
        }
    

    指定下标删除:

        public void remove(int index) {
    
            //判断下标是否越界
            if (index < 0 || index > size) {
                throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
            }
            fastRemove(index);
        }
    

    清空:

        public void clear() {
            //引用指向空,gc会清除内存数据
            for (int i = 0; i < size; i++) {
                elementData[i] = null;
            }
            size = 0;
        }
    

    相关文章

      网友评论

        本文标题:线性表的顺序存储

        本文链接:https://www.haomeiwen.com/subject/pbfjnctx.html