首页 > 编程语言 >JavaDS-学习数据结构之如果从零开始手搓顺序表,顺带学习自定义异常怎么用!

JavaDS-学习数据结构之如果从零开始手搓顺序表,顺带学习自定义异常怎么用!

时间:2024-05-30 17:31:59浏览次数:27  
标签:顺序 自定义 int 顺带 pos myarray void JavaDS public

前言

笔者开始学习数据结构了,虽然笔者已经会用了,不管是C++ 中的stl亦或是Java 中的集合,为了算法比赛多少都突击过,但只知其然而不知其所以然,还是会限制发展的,因此,笔者写下这篇博客.内容是手搓一个顺序表.顺带加一点异常的使用,大伙看个乐子就好了.有错误直接私信喷我就好了,不用和我客气!

前置知识-什么是数据结构

说的简短一些,数据结构是计算机存储、组织数据的方式。数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。

前置知识-什么是顺序表?

答:说白了就是一个动态数组

官方概念如下:

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

顺序表如何实现?

如图

一个接口,一个类负责实现方法,一个Main类来调用,一个我们自定义的异常来处理各种问题!!!

顺序表的接口

package LIST;

public interface list
{
    // 新增元素,默认在数组最后新增
    public void add(int data);
    // 在 pos 位置新增元素
    public void add(int pos, int data);
    // 判定是否包含某个元素
    public boolean contains(int toFind);
    // 查找某个元素对应的位置
    public int indexOf(int toFind);
    // 获取 pos 位置的元素
    public int get(int pos);
    // 给 pos 位置的元素设为 value
    public void set(int pos, int value);
    //删除第一次出现的关键字key
    public void remove(int toRemove);
    // 获取顺序表长度
    public int size() ;
    // 清空顺序表
    public void clear();
    // 打印顺序表,注意:该方法并不是顺序表中的方法,为了方便看测试结果给出的
    public void display();
    public boolean isfull();
    // 负责检查顺序表是否满了
    public boolean isEmpty();
    //负责检查顺序表是否是空的
}

每个结构具体需要实现什么功能,笔者已经写在注释里了,作为一个"动态数组",也就是"CURD"而已.

没什么难的,但是不借助外力的手搓还是有点难的.

自定义异常   

比起使用现有的异常,我们还是自己定义一个方便一些

package LIST;

public class POSIllegal extends RuntimeException
{
    public POSIllegal(String message)
    {
        super(message);
    }
}

顺序表的功能实现

前置功能

@Override
public boolean isfull()
// 检测顺序表是否以及满了
{
    if(usedsize==myarray.length)
        return true;
    else
        return  false;
}
    @Override
    public boolean isEmpty()
    {
        return this.usedsize==0?true:false;
    }

 设置这两个功能说实话有的没必要,但是一定要考虑到严谨,这必须加上来,以防止越界,也可以引出如果使用自定义异常!

通过这两个重写方法,也可以衍生出一个被封装的方法

private  void checkcap()
{
    if(isfull())
    // 检测一下
    {
        myarray = Arrays.copyOf(myarray,myarray.length*2);
        // 扩容(两倍)
    }
}

 为什么我们这里用private?因为你作为使用者,你压根用不着.这也是一种没什么必要的严谨性吧.早点养成习惯也不是什么坏事.

部分核心功能

接下来来到我们的核心功能了,我们一个个来看

增加

    @Override
    public void add(int data)
    {
        checkcap();
            this.myarray[this.usedsize] =data;
            this.usedsize++;
    }

在指定位置增加

    private  void checkPos (int pos)   throws POSIllegal
    {
        if(pos<0||pos>this.usedsize)
        {
            throw  new POSIllegal("pos不合法,你的pos是 :"+pos);
        }
    }   

 @Override
    public void add(int pos, int data)
    {
        checkcap();
        try {
            checkPos(pos);
        }
        catch (POSIllegal e)
        {
            e.printStackTrace();
            System.out.println("下标不符合规定");
            return ;
        }
        for(int i=this.usedsize-1;i>=pos;i--)
        {
             this.myarray[i+1]=this.myarray[i];
        }
        this.myarray[pos]=data;
        this.usedsize++;
    }

