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

线性表

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

顺序表

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

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

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才能释放内存。

相关推荐
小bo波1 天前
从"任意文件复制"深挖Java I/O:字符流与字节流的本质抉择
java·nio·io流·后端开发·文件复制
JieE2122 天前
LeetCode 101. 对称二叉树|JS 递归 + 迭代双解法,彻底搞懂镜像判断
javascript·算法
nanxun8862 天前
记一次诡异的 Docker 容器"串包"故障排查
java
用户1563068103512 天前
Day01 | Java 基础(Java SE)
java
行者全栈架构师2 天前
Maven dependency:tree 的 8 个高级用法
java·后端
行者全栈架构师2 天前
IDEA 中 Maven 项目的 15 个红色报错快速解决方法
java·后端
令人头秃的代码0_02 天前
mac(m5)平台编译openjdk
java
JieE2123 天前
LeetCode 56. 合并区间|超清晰 JS 图解思路,面试高频区间题
javascript·算法·面试
Jack203 天前
HarmonyOS开发中错误处理策略:网络异常统一处理
算法
小小杨树3 天前
读懂色彩:拍照调色不再难
算法·计算机视觉·配色