Java data structure and algorithm sequence table

        The sequence table is a linear structure in which data elements are sequentially stored in a segment of storage units with consecutive physical addresses, generally using array storage. Complete data addition, deletion, search and modification on the array. The sequence table can generally be divided into: Static sequence table: use fixed-length array storage. Dynamic sequence table: use dynamically developed array storage. A static sequence table is useful when you know how much data you need to store. The fixed-length array of the static sequence table causes N to be large, and the space is too wasteful, and the less is not enough. In contrast, the dynamic sequence table is more flexible, and the size of the space is dynamically allocated according to the needs.

Next, let's implement a dynamic sequence table.

First, the interface to be implemented

 public class SeqList {
 
    // 打印顺序表 
    public void display() { }
 
    // 在 pos 位置新增元素 
    public void add(int pos, int data) { }
 
    // 判定是否包含某个元素 
    public boolean contains(int toFind) { return true; }
 
    // 查找某个元素对应的位置 
    public int search(int toFind) { return -1; }
 
    // 获取 pos 位置的元素 
    public int getPos(int pos) { return -1; }
 
    // 给 pos 位置的元素设为 value 
    public void setPos(int pos, int value) { }
 
    //删除第一次出现的关键字key 
    public void remove(int toRemove) { } 

    // 获取顺序表长度 
    public int size() { return 0; } 

    // 清空顺序表 
    public void clear() { }
}

Second, the realization of the interface

        1, build the frame of the table

        As you can see from the above picture, we need to create an array (int[] elem) and add elements to it by ourselves. At the same time, you also need to know the size of the array in this table. The size of the array is determined by yourself. Here, we assume that the initial capacity (int IntCapacity) is 10. Although we have opened up such a large table, not every array has elements in it. At this time, we need to know its real size, which is the effective size (int usedSize).

    public int[] elem;
    //有效的数据个数
    public int usedSize;
    //初始容量,且不能被改变
    public static final int intCapacity = 10;


    //创建对象并调用合适的构造方法
    public MyArrayList() {
        //创建一个初始容量为10个大小的数组对象
        this.elem = new int[intCapacity];
        this.usedSize = 0;
    }

       2. Print order table

        First, print the sequence table. Only after printing, we can know whether the subsequent interface implementation is correct. At the beginning, the content in the table is empty, so the printed table is naturally empty. Here, we assume that the table has content. We just need to traverse this table and that's it. It should be noted that to print the valid elements in this table, it is necessary to specify the termination condition of the traversal, whether it is IntCapacity or usedSize.

// 打印顺序表
    public void display() {

        int i  = 0;
        for(i = 0; i < this.usedSize; i++) {
            System.out.print(this.elem[i] + " ");
        }
        System.out.println();
        //System.out.print(Arrays.toString(this.elem));
    }

       3. Add an element at the pos position 

        Here, we need to consider: 1, how to achieve? 2. Is the input pos position within the valid range of this array? 3. Will this array be full? What should I do when it's full?

        We first consider how to implement this problem. After finding the pos position first, you need to move the element inside, leaving a position for the element to be inserted, otherwise direct insertion will overwrite the content of the pos position. So, to move the element behind pos. When moving, start from the last one, otherwise, moving from the pos position will still cause the problem of being overwritten. Once done, let usedSize++ do it.

        Next, consider questions 2 and 3. For question 2, pos is within the valid range and can be operated. This range is from subscript 0 to usedSizes - 1 subscript. Once out of this range, it is illegal and needs to be warned. You can use exceptions, or you can print. Question 3, we need to judge the full situation. When adding elements, the usedSize (effective length) is accumulating. When enough elements are added, the usedSize will be equal to the capacity length of the array. Here, is the condition for judging whether expansion is needed. At the same time, it should be noted that the initial capacity cannot be changed, so when expanding the capacity, it is necessary to copy the array to expand the capacity. Use the copyOf method in Arrays to copy the array and expand the capacity at the same time.

    //检查pos位置合法性
    private void checkPos(int pos) {

        if(pos < 0 || pos > this.usedSize) {
            throw new RuntimeException("pos位置不合法!");
        }
    }

    //检查数组是否满的情况
    private boolean isFull() {

        if(this.elem.length == this.usedSize) {
            return true;
        }
        return false;
    }

    // 在 pos 位置新增元素
    public void add(int pos, int data) {

        //pos位置合法性
        checkPos(pos);
        //检查数组是否满了
        if(isFull()) {
            this.elem = Arrays.copyOf(this.elem, 2 * this.elem.length);
        }
        //新增元素
        for(int i = this.usedSize - 1; i >= pos; i--) {
            this.elem[i + 1] = this.elem[i];
        }
        this.elem[pos] = data;
        this.usedSize++;
    }

        4. Determine whether an element is included

        This only needs to be traversed and then judged.        

