前言
在Java编程中,顺序表是一种基础且重要的数据结构。它通常用来表示线性结构数据,如数组等。通过使用顺序表,我们可以轻松管理和操作大量的数据,并实现各种算法和功能。本篇博客将详细介绍Java中顺序表相关的原理、方法和实例,帮助大家更好地理解和应用这一知识点。
一、顺序表的定义
知己知彼,才能百战不殆,想要会写顺序表,我们首先就得知道顺序表是什么。那顺序表是什么呢?如下:
顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。
说白了,顺序表就是一个数组,但是顺序表的空间大小是可变的,数组不行,数组是死的,但是数组也有数组的好处,顺序表虽然可以实现动态调整大小和快速的插入和删除操作,但是对于随机访问元素时却比数组效率要低。所以,需要进行大量的随机访问,则应该使用数组;如果需要经常进行插入和删除操作,则应该使用顺序表。
二、顺序表的实现
首先,我们得写一个关于顺序表的类,里面放顺序表的增删查改······等方法,我先给个引子,大家可以自己试着先实现方法体,如下:
public class SeqList {
private int elemSize;//表示实际存储了多少个数据
private int[] elem;
private static final int space = 10;//先默认给10个空间的容量
// 初始化顺序表
public SeqList() {
this.elem = new int[space];//默认赋予10个空间的大小
}
// 将顺序表的底层容量设置为initcapacity
public SeqList(int initcapacity) {}
//判断是否需要扩容
private boolean isFull() {}
// 新增元素,默认在数据最后新增
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() {}
}
2.1、获取顺序表的长度
能看到这里,说明大家已经写完了,或者已经思考完了,柿子得挑软的捏,我们先实现获取顺序表的长度,那怎么获得呢?我们可以让顺序表的元素等于0就返回吗?因为数组只有初始化没有存数据的话默认值都是0,所以我们遇到0就返回,答案肯定是不行的,假设我们存储的数据中间就是0呢?那不就完蛋了吗。得用其他办法,话说我们不是定义了一个elemSize的属性吗?这个就是顺序表实际存储数据的长度,代码实现如下:
public int size() {
return this.elemSize;
}
2.2、初始化顺序表
首先,我们得初始化一个顺序表,让他得有空间存数据呀,所以我们就写它的构造方法,代码实现如下:
public SeqList(int initcapacity) {
this.elem = new int[initcapacity];
}
2.3、顺序表的查找
2.3.1、查找位置的元素
想要查找pos位置上的元素,只需要先判断你给的下标是否合法,如果不合法,我们可以抛出异常,如果合法,我们就直接返回下标位置上的元素就好了,下面是代码实现:
public int get(int pos) {
if (pos < 0 || pos >= this.elemSize) {
throw new NullPointerException("输入下标不合法!!!");
}
return this.elem[pos];
}
2.3.2、查找元素的位置
和上面差不多,还是首先判断位置是否合法,如果合法,那就循环迭代往后走,找到就返回,如果不合法,就return -1;,下面是代码实现:
public int indexOf(int toFind) {
for (int i = 0; i < this.elemSize; i++) {
if (this.elem[i] == toFind) {
return i;
}
}
return -1;
}
2.4、判断是否包含某个元素
相信大家也看到了,返回的是boolean类型,如果有这个元素,返回true,没有返回false,下面是代码实现:
public boolean contains(int toFind) {
for (int i = 0; i < this.elemSize; i++) {
if (this.elem[i] == toFind) {
return true;
}
}
return false;
}
2.5、判断是否需要扩容
本来是要实现怎么增加元素代码的,但是,怎家元素之前,我们需要判断存储的元素是否已经满了,因为两个增加数据的代码都用的到,我懒得写两遍,所以就单独拎出来写了,那怎么判断呢?下面让我来告诉你,代码实现如下:
private boolean isFull() {
return this.elemSize >= this.elem.length;
}
2.6、添加元素
2.6.1、尾插
顾名思义,尾插就是从顺序表的尾部插入,那顺序表是谁呢?下面是代码实现:
public void add(int data) {
if (isFull()) {//判断是否需要扩容
//扩容代码的实现
this.elem = Arrays.copyOf(this.elem,2 * this.elemSize);
}
this.elem[this.elemSize++] = data;
}
2.6.2、在指定位置插入
这个比尾插要难一点,我画个图帮助大家理解,如下:
例如这个顺序表,目前存了如上数据,如果说我要在pos == 5的位置插入一个数字,该怎么办呢?很简单,是不是要先找到这个下标,然后这个下标后面的数据往后移呀,所以我们就可以写如下代码:
public void add(int pos, int data) {
if (isFull()){//还是和上面一样,一进来判断是否合法
this.elem = Arrays.copyOf(this.elem,2 * this.elemSize);
}
for (int i = this.elemSize; i > pos; ) {
this.elem[i] = this.elem[--i];
}
this.elem[pos] = data;
this.elemSize++;
}
2.7、删除第一次出现的关键字
首先我们要找到这个数字,然后让这个数字后面的数字全部往前挪,下面是代码实现:
public void remove(int toRemove) {
if (this.elemSize == 0) {
return;
}
int key = 0;
boolean flag = false;
int i = 0;
for (; i < this.elemSize; i++) {
if (this.elem[i] == toRemove) {
System.out.println("存在" + toRemove + "下标为" + i);
flag = true;
break;
}
}
if (flag) {
for (; i < this.elemSize - 1; i++) {
this.elem[i] = this.elem[i + 1];
}
this.elem[--this.elemSize] = 0;
}
else {
System.out.println("未找到!!!");
}
}
2.8、更改顺序表中的数字
首先判断pos下标是否合法,合法就更改,如果pos等于最后一个元素的后面,就是尾插,elemSize就需要++,下面是代码实现:
public void set(int pos, int value) {
if (pos >= 0 && pos <= this.elemSize) {
this.elem[pos] = value;
if (pos == this.elemSize) {
this.elemSize++;
}
}
else {
System.out.println("未找到该位置的下标");
}
}
2.9、打印顺序表
到这里,我们就得写一个打印函数来打印我们的顺序表了,主要是每一次增删查改后方便检查是否正确的,不用去调试,下面是代码实现:
public void display() {
System.out.print("SeqList{" + "elem=");
for (int i = 0; i < this.elemSize; i++) {
System.out.print(this.elem[i]);
if (i < this.elemSize - 1) {
System.out.print(", ");
}
}
System.out.println('}');
}
2.10、清空顺序表
其实只是存数据的话不用写这个,一般来说存引用类型的才需要制空,因为如果不制空,那我们可用的内存就会越来越少,这就是内存泄漏,但是我们还是得意思意思一下,代码实现如下:
public void clear() {
for (int i = 0; i < this.elemSize; i++) {
this.elem[i] = 0;
}
this.elem = null;
}
写到这儿就都写完了,可以自己去写一个main方法爽一下了。
三、结语
在Java编程的学习之路上,顺序表是第一步不可或缺的环节。虽然这看起来非常基础,但是它却包含了许多深刻的思想和原则,以及不少鲜活的实践案例。这个知识点可能需要长时间、反复地掌握,所以要保持专注和耐心。最终的收获往往会超出我们的预期。
当遇到挫折和困难时,我们需要坚信自己,勇于尝试和学习。程序设计中最美妙的地方就在于,即便面对重重困难,只要你坚定地寻求解决方案并付出努力,终究可以找到突破口。成功并不是唯一的目标,每一个错误和失败都为我们提供了重要的经验教训,帮助我们更好地成长。
因此,在Java编程的道路上,我们不能怕输、要有勇气追梦。与其担心失败的后果,不如预备迎接挑战,并珍视每一次机会逐渐提高自我。记住,“天才”不是先天赋予的,而是通过向内探索和不断尝试而达成的,只要保持学习的热情,我们就会在Java编程的路上越走越远。