我们首先,看看,需不需要扩容,不需要,好的,再看看有没有异常,有的话,抛出异常,让catch接收,然后return,没有异常,那就更好了,直接就可以扩容了,注意下标的边界就好了,没有难度.

得到指定位置的数据

    @Override
    public int get(int pos)
    {
        try {
            return this.myarray[pos];
        } catch (ArrayIndexOutOfBoundsException e)
        {
            e.printStackTrace();
            System.out.println("越界了,数组只有"+myarray.length+"这么大");
            System.out.println("请你看看自己是不是选择了负数或者大于数组大小的数");
           return  pos;
        }
    }

 这里我们用了官方的异常,有个对比参考.

 在指定位置替换元素

    private  void checkPosSet (int pos)   throws POSIllegal
    {
        if(pos<0||pos>=this.usedsize)
        {
            throw  new POSIllegal("pos不合法,你的pos是 :"+pos);
        }
    }

    @Override
    public void set(int pos, int value)
    {
        try {
           checkPosSet(pos);
        }
        catch (POSIllegal e)
        {
            e.printStackTrace();
            return ;
        }
        this.myarray[pos]=value;
    }

注意注意,这里和增加不同了,增加是可以在顺序表增加的,但是替换是不能在结尾替换的,因为你没有元素,你怎么替换?你告诉我.

获取指定位置元素

    @Override
    public int indexOf(int toFind)
    {
        if(isEmpty())
        {
            return -1;
        }
        else
        {
            for(int i=0;i<this.usedsize;i++)
            {
                if(this.myarray[i]==toFind)
                    return i;
            }
        }
            return -1;
    }

 这里我就没用try catch 写法了

移除第一次出现的某元素

    @Override
    public void remove(int toRemove)
    {
         int idx=indexOf(toRemove);
         if(idx==-1)
         {
             System.out.println("没有这个数字哦");
         }
         else
         {
             for(int i=idx;i<usedsize-1;i++)
             {
                 this.myarray[i]=this.myarray[i+1];
             }
             usedsize--;
         }
    }

其他功能

还有两个其他功能

清空,还有获得usedsize

    @Override
    public int size()
    {
        return this.usedsize;
    }
    @Override
    public void clear()
    {
        if(isEmpty())
        {
            System.out.println("没法清理,顺序表是空的");
            return ;
        }
        for(int i=0;i<this.usedsize;i++)
        {
            this.myarray[i]=0;
        }
        display();
        System.out.println("清空完成");
    }

主函数

package LIST;
public class Main
{
    public static void main(String[] args) {
        Mylist mylist=new Mylist();
         mylist.add(0,2);
        mylist.add(1,2);
        mylist.add(2,2);
        mylist.add(3,2);
        mylist.add(1,23);
        mylist.add(3,2);
        mylist.add(3,2);
        mylist.add(3,2);
        mylist.display();
        mylist.set(5,2324);
        mylist.set(7,232);
        mylist.add(543,242);
        System.out.println(mylist.size());
        mylist.display();
        mylist. clear();
    }
}

可以进行各种调用

也会显示异常出来

效果如图!!!!!!!

完整代码

完整代码如下

package LIST;

public interface list
{
    // 新增元素,默认在数组最后新增
    public void add(int data);
    // 在 pos 位置新增元素
    public void add(int pos, int data);
    // 判定是否包含某个元素
    public boolean contains(int toFind);
    // 查找某个元素对应的位置
    public int indexOf(int toFind);
    // 获取 pos 位置的元素
    public int get(int pos);
    // 给 pos 位置的元素设为 value
    public void set(int pos, int value);
    //删除第一次出现的关键字key
    public void remove(int toRemove);
    // 获取顺序表长度
    public int size() ;
    // 清空顺序表
    public void clear();
    // 打印顺序表,注意:该方法并不是顺序表中的方法,为了方便看测试结果给出的
    public void display();
    public boolean isfull();
    // 负责检查顺序表是否满了
    public boolean isEmpty();
    //负责检查顺序表是否是空的
}

