「数据结构」- 顺序表

线性表概念

线性表(linear list)是数据结构的一种,一个线性表是n个具有相同特性的数据元素的有限序列。线性表是最基本、最简单、也是最常用的一种数据结构,常见的线性表:顺序表、链表、栈、队列…

本章学习的是属于线性表中的一种:顺序表

顺序表

顺序表是用一段物理 (内存) 地址连续的存储单元依次存储数据元素的线
性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。

顺序表一般可以分为:

  • 静态顺序表:使用定长数组存储。
  • 动态顺序表:使用动态开辟的数组存储。

静态顺序表适用于确定知道需要存多少数据的场景.静态顺序表的定长数组导致N定大了,空间开多了浪费,开少了不够用.相比之下动态顺序表更灵活, 根据需要动态的分配空间大小,本章主要介绍动态顺序表,相信看完了动态顺序表,实现静态顺序表则轻而易举。


顺序表主体

顺序表其实底层就是数组实现的,主体部分需要定义一个数组和一个计数器来存 储当前数组中有多少个数据,在构造方法中根据情 况初始化数组大小。

在这里插入图片描述


方法实现

接下来我们的任务就是实现以下方法,为了代码可读性,后续实现顺序可能会图片顺序不一致,但总体来说都是一样的。

在这里插入图片描述

获取顺序表长度

顾名思义,就是把顺序表中的有效数据返回给调用者,在定义顺序表的时候我们就定义了一个记录有效数据的计数器usedSize,这里只需要将usedSize返回回去就ok了。

在这里插入图片描述

新增元素

思路: 实现在 pos 下标位置新增元素,需要考虑 pos 下标是否合法,如果 pos 位置小于0(数组下标从0开始),或者 pos 下标大于有效数据则会发生断层,也是不可以的。
在这里插入图片描述
其次还需要考虑扩容的问题,只有当有效数据小于数组预设长度时才能进行添加元素,如果 usedSize 等于数组的长度则需要进行扩容,接下来就是移动数据,只需要定义一个 iusedSize -1的位置 通过循环往后移动数据,最后往 pos 位置进行插入就ok了,并且 usedSize 自增一次。

在这里插入图片描述

查找某个元素对应的位置

数组中有该元素返回对应的下标,无则返回-1(数组下标最小是0)。
思路:循环遍历有效数据,相等返回对应下标,退出循环则代表没找到返回-1

在这里插入图片描述

判断是否包含某个元素

包含则返回true,无则返回false
思路:调用刚写的查找元素位置的方法,返回的不是-1则返回true,否则返回false

在这里插入图片描述

获取 pos 位置的元素

思路:先考虑 pos 位置是否合法,如果 pos 位置大于 usedSize -1或者小于0的情况下,则会造成越界访问。pos 合法的情况直接返回pos 下标对应的元素

在这里插入图片描述

修改元素

思路:先考虑 pos 位置是否合法,如果 pos 位置大于 usedSize -1或者小于0的情况下,则会造成越界访问。pos 合法的情况把pos 下标对应的元素更改成value

在这里插入图片描述

删除元素

思路:调用刚写的 search 方法,定义 pos 接受返回的下标,如果不等于-1则使用循环从 pos 位置至 usedSize -1的位置开始往后覆盖元素,最后 usedSize自减一次。

在这里插入图片描述

打印顺序表

思路:循环遍历有效数据进行输出

在这里插入图片描述

清空顺序表

只需将 usedSize 置0就ok了

在这里插入图片描述


以上就是实现顺序表的过程啦,希望对读者能带来帮助,最后附上源代码

public class MyArrayList {
    public int[] elem;
    public int usedSize;

    public MyArrayList() {
        this.elem = new int[5];//初始化数组大小
    }


    // 在 pos 位置新增元素    
    public void add(int pos, int data) {
        //先判断pos合法性
        if (pos < 0 || pos > this.usedSize) {
            System.out.println("pos:" + pos + " 位置不合法!");
            return;
        }
        //扩容
        if (this.usedSize == this.elem.length) {
            this.elem = Arrays.copyOf(this.elem, 2 * this.elem.length);
        }
        //插入找到最后一个有效的数据,然后把 i的元素移到i+1的地方去
        int i = 0;
        for (i = usedSize - 1; i >= pos; i--) {
            this.elem[i + 1] = this.elem[i];
        }
        this.elem[pos] = data;
        this.usedSize++;
    }

    // 打印顺序表    
    public void display() {
        for (int i = 0; i < usedSize; i++) {
            System.out.print(elem[i] + " ");
        }
        System.out.println();
    }


    // 判定是否包含某个元素    
    public boolean contains(int toFind) {
        if (this.search(toFind) != -1) {
            return true;
        }
        return false;
    }

    // 查找某个元素对应的位置    
    public int search(int toFind) {
        for (int i = 0; i < this.usedSize; i++) {
            if (this.elem[i] == toFind) {
                return i;
            }
        }
        return -1;
    }
    // 获取 pos 位置的元素    
    public int getPos(int pos) {
        if (pos < 0 || pos > this.usedSize - 1) {
            System.out.println("pos:" + pos + " 位置不合法");
            return -1;
        }
        return this.elem[pos];
    }

    // 给 pos 位置的元素设为 value  
    public void setPos(int pos, int value) {
        if (pos < 0 || pos > this.usedSize - 1) {
            System.out.println("pos:" + pos + " 位置不合法");
            return;
        }
        this.elem[pos] = value;
    }

    //删除第一次出现的关键字key    
    public void remove(int toRemove) {
        //1、找到要删除的关键字的位置
        int pos = this.search(toRemove);
        if (pos == -1) {
            System.out.println("没有该关键字" + toRemove);
            return;
        }
        for (int i = pos; i < this.usedSize - 1; i++) {
            this.elem[i] = this.elem[i + 1];
        }
        this.usedSize--;
    }

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

    // 清空顺序表    
    public void clear() {
        this.usedSize = 0;
    }
}

总结

顺序表的问题

  1. 顺序表中间/头部的插入删除,时间复杂度为O(N)
  2. 增容需要申请新空间,拷贝数据,释放旧空间。会有不小的消耗
  3. 增容一般是呈2倍的增长,势必会有一定的空间浪费。例如当前容量为100,满了以后增容到200,我们再继续插入了5个数据,后面没有数据插入了,那么就浪费了95个数据空间。

后续我会出一篇关于链表的博客,读者可以自行对比两种数据结构的区别,感兴趣的读者话可以一键三连,防止迷路。

  • 8
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值