// 判定是否包含某个元素
    public boolean contains(int toFind) {

        for(int i = 0; i < this.usedSize; i++) {
            if(this.elem[i] == toFind) {
                return true;
            }
        }
        return false;
    }

        5. Find the position corresponding to an element

        This only needs to be traversed and then judged. The validity check function has been written before, and it can be called directly.  

    // 查找某个元素对应的位置
    public int search(int toFind) {

        //合法性检查
        checkPos(toFind);
        for(int i = 0; i < this.usedSize; i++) {
            if(this.elem[i] == toFind) {
                return i;
            }
        }
        return -1;
    }

      6. Get the element at the pos position

        Questions to consider: 1. How to find? 2. Legality? 3. Is the table empty?

        Earlier, we wrote the function for judging the validity of pos, and here we only need to call it. Now let's solve problem 3. Why is it necessary to determine if the table is empty? The table is empty, indicating that its effective length is 0, that is, there are no elements in it to return, and there is no need to obtain them.

    //判断是否为空
    private boolean isEmpty() {
        return this.usedSize == 0;
    }

    // 获取 pos 位置的元素
    public int getPos(int pos) {

        //表是否为空
        if (isEmpty()) {
            //也可以进行打印
            throw new RuntimeException("表为空!");
        }
        //检查合法性
        if(pos < 0 || pos >= this.usedSize) {
            throw new RuntimeException("pos位置不合法!");
        }
        //获取元素
        return this.elem[pos];
    }

        7. Set the element at the pos position to value

        First check the validity, and then overwrite the value. Whether the table is empty needs to be judged.

    // 给 pos 位置的元素设为 value
    public void setPos(int pos, int value) {

        checkPos(pos);
        if(isFull()) {
            throw new RuntimeException("表为空!");
        }
        this.elem[pos] = value;
    }

       8. Delete the first occurrence of the keyword key 

        After deletion, let the effective length --.

    //删除第一次出现的关键字key
    public void remove(int toRemove) {

        int pos = search(toRemove);
        if(pos == -1) {
            System.out.println("未找到该值!");
            return;
        }
        for(int i = pos; i < this.usedSize - 1; i++) {
            this.elem[i] = this.elem[i + 1];
        }
        this.usedSize--;
    }

        9. Get the length of the sequence table

        The length of the sequence table is its effective length.

    // 获取顺序表长度
    public int size() {

        if (!isEmpty()) {
            return this.usedSize;
        }
        return 0;
    }

        10. Clear the sequence table

        Let the effective length be 0.

    // 清空顺序表
    public void clear() {

        this.usedSize = 0;
    }

3. All codes and results

import java.util.Arrays;

/**
 * @author: Naion
 * @create: 2021-12-26 14:56
 **/

public class MySeqlist {

    //定义一个顺序表
    private int[] elem;
    private int usedSize;
    private int intCapacity = 10;

    //调用合适的构造方法
    public MySeqlist() {
        //定义大小
        this.elem = new int[intCapacity];
        this.usedSize = 0;
    }

    // 打印顺序表
    public void display() {

        int i = 0;
        for(i = 0; i < this.usedSize; i++) {
            System.out.print(this.elem[i] + " ");
        }
        System.out.println();
    }