package LIST;
import java.util.Arrays;
public class Mylist implements list
{
    int [] myarray;
    public  static  final int number= 5;
  int  usedsize=0;
    public Mylist()
    {
        this.myarray = new int[number];
    }
private  void checkcap()
{
    if(isfull())
    // 检测一下
    {
        myarray = Arrays.copyOf(myarray,myarray.length*2);
        // 扩容(两倍)
    }
}
@Override
public boolean isfull()
// 检测顺序表是否以及满了
{
    if(usedsize==myarray.length)
        return true;
    else
        return  false;
}
    @Override
    public boolean isEmpty()
    {
        return this.usedsize==0?true:false;
    }

    private  void checkPos (int pos)   throws POSIllegal
    {
        if(pos<0||pos>this.usedsize)
        {
            throw  new POSIllegal("pos不合法,你的pos是 :"+pos);
        }
    }
    private  void checkPosSet (int pos)   throws POSIllegal
    {
        if(pos<0||pos>=this.usedsize)
        {
            throw  new POSIllegal("pos不合法,你的pos是 :"+pos);
        }
    }
@Override
public void display()
{
        // 打印顺序表
        for(int i=0;i<this.usedsize;i++)
        {
            System.out.print(myarray[i]);
            System.out.print(" ");
        }
        System.out.println();
}
    @Override
    public void add(int data)
    {
        checkcap();
            this.myarray[this.usedsize] =data;
            this.usedsize++;
    }
    @Override
    public void add(int pos, int data)
    {
        checkcap();
        try {
            checkPos(pos);
        }
        catch (POSIllegal e)
        {
            e.printStackTrace();
            return ;
        }
        for(int i=this.usedsize-1;i>=pos;i--)
        {
             this.myarray[i+1]=this.myarray[i];
        }
        this.myarray[pos]=data;
        this.usedsize++;
    }
    @Override
    public boolean contains(int toFind)
    {
        if(isEmpty())
        {
            System.out.println("找不到,因为顺序表是空的");
            return false;
        }
        for(int i=0;i<usedsize;i++)
        {
            if(this.myarray[i]==toFind)
            {
                System.out.println("找到了,它的下标是 :"+i);
                return true;
            }
        }
        System.out.println("顺序表里没有这么元素");
        return  false;
    }

      @Override
    public int indexOf(int toFind)
    {
        if(isEmpty())
        {
            return -1;
        }
        else
        {
            for(int i=0;i<this.usedsize;i++)
            {
                if(this.myarray[i]==toFind)
                    return i;
            }
        }
            return -1;
    }

    @Override
    public int get(int pos)
    {
        try {
            return this.myarray[pos];
        } catch (ArrayIndexOutOfBoundsException e)
        {
            e.printStackTrace();
            System.out.println("越界了,数组只有"+myarray.length+"这么大");
            System.out.println("请你看看自己是不是选择了负数或者大于数组大小的数");
           return  pos;
        }
    }
    @Override
    public void set(int pos, int value)
    {
        try {
           checkPosSet(pos);
        }
        catch (POSIllegal e)
        {
            e.printStackTrace();
            return ;
        }
        this.myarray[pos]=value;
    }
    @Override
    public void remove(int toRemove)
    {
         int idx=indexOf(toRemove);
         if(idx==-1)
         {
             System.out.println("没有这个数字哦");
         }
         else
         {
             for(int i=idx;i<usedsize-1;i++)
             {
                 this.myarray[i]=this.myarray[i+1];
             }
             usedsize--;
         }
    }
    @Override
    public int size()
    {
        return this.usedsize;
    }
    @Override
    public void clear()
    {
        if(isEmpty())
        {
            System.out.println("没法清理,顺序表是空的");
            return ;
        }
        for(int i=0;i<this.usedsize;i++)
        {
            this.myarray[i]=0;
        }
        display();
        System.out.println("清空完成");
    }
}
package LIST;

public class POSIllegal extends RuntimeException
{
    public POSIllegal(String message)
    {
        super(message);
    }
}

结尾

可以看到,对于核心功能,我写的很草率,压根没有写完整,只是随便写了几个增删查改的功能,如果要细化还是能出很多的,交给能看到这里的读者了.

我写学过用C语言手搓顺序表,只能说,Java还是更简单一点.

需要我的完整代码,可以访问我的GitHub,链接点进去,这部分代码在JavaDS  List当中

需要就点个星呗,我的GitHub有的乱,后续我会整理的.

calljsh/Call-JJ-java (github.com)

