第二章 线性表-顺序表

提出问题

顺序表,它是基于数组的对线性表的一种实现。

抽象数据类型

很多时间数组并不能满足我们的需求,比如,所以基于数组要进行封装,也就是我们的顺序表

getSize()

 

 

代码实现


public class ArrayList {
    /** 使用数组存储数据 */
    private int[] data;
    /** size记录当前数组data中实际元素个数 */
    private int size;

    public ArrayList(int capacity) {
        this.data =  new int[capacity];
        this.size = 0;
    }
    public ArrayList() {
        this(10);
    }

    /**
     * 获取顺序表中元素个数
     * @return
     */
    public int getSize(){
        return this.size;
    }

    /**
     * 获取顺序表容器
     * @return
     */
    public int getCapacity(){
        return this.data.length;
    }

    /**
     * 判断顺序表是否为空
     * @return
     */
    public boolean isEmpty(){
        return size == 0;
    }


    /**
     * 向顺序表中index位置上添加元素
     * @param index
     * @param e
     */
    public void add(int index, int e){
        if (index < 0 || index > this.size){
            throw new IllegalArgumentException("Add failed. Require index >= 0 and index < size");
        }
        if (this.size == this.data.length){
            throw new IllegalArgumentException("Add failed. Array is full.");
        }
        for (int i = size - 1; i >= index; i--){
            this.data[i + 1] = data[i];
        }
        this.data[index] = e;
        this.size ++;
    }

    /**
     * 在所有元素后添加一个新元素
     * @param e
     */
    public void addLast(int e){
        /*
        if (this.size == this.data.length){
            throw new IllegalArgumentException("Add failed. Array is full.");
        }
        this.data[size] = e;
        this.size ++;
        */
        this.add(size, e);
    }

    /**
     * 在所有元素前添加一个新元素
     * @param e
     */
    public void addFirst(int e){
        this.add(0, e);
    }

    /**
     * 获取指定索引位置上的元素e
     * @param index
     * @return
     */
    public int get(int index){
        if (index < 0 || index >= size){
            throw new IllegalArgumentException("Get failed. Index is illegal");
        }
        return this.data[index];
    }

    /**
     * 修改指定索引位置上的元素e
     * @param e
     * @param index
     */
    public void set(int e, int index){
        if (index < 0 || index >= size){
            throw new IllegalArgumentException("Get failed. Index is illegal");
        }
        this.data[index] = e;
    }

    /**
     * 查询顺序表中是否包含指定的元素e
     * @param e
     * @return
     */
    public boolean contains(int e){
        for (int i = 0; i < size; i++){
            if (data[i] == e){
                return true;
            }
        }
        return false;
    }

    /**
     * 查找顺序表中元素e所在的索引,如果元素e不存在返回-1
     * @param e
     * @return
     */
    public int find(int e){
        for (int i = 0; i < size; i++){
            if (data[i] == e){
                return i;
            }
        }
        return -1;
    }

    /**
     * 删除顺序表中index位置上的元素,返回删除的元素
     * @param index
     * @return
     */
    public int remove(int index){
        if (index < 0 || index >= size){
            throw new IllegalArgumentException("Remove failed. Index is illegal");
        }
        int ret  = this.data[index];
        for (int i = index + 1; i < this.size; i++){
            this.data[i - 1] = this.data[i];
        }
        this.size --;
        return ret;
    }

    /**
     * 删除顺序表中第一个元素,返回删除的元素
     * @return
     */
    public int removeFirst(){
        return this.remove(0);
    }

    /**
     * 删除顺序表中最后一个元素,返回删除的元素
     * @return
     */
    public int removeLast(){
        return this.remove(this.size -1);
    }

    /**
     * 删除指定的元素
     * @param e
     */
    public boolean removeElement(int e){
        int index = this.find(e);
        if (index != -1){
            this.remove(index);

        }
        return false;
    }

    @Override
    public String toString() {
        StringBuffer rs = new StringBuffer();
        rs.append(String.format("Array List: size = %d, capacity = %d\n", this.size, this.data.length));
        rs.append("[");
        for (int i = 0; i < this.size; i ++){
            rs.append(this.data[i]);
            if (i != size -1){
                rs.append(", ");
            }
        }
        rs.append("]");
        return rs.toString();
    }
}

 

代码优化:

加入范型支持

以上我们实现的顺序表只能存储int类型的数据,为了让我们以上实现的顺序表能够支持存储更多的数据类型,加入范型


public class ArrayList {
    /** 使用数组存储数据 */
    private T[] data;
    /** size记录当前数组data中实际元素个数 */
    private int size;

    public ArrayList(int capacity) {
        this.data = (T[]) new Object[capacity];
        this.size = 0;
    }
    public ArrayList() {
        this(10);
    }

