【数据结构中链表常用的方法实现过程】

线性表

  • 线性表包括:顺序表、链表、栈,队列等,本节我们先学习顺序表。

顺序表

利用新的数据类型------顺序表,操作数组

顺序表的本质就是对数组的增删改查。

java 复制代码
    /**
     * 打印顺序表中的所有元素
     */
    @Override
    public void display() {
        for (int i = 0; i < usedSize; i++) {
            System.out.println(elem[i]+" ");
        }
        System.out.println();
    }

往数组末尾添加元素

java 复制代码
    /**
     * 添加元素:默认添加到数组的最后位置
     * @param data
     */
    @Override
    public void add(int data) {
        //1.如果满了,要进行扩容
        if(isFull()){
            //二倍扩容 -> 拷贝完之后让elem指向一个新的数组对象
            elem = Arrays.copyOf(elem , 2*elem.length);
        }
        //将元素放入数组中
        elem[usedSize] = data;
        usedSize++;
    }
    
    //判断数组是否满了
    @Override
    public boolean isFull() {
        return usedSize == elem.length;
    }

通过debug可以看到,当数组元素超出其所能承载的容量大小时,可以通过copyOf进行扩容,从而将第六个元素放进去。


在指定位置添加新元素

  • 1.首先从后往前移动元素
  • 2.将元素放进指定位置,并且更新元素个数。

java 复制代码
    @Override//①
    public void add(int pos, int data) {

        //1.先挪动元素,将最后面元素逐个往前挪
        //i >= pos 时元素才会往前移
        for (int i = usedSize - 1; i >= pos; i--) {

            elem[i+1] = elem[i];
        }//挪完将指定元素插入到位置中
         elem[pos] = data;
        usedSize++;

        }

    @Override
    public String toString() {
        // 数组的话是没有toString的,可以使用它的工具类去打印
        return Arrays.toString(elem);
//        刚刚写的是return elem.tostring
        // 当这个是list类型,不是普通的数组类型的时候,是可以直接调用toString打印的,但是普通数组是不可以直接toString打印的
//        return elem.toString(); // 这个打印的是这个数组的地址
    }
  • 但是上面的分析还是有些不够严谨,对于插入元素的位置还需要考虑,这个位置的正负以及是否会造成空间浪费(eg:隔空插入元素);此外,数组是否会发生越界异常也需要考虑。
java 复制代码
    @Override//①
    public void add(int pos, int data) {

        //1.pos位置的判断 -> pos 不能为负的 或 pos不能隔空插元素
        checkPosOfAdd(pos);
        //1.先挪动元素,将最后面元素逐个往前挪
        //i >= pos 时元素才会往前移
        for (int i = usedSize - 1; i >= pos; i--) {

            elem[i+1] = elem[i];
        }//挪完将指定元素插入到位置中
         elem[pos] = data;
        usedSize++;

        }

    @Override
    public String toString() {
        // 数组的话是没有toString的,可以使用它的工具类去打印
        return Arrays.toString(elem);
//        刚刚写的是return elem.tostring
        // 当这个是list类型,不是普通的数组类型的时候,是可以直接调用toString打印的,但是普通数组是不可以直接toString打印的
//        return elem.toString(); // 这个打印的是这个数组的地址
    }

    //1.pos位置的判断 -> pos 不能为负的 或 pos不能隔空插元素
    public void checkPosOfAdd(int pos){
        if(pos <0 || pos > usedSize){
            throw new PosException("pos位置是" + pos);
        }
    }
  • ⚠️如果当这个数组满了插入元素,可看到报越界异常。

    ✅️解决方案:判段这个要插入的数组是否满了,满了可以通过扩容来解决越界问题。
java 复制代码
    @Override//①
    public void add(int pos, int data) {

        //1.pos位置的判断 -> pos 不能为负的 或 pos不能隔空插元素
        checkPosOfAdd(pos);
        //2.如果这个数组是满的,则需要对数组进行扩容才能插入新元素
        isFulling();


        //1.先挪动元素,将最后面元素逐个往前挪
        //i >= pos 时元素才会往前移
        for (int i = usedSize - 1; i >= pos; i--) {
            elem[i+1] = elem[i];
        }//挪完将指定元素插入到位置中
         elem[pos] = data;
        usedSize++;

        }

    @Override
    public String toString() {
        // 数组的话是没有toString的,可以使用它的工具类去打印
        return Arrays.toString(elem);
//        刚刚写的是return elem.tostring
        // 当这个是list类型,不是普通的数组类型的时候,是可以直接调用toString打印的,但是普通数组是不可以直接toString打印的
//        return elem.toString(); // 这个打印的是这个数组的地址
    }

    //1.pos位置的判断 -> pos 不能为负的 或 pos不能隔空插元素
    public void checkPosOfAdd(int pos){
        if(pos <0 || pos > usedSize){
            throw new PosException("pos位置是" + pos);
        }
    }

    //2.如果这个数组是满的,则需要对数组进行扩容才能插入新元素
    public void isFulling(){
        elem = Arrays.copyOf(elem,2*elem.length);
    }

