当前位置: 首页 > article >正文

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

在这里插入图片描述

线性表

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

顺序表

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

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

在这里插入图片描述

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

往数组末尾添加元素

    /**
     * 添加元素:默认添加到数组的最后位置
     * @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.将元素放进指定位置,并且更新元素个数。
    在这里插入图片描述

在这里插入图片描述

    @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:隔空插入元素);此外,数组是否会发生越界异常也需要考虑。
    @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);
        }
    }
  • ⚠️如果当这个数组满了插入元素,可看到报越界异常。
    在这里插入图片描述
    ✅️解决方案:判段这个要插入的数组是否满了,满了可以通过扩容来解决越界问题。
    @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);
    }

在这里插入图片描述


查找当前元素是否存在

    /**
     * 查找当前元素是否存在
     * @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进行比较。


查找当前元素的下标

    /**
     * 查找当前元素的下标
     * @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;
    }

在这里插入图片描述
在这里插入图片描述


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

在这里插入图片描述

    /**
     * 获取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;
    }

在这里插入图片描述


更新对应下标的元素值

    /**
     * 更新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);
        }
    }

在这里插入图片描述


获取顺序表的大小

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

在这里插入图片描述


删除指定元素

在这里插入图片描述

   /**
     * 删除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进行释放的。
    /**
     * 清空顺序表,防止内存泄漏
     */
    @Override
    public void clear() {
        usedSize = 0;
    }
  • 因为示例中的数据都是int类型不是引用类型,所以如果需要释放内存,直接将其赋值为0即可,而对于引用类型由于他们有内存地址所以需要将它们置为null才能释放内存。


http://www.kler.cn/a/538196.html

相关文章:

  • openAI官方prompt技巧(一)
  • Go语言构建微服务:从入门到实战
  • idea 如何使用deepseek 保姆级教程
  • Goland 内存逃逸问题
  • StochSync:可在任意空间中生成360°全景图和3D网格纹理
  • 在CT107D单片机综合训练平台上,8个数码管分别单独依次显示0~9的值,然后所有数码管一起同时显示0~F的值,如此往复。
  • python基于深度学习的中文情感分析系统
  • AI安全最佳实践:AI应用开发安全评估矩阵(上)
  • Spring Boot:简化 Java 开发的利器
  • 24.ppt:小李-图书策划方案【1】
  • 通过C变成语言实现一个或多个算法
  • Redis数据库篇 -- Pipeline
  • 【0404】Postgres内核 实现分配一个新的 Object ID (OID)
  • Python如何实现名称为”000-“~“999-”文件的自动生成,且后缀名可以自定义
  • 基于SeaTunnel同步数据
  • 使用Jenkins实现鸿蒙HAR应用的自动化构建打包
  • COBOL语言的云计算
  • 基于HTML、CSS 和 JavaScript 开发个人读书类网站
  • uniapp中使用uCharts折线图X轴数据间隔显示
  • 基于python多线程多进程爬虫的maa作业站技能使用分析
  • Python----Python高级(网络编程:网络基础:发展历程,IP地址,MAC地址,域名,端口,子网掩码,网关,URL,DHCP,交换机)
  • 【爬虫开发】爬虫开发从0到1全知识教程第13篇:scrapy爬虫框架,介绍【附代码文档】
  • <tauri><rust><GUI>基于rust和tauri,在已有的前端框架上手动集成tauri示例
  • RabbitMQ 消息顺序性保证
  • 多线程下jdk1.7的头插法导致的死循环问题
  • 学JDBC 第二日