到这里我也写了快一个小时了,不知道有没有人可以看到啊!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

标签:顺序,自定义,int,顺带,pos,myarray,void,JavaDS,public
From: https://blog.csdn.net/cjejwe/article/details/139298074

相关文章

  • QT事件触发顺序探讨:处理自定义事件与系统事件的冲突
    1.课题背景在项目开发过程中用到了纯按键的QT交互,我们通过自定义以下全局键盘事件类进行交互的实现:classKEYPRESSFILTER_EXPORTKeyPressFilter:publicQObject{Q_OBJECTpublic:staticKeyPressFilter*instance(){if(m_instance==nullptr){......
  • C#自定义事件的写法
    C#事件基于委托例1:只用于学习,理解事件底层原理,不推荐这么写;例2:系统用的就是该方式,例如按钮的Click事件;例3:最简略的写法,但是需要客户代码转换EventArgs;1、事件声明完整格式范例: 1//自定义事件参数,默认以EventArgs结尾,需要继承EventArgs类2publicclassMyEventArgs:......
  • 【源码】Spring Data JPA原理解析之Repository自定义方法命名规则执行原理(一)
     SpringDataJPA系列1、SpringBoot集成JPA及基本使用2、SpringDataJPACriteria查询、部分字段查询3、SpringDataJPA数据批量插入、批量更新真的用对了吗4、SpringDataJPA的一对一、LazyInitializationException异常、一对多、多对多操作5、SpringDataJPA自定......
  • TabControl和TabItem的样式自定义:为什么要使用自定义模板?
    在WPF(WindowsPresentationFoundation)中,控件的外观和行为是通过控件模板(ControlTemplate)来定义的。TabControl和TabItem控件也不例外,它们的默认控件模板定义了这些控件的结构和视觉状态。在实际应用中,开发者可能会发现直接设置TabItem的某些属性(例如Background)时不会生效。这篇......
  • 解决因跨域导致使用a标签下载文件download属性失效无法自定义命名的问题
    问题背景:在使用a标签下载文件时,download属性可以更改下载的文件//下载a.exe,并采用默认命名<ahref="/images/a.exe"download>点击下载</a>//将a.exe改名为b.exe下载<ahref="/images/a.exe"download="b">点击下载</a>注意:html5新特性a标签download属性只支持......
  • echarts饼图给legend图例增加自定义点击事件
    echarts图例点击会有一个默认的点击事件,会把点击的图例对应的legend取消解决办法legendselectchanged事件中将取消选中的legend动态设置回来,主要代码如下:letchart=echarts.init(document.getElementById('main'),null)//图例点击事件chart.on('legendselectchanged',(pa......
  • uniapp自定义富文本编辑器+内容渲染回显功能(多端可用)
    这个编辑器app端、H5端、小程序端都可以用,这里以小程序为例。先上效果图,文本编辑、样式调整、图片上传等各项功能皆可满足。一、整体介绍 使用富文本编辑并且可以渲染内容这个功能,主要涉及到两个页面。①触发编辑的页面(按钮+接收富文本内容)②编辑器页面(效果图页面)二......
  • custom:用户自定义插件,提供开放能力
    custom插件的功能:支持用户在右键菜单中自定义插件。简介custom插件大量采用声明式代码(声明代替代码开发),比如:只需使用style=()=>"...",即可注册css。只需使用styleTemplate=()=>({renderArg}),即可引入css文件,并且支持渲染模板。只需使用html=()=>"...",即......
  • 第20讲:自定义类型:联合和枚举
    目录1.联合体1.1联合体类型的声明1.2联合体的特点1.3相同成员的结构体和联合体对比1.4联合体的大小1.5联合的一个练习2.枚举类型2.1枚举类型的声明2.3枚举类型的使用1.联合体1.1联合体类型的声明像结构体⼀样,联合体也是由⼀个或者多个成员构成,这些成员......
  • 在Spring中自定义事件及发布与监听
    在Spring框架中,自定义事件及其发布与监听是一个涉及Spring事件机制的过程。Spring提供了一个基于观察者模式的事件发布和监听机制,允许在Spring容器中的组件之间进行松耦合的通信。以下是如何自定义事件以及如何发布和监听这些事件的步骤:1.创建自定义事件类首先,需要定义一......