    /**
     * 获取顺序表中元素个数
     * @return
     */
    public int getSize(){
        return this.size;
    }

    /**
     * 获取顺序表容器
     * @return
     */
    public int getCapacity(){
        return this.data.length;
    }

    /**
     * 判断顺序表是否为空
     * @return
     */
    public boolean isEmpty(){
        return size == 0;
    }


    /**
     * 向顺序表中index位置上添加元素
     * @param index
     * @param e
     */
    public void add(int index, T e){
        if (index < 0 || index > this.size){
            throw new IllegalArgumentException("Add failed. Require index >= 0 and index < size");
        }
        // 如果当前data数组元素个数为整个数组容量时,进行扩容
        if (this.size == this.data.length){
            resize(2 * this.data.length);
        }
        for (int i = size - 1; i >= index; i--){
            this.data[i + 1] = data[i];
        }
        this.data[index] = e;
        this.size ++;
    }


    /**
     * 在所有元素后添加一个新元素
     * @param e
     */
    public void addLast(T e){
        this.add(size, e);
    }

    /**
     * 在所有元素前添加一个新元素
     * @param e
     */
    public void addFirst(T e){
        this.add(0, e);
    }

    /**
     * 获取指定索引位置上的元素e
     * @param index
     * @return
     */
    public T get(int index){
        if (index < 0 || index >= size){
            throw new IllegalArgumentException("Get failed. Index is illegal");
        }
        return this.data[index];
    }

    /**
     * 修改指定索引位置上的元素e
     * @param e
     * @param index
     */
    public void set(T e, int index){
        if (index < 0 || index >= size){
            throw new IllegalArgumentException("Get failed. Index is illegal");
        }
        this.data[index] = e;
    }

    /**
     * 查询顺序表中是否包含指定的元素e
     * @param e
     * @return
     */
    public boolean contains(T e){
        for (int i = 0; i < size; i++){
            if (data[i] == e){
                return true;
            }
        }
        return false;
    }

    /**
     * 查找顺序表中元素e所在的索引,如果元素e不存在返回-1
     * @param e
     * @return
     */
    public int find(T e){
        for (int i = 0; i < size; i++){
            if (data[i].equals(e) ){
                return i;
            }
        }
        return -1;
    }

    /**
     * 删除顺序表中index位置上的元素,返回删除的元素
     * @param index
     * @return
     */
    public T remove(int index){
        if (index < 0 || index >= size){
            throw new IllegalArgumentException("Remove failed. Index is illegal");
        }
        T ret  =  this.data[index];
        for (int i = index + 1; i < this.size; i++){
            this.data[i - 1] = this.data[i];
        }
        this.size --;
        this.data[size] = null;
        // 如果当前data数组元素个数为整个数组容量的1/2时,进行缩容
        if (this.size == this.data.length / 2){
            resize(this.data.length / 2);
        }
        return ret;
    }

    /**
     * 删除顺序表中第一个元素,返回删除的元素
     * @return
     */
    public T removeFirst(){
        return this.remove(0);
    }

    /**
     * 删除顺序表中最后一个元素,返回删除的元素
     * @return
     */
    public T removeLast(){
        return this.remove(this.size -1);
    }

    /**
     * 删除指定的元素
     * @param e
     */
    public boolean removeElement(T e){
        int index = this.find(e);
        if (index != -1){
            this.remove(index);

        }
        return false;
    }

    /**
     * 返回最后一个元素
     * @return
     */
    public T getLast(){
        return this.get(this.size -1);
    }

    /**
     * 返回第一个元素
     * @return
     */
    public T getFirst(){
        return this.get(0);
    }


    private void resize(int newCapacity) {
        T[] newData = (T[]) new Object[newCapacity];
        for (int i = 0; i < this.size; i++){
            newData[i] = this.data[i];
        }
        this.data = newData;
    }

    @Override
    public String toString() {
        StringBuffer rs = new StringBuffer();
        rs.append(String.format("Array List: size = %d, capacity = %d\n", this.size, this.data.length));
        rs.append("[");
        for (int i = 0; i < this.size; i ++){
            rs.append(this.data[i]);
            if (i != size -1){
                rs.append(", ");
            }
        }
        rs.append("]");
        return rs.toString();
    }
}

 

动态扩容:

以上我们虽然实现了顺序表,存储数据是使用的静态数组,容量有限,很多时候我们无法预估往数组中放多少个元素,在这种情况下如果容量太大会浪费空间,容量太小则不够使用,这种情况下我们需要一种解决方案:我们数组容量可伸缩的(动态扩容)


public class ArrayList {
    /** 使用数组存储数据 */
    private T[] data;
    /** size记录当前数组data中实际元素个数 */
    private int size;