    //检查pos位置合法性
    private void checkPos(int pos) {

        if(pos < 0 || pos > this.usedSize) {
            throw new RuntimeException("pos位置不合法!");
        }
    }

    //检查数组是否满的情况
    private boolean isFull() {

        if(this.elem.length == this.usedSize) {
            return true;
        }
        return false;
    }

    // 在 pos 位置新增元素
    public void add(int pos, int data) {

        //pos位置合法性
        checkPos(pos);
        //检查数组是否满了
        if(isFull()) {
            this.elem = Arrays.copyOf(this.elem, 2 * this.elem.length);
        }
        //新增元素
        for(int i = this.usedSize - 1; i >= pos; i--) {
            this.elem[i + 1] = this.elem[i];
        }
        this.elem[pos] = data;
        this.usedSize++;
    }

    // 判定是否包含某个元素
    public boolean contains(int toFind) {

        for(int i = 0; i < this.usedSize; i++) {
            if(this.elem[i] == toFind) {
                return true;
            }
        }
        return false;
    }

    // 查找某个元素对应的位置
    public int search(int toFind) {

        //合法性检查
        checkPos(toFind);
        for(int i = 0; i < this.usedSize; i++) {
            if(this.elem[i] == toFind) {
                return i;
            }
        }
        return -1;
    }

    //判断是否为空
    private boolean isEmpty() {
        return this.usedSize == 0;
    }

    // 获取 pos 位置的元素
    public int getPos(int pos) {

        //表是否为空
        if (isEmpty()) {
            throw new RuntimeException("表为空!");
        }
        //检查合法性
        if(pos < 0 || pos >= this.usedSize) {
            throw new RuntimeException("pos位置不合法!");
        }
        //获取元素
        return this.elem[pos];
    }

    // 给 pos 位置的元素设为 value
    public void setPos(int pos, int value) {

        checkPos(pos);
        if(isFull()) {
            throw new RuntimeException("表为空!");
        }
        this.elem[pos] = value;
    }

    //删除第一次出现的关键字key
    public void remove(int toRemove) {

        int pos = search(toRemove);
        if(pos == -1) {
            System.out.println("未找到该值!");
            return;
        }
        for(int i = pos; i < this.usedSize - 1; i++) {
            this.elem[i] = this.elem[i + 1];
        }
        this.usedSize--;
    }

    // 获取顺序表长度
    public int size() {

        if (!isEmpty()) {
            return this.usedSize;
        }
        return 0;
    }
    // 清空顺序表
    public void clear() {

        this.usedSize = 0;
    }
}
/**
 * @author: Naion
 * @create: 2021-12-26 14:55
 **/

public class test_12_26_01 {

    public static void main(String[] args) {

        MySeqlist myseqlist = new MySeqlist();
        for(int i = 0; i < 10; i++) {
            myseqlist.add(i, i);
        }
        myseqlist.display();
        System.out.println("======");
        myseqlist.add(1, 3);
        myseqlist.display();
        System.out.println("======");
        System.out.println(myseqlist.contains(3));
        System.out.println("======");
        System.out.println(myseqlist.search(3));
        System.out.println("======");
        System.out.println(myseqlist.getPos(1));
        System.out.println("======");
        myseqlist.setPos(1, 0);
        myseqlist.display();
        System.out.println("======");
        myseqlist.remove(0);
        myseqlist.display();
        System.out.println("======");
        System.out.println(myseqlist.size());
        System.out.println("======");
        myseqlist.clear();
        myseqlist.display();
    }
}

Fourth, the problem of the sequence table

1. Insertion and deletion in the middle/head of the sequence table, the time complexity is O(N)

2. To increase capacity, you need to apply for new space, copy data, and release old space. There will be some consumption.

3. The capacity expansion is generally a 2-fold increase, and there is bound to be a certain amount of space waste. For example, the current capacity is 100, and the capacity is increased to 200 when it is full. We continue to insert 5 data, and no data is inserted later, so 95 data spaces are wasted.

These problems require a singly linked list to solve. 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324125939&siteId=291194637