查找当前元素是否存在

java 复制代码
    /**
     * 查找当前元素是否存在
     * @param toFind
     * @return
     */
    @Override
    public boolean contains(int toFind) {
        for(int i = 0 ; i < usedSize ; i++){
            if(elem[i] == toFind){
                return true;
            }
        }
        return false;
    }

如果这里的元素是引用类型,需要通过equals进行比较。


查找当前元素的下标

java 复制代码
    /**
     * 查找当前元素的下标
     * @param toFind
     * @return
     */
    @Override
    public int indexOf(int toFind) {
        for(int i = 0 ; i < usedSize ; i++){
            if(elem[i] == toFind){//如果这里是引用数据类型需要用equals进行比较
                return i;
            }
        }
        return -1;
    }



获取对应下标对应元素的数值

java 复制代码
    /**
     * 获取pos位置的值
     * @param pos
     * @return
     */
    @Override
    public int get(int pos) {

        //1.判断pos合法性
        checkPosGet(pos);
        //2.pos为空的异常处理
        if(isEmpty()){
            throw new EmptyException("数组为空,无法获取元素" );
        }
        return elem[pos];
    }

    //1.判断pos合法性
    public  void checkPosGet(int pos){
        if(pos < 0 || pos >= usedSize){
            throw new PosException("Pos 不合法 , 位置是:" + pos);
        }

    }
    //2.pos为空的异常处理 -> 此时pos正好符合>=usedSize(为0)的情况,算是1的一种。  
    public boolean isEmpty(){
        return  usedSize == 0;
    }

更新对应下标的元素值

java 复制代码
    /**
     * 更新pos位置的值为 value
     * @param pos
     * @param value
     */
    @Override
    public void set(int pos, int value) {
        //1.检查pos位置的合法性
        checkPosOfSet(pos);
        //2.pos为空的异常处理
        if(isEmpty()){
            throw new EmptyException("顺序表为空");
        }
        elem[pos] = value;
    }
    public void checkPosOfSet(int pos){
        if(pos < 0 || pos >= usedSize){
            throw  new PosException("Pos 位置不合法位置是 :"+ pos);
        }
    }

获取顺序表的大小

java 复制代码
    /**
     * 获取顺序表的大小
     * @return
     */
    @Override
    public int size() {
        return this.usedSize;
    }

删除指定元素

java 复制代码
   /**
     * 删除toRemove这个数字
     * 删除指定元素
     * @param toRemove
     */
    @Override
    public void remove(int toRemove) {
        //首先,找到元素下标
        //因为刚刚已经实现过通过元素寻找下标的方法了,现在只要调用这个方法即可找到对应元素的下标
        int index = indexOf(toRemove);
        //然后,将这个位置前面的元素往后移动覆盖掉即可删除
        for(int i = index ; i < usedSize - 1  ; i++){
            elem[i] = elem[i+1];
        }
        usedSize--;
    }

释放内存

  • 在源码中是先将元素置为null之后,再将空间置为0进行释放的。
java 复制代码
    /**
     * 清空顺序表,防止内存泄漏
     */
    @Override
    public void clear() {
        usedSize = 0;
    }
  • 因为示例中的数据都是int类型不是引用类型,所以如果需要释放内存,直接将其赋值为0即可,而对于引用类型由于他们有内存地址所以需要将它们置为null才能释放内存。

相关推荐
JialBro2 小时前
【嵌入式】直流无刷电机FOC控制算法全解析
算法·嵌入式·直流·foc·新手·控制算法·无刷电机
昌兵鼠鼠2 小时前
LeetCode Hot100 哈希
学习·算法·leetcode·哈希算法
忘梓.2 小时前
二叉搜索树·极速分拣篇」:用C++怒肝《双截棍》分拣算法,暴打节点删除Boss战!
开发语言·c++·算法
星辰徐哥2 小时前
Java数组的定义、操作与应用场景
java·开发语言
人工智能AI酱2 小时前
【AI深究】高斯混合模型(GMM)全网最详细全流程详解与案例(附Python代码演示) | 混合模型概率密度函数、多元高斯分布概率密度函数、期望最大化(EM)算法 | 实际案例与流程 | 优、缺点分析
人工智能·python·算法·机器学习·分类·回归·聚类
逻辑流2 小时前
《精准测量的起点:STM32中的电压电流有效值计算算法》
stm32·单片机·嵌入式硬件·算法
脏脏a2 小时前
【优选算法・双指针】以 O (n) 复杂度重构数组操作:从暴力遍历到线性高效的范式跃迁
算法·leetcode·双指针·牛客·优选算法
Piar1231sdafa2 小时前
深度学习目标检测算法之YOLOv26加拿大鹅检测
深度学习·算法·目标检测
闻缺陷则喜何志丹2 小时前
【C++DFS 马拉车】3327. 判断 DFS 字符串是否是回文串|2454
c++·算法·深度优先·字符串·力扣·回文·马拉车