    public ArrayList(int capacity) {
        this.data = (T[]) new Object[capacity];
        this.size = 0;
    }
    public ArrayList() {
        this(10);
    }

    /**
     * 获取顺序表中元素个数
     * @return
     */
    public int getSize(){
        return this.size;
    }

    /**
     * 获取顺序表容器
     * @return
     */
    public int getCapacity(){
        return this.data.length;
    }

    /**
     * 判断顺序表是否为空
     * @return
     */
    public boolean isEmpty(){
        return size == 0;
    }


    /**
     * 向顺序表中index位置上添加元素
     * @param index
     * @param e
     */
    public void add(int index, T e){
        if (index < 0 || index > this.size){
            throw new IllegalArgumentException("Add failed. Require index >= 0 and index < size");
        }
        // 如果当前data数组元素个数为整个数组容量时,进行扩容
        if (this.size == this.data.length){
            resize(2 * this.data.length);
        }
        for (int i = size - 1; i >= index; i--){
            this.data[i + 1] = data[i];
        }
        this.data[index] = e;
        this.size ++;
    }


    /**
     * 在所有元素后添加一个新元素
     * @param e
     */
    public void addLast(T e){
        this.add(size, e);
    }

    /**
     * 在所有元素前添加一个新元素
     * @param e
     */
    public void addFirst(T e){
        this.add(0, e);
    }

    /**
     * 获取指定索引位置上的元素e
     * @param index
     * @return
     */
    public T get(int index){
        if (index < 0 || index >= size){
            throw new IllegalArgumentException("Get failed. Index is illegal");
        }
        return this.data[index];
    }

    /**
     * 修改指定索引位置上的元素e
     * @param e
     * @param index
     */
    public void set(T e, int index){
        if (index < 0 || index >= size){
            throw new IllegalArgumentException("Get failed. Index is illegal");
        }
        this.data[index] = e;
    }

    /**
     * 查询顺序表中是否包含指定的元素e
     * @param e
     * @return
     */
    public boolean contains(T e){
        for (int i = 0; i < size; i++){
            if (data[i] == e){
                return true;
            }
        }
        return false;
    }

    /**
     * 查找顺序表中元素e所在的索引,如果元素e不存在返回-1
     * @param e
     * @return
     */
    public int find(T e){
        for (int i = 0; i < size; i++){
            if (data[i].equals(e) ){
                return i;
            }
        }
        return -1;
    }

    /**
     * 删除顺序表中index位置上的元素,返回删除的元素
     * @param index
     * @return
     */
    public T remove(int index){
        if (index < 0 || index >= size){
            throw new IllegalArgumentException("Remove failed. Index is illegal");
        }
        T ret  =  this.data[index];
        for (int i = index + 1; i < this.size; i++){
            this.data[i - 1] = this.data[i];
        }
        this.size --;
        this.data[size] = null;
        // 如果当前data数组元素个数为整个数组容量的1/2时,进行缩容
        if (this.size == this.data.length / 2){
            resize(this.data.length / 2);
        }
        return ret;
    }

    /**
     * 删除顺序表中第一个元素,返回删除的元素
     * @return
     */
    public T removeFirst(){
        return this.remove(0);
    }

    /**
     * 删除顺序表中最后一个元素,返回删除的元素
     * @return
     */
    public T removeLast(){
        return this.remove(this.size -1);
    }

    /**
     * 删除指定的元素
     * @param e
     */
    public boolean removeElement(T e){
        int index = this.find(e);
        if (index != -1){
            this.remove(index);

        }
        return false;
    }

    private void resize(int newCapacity) {
        T[] newData = (T[]) new Object[newCapacity];
        for (int i = 0; i < this.size; i++){
            newData[i] = this.data[i];
        }
        this.data = newData;
    }

    @Override
    public String toString() {
        StringBuffer rs = new StringBuffer();
        rs.append(String.format("Array List: size = %d, capacity = %d\n", this.size, this.data.length));
        rs.append("[");
        for (int i = 0; i < this.size; i ++){
            rs.append(this.data[i]);
            if (i != size -1){
                rs.append(", ");
            }
        }
        rs.append("]");
        return rs.toString();
    }
}

 

顺序表的各种操作时间复杂度分析

  • 添加操作
    •  addLast(e):O(1)
    • addFirst(e):O(n)
    • add(index, e):O(n)
  • resize:O(n)
  • 修改操作
    • set:O(1)
  • 删除操作
    • removeLast:O(1)
    • removeFirst:O(1)
    • remove:O(n)
  • 查找操作
    • get(index):O(1)
    • contains(e):O(n)​​​​​​​
    • find(e):O(n)

 

你可能感兴趣的:(Java方面,数据结构与算法)