[Data structure] Linear table (Introduction to the concept of linear table | Sequential storage structure / chained storage structure | Sequential storage structure - Sequence table List | Sequence table ArrayList source code analysis )





1. Introduction to the concept of linear table



A linear table is a data set composed of a set of elements arranged in order ;


There are two storage structures for linear tables:

  • Sequential storage structure: the data stored in memory is continuous , such as: array;
  • Linked storage structure: the data stored in memory is discontinuous , such as: linked list;

In the linear table

  • Except for the first element , each element has a unique predecessor element;
  • Each element except the last has a unique successor element;

All elements form a linear structure.





2. Sequential storage structure - sequence table List



The sequential storage structure is the sequence table List;

Sequential storage structure:

  • Memory contiguous: Sequential storage structure uses contiguous memory space in memory to store elements in the linear table.
  • Index access: In a sequential storage structure, data elements are sequentially stored in a continuous address space in memory in a specific order, and elements can be accessed through indexes. The index is the memory address;
  • Sequential storage structure (sequence table) example:
    • array
    • ArrayList , which is also implemented internally by an array;

Sequence table advantages:

  • Random access: through the index subscript, you can directly access the elements at the specified location in the memory, and the time complexity is O(1);
  • High storage efficiency: no need to consume additional space to define pointers to other element storage, only the storage space of the element itself is required.

Disadvantages of sequence table:

  • Insertion and deletion are inefficient: In a sequential storage structure, insertion and deletion operations need to move all elements as a whole, and the time complexity is O(n);
  • Fixed storage space: The array needs to specify a fixed size when it is created, and the size cannot be changed after creation;

Sequence table code example: the sequence table is directly stored in the array;

class Students {
    
    
	Student[20];
	int size;
}




3. Sequence table ArrayList source code analysis



ArrayList in Java is a sequence table, the source code of which is analyzed below;

ArrayList source code address: https://www.androidos.net.cn/android/9.0.0_r8/xref/libcore/ojluni/src/main/java/java/util/ArrayList.java

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
    
    
    private static final long serialVersionUID = 8683452581122892189L;

    /**
     * 默认初始容量。
     */
    private static final int DEFAULT_CAPACITY = 10;

    /**
     * 用于空实例的共享空数组实例。
     */
    private static final Object[] EMPTY_ELEMENTDATA = {
    
    };

    /**
     * 用于默认大小的空实例的共享空数组实例。我们
     * 将其与EMPTY_ELEMENTDATA区分开来,以了解何时膨胀多少
     * 添加第一个元素。
     */
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {
    
    };

    /**
     * 存储ArrayList元素的数组缓冲区。
     * ArrayList的容量就是这个数组缓冲区的长度。任何
     * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
     * 将在添加第一个元素时扩展为DEFAULT_CAPACITY。
     */
    transient Object[] elementData; // 非私有以简化嵌套类访问

    /**
     * 数组列表的大小(包含的元素数量)。
     *
     * @serial
     */
    private int size;
}

The default initial capacity of ArrayList is int DEFAULT_CAPACITY = 10, if the constructor without any parameters is called, the default initial capacity is 10;

    /**
     * 构造一个初始容量为10的空列表。
     */
    public ArrayList() {
    
    
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

In the ArrayList # add method, the function is called to handle whether the size of the array is sufficient;ensureCapacityInternal

Call elementData[size++] = ethe code to add element e to the end of the array;

    /**
     * Appends the specified element to the end of this list.
     *
     * @param e element to be appended to this list
     * @return <tt>true</tt> (as specified by {@link Collection#add})
     */
    public boolean add(E e) {
    
    
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

In the ensureCapacityInternal function, the ensureExplicitCapacity function is called,

    private void ensureCapacityInternal(int minCapacity) {
    
    
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
    
    
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }

        ensureExplicitCapacity(minCapacity);
    }

In the ensureExplicitCapacity function, the grow function is called , which is the function to increase the capacity of ArrayList;

    private void ensureExplicitCapacity(int minCapacity) {
    
    
        modCount++;

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

In the grow function, a new array is created, and the data in the original array is copied to the new array;

    /**
     * 增加容量以确保它至少可以容纳最小容量参数指定的元素数量。
     *
     * @param minCapacity 所需的最小容量
     */
    private void grow(int minCapacity) {
    
    
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

The minimum capacity above is the current size + 1;


If you want to insert an element to a specified position, you must first copy the first index elements of the current array, then copy the element to be inserted, and finally copy the element after the index in the original array;

It involves two copies, and the operation process is very troublesome;

    /**
     * 将指定元素插入此列表中的指定位置。
     * 将当前在该位置的元素(如果有的话)和任何后续元素向右移动(在它们的索引上加1)。
     *
     * @param index 要插入指定元素的索引
     * @param element 要插入的元素
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public void add(int index, E element) {
    
    
        rangeCheckForAdd(index);

        ensureCapacityInternal(size + 1);  // Increments modCount!!
        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index);
        elementData[index] = element;
        size++;
    }

The function of the following code is to copy the elementData source array, the element starting from the index position, to the index + 1 position of the elementData destination array, copying size - index elements, which is equivalent to moving the elements starting from the index of the elementData array backward a location;

        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index);

System.arraycopy function prototype:

    public static native void arraycopy(Object src,  int  srcPos,
                                        Object dest, int destPos,
                                        int length);

Call the ArrayList # remove function to delete an element, which is to move the elements after the index forward by one position;

    public E remove(int index) {
    
    
        rangeCheck(index);

        modCount++;
        E oldValue = elementData(index);

        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--size] = null; // clear to let GC do its work

        return oldValue;
    }

The function of the following code is to copy the elementData source array, the element starting from index + 1, to the index position of the elementData destination array, and copy numMoved elements, which is equivalent to moving the elements starting from index of the elementData array one position forward ;

            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);

Guess you like

Origin blog.csdn.net/han1202012/article/details/130716313