JAVA语言手把手教你编程 —— 顺序表实现
- 顺序表是什么
- 顺序表接口实现
- 1、创建类
- 2、打印顺序表
- 3、获取顺序表长度
- 4、在 pos 位置新增元素
- 5、判定是否包含某个元素
- 6、查找某个元素对应的位置
- 7、获取 pos 位置的元素
- 8、给 pos 位置的元素设为 value
- 8、删除第一次出现的关键字key
- 9、清空顺序表
- 小结
顺序表是什么
顺序表是在计算机内存中以数组的形式存储的线性表,线性表的顺序存储是指用一组地址连续的存储单元依次存储线性表中的各个元素、使得线性表中在逻辑结构上相邻的数据元素存储在相邻的物理存储单元中。
顺序表接口实现
动态顺序表需要实现的接口如下:
// 打印顺序表
public void display() { }
// 在 pos 位置新增元素
public void add(int pos, int data) { }
// 判定是否包含某个元素
public boolean contains(int toFind) { return true; }
// 查找某个元素对应的位置
public int search(int toFind) { return -1; }
// 获取 pos 位置的元素
public int getPos(int pos) { return -1; }
// 给 pos 位置的元素设为 value
public void setPos(int pos, int value) { }
//删除第一次出现的关键字key
public void remove(int toRemove) { }
// 获取顺序表长度
public int size() { return 0; }
// 清空顺序表
public void clear() { }
1、创建类
把顺序表创建成一个类,这个类里面包括了两个属性:数组(因为顺序表底层就是对数组的操作)和有效数据(来记录整个数组的有效数据有多少个);
构造方法:初始化数组大小为10(因为数组默认值是null不指向任何对象,数组要给一个大小),usedSize的默认值是0,所以不用初始化。
public class MyArrayList {
public int[] elam;
public int usedSize; //有效数据
//构造方法
public MyArrayList(){
this.elam = new int[10];
}
}
注意:最好不要在成员变量中初始化
面向对象/类的使用者
引用了顺序表这个对象,之后我只需要调用顺序表的功能就好,不需要知道这么实现的
具体的方法是由类的实现者实现的,这里是类的使用者
public class Main {
public static void main(String[] args) {
MyArrayList myArrayList = new MyArrayList();
}
}
首先主函数里面会在栈上面新建一个引用myArrayList;
这个引用会指向MyArrayList这个对象;
这个对象里面就包含了两个属性;
通过构造方法属性中elam数组在堆上创建了一个大小为10的数组
2、打印顺序表
根据有效数据的个数,让 i 从0下标一直遍历到3下标,然后把对应的下标的值打印出来
// 打印顺序表
public void display() {
for (int i = 0; i < usedSize; i++) {
System.out.println(this.elam[i]+" ");
}
System.out.println();
}
3、获取顺序表长度
顺序表的有效长度就是等于数据的有效个数
// 获取顺序表长度
public int size() {
return this.usedSize;
}
4、在 pos 位置新增元素
判断完pos的插入位置之后,就是对顺序表进行插入的动作
判断pos插入位置不同情况
public void add(int pos, int data) {
//1、判断pos的合法性
if(pos < 0 || pos > usedSize){
System.out.println("插入位置不合法");
return;
}
//2、判断数组是否满了, 满了就扩容(扩容原来数组的2倍)
if (isFull()){
this.elam = Arrays.copyOf(this.elam,2*this.elam.length)
}
}
//判断顺序表是否满
public boolean isFull(){
return this.usedSize == this.elam.length;
}
完整代码
// 在 pos 位置新增元素
public void add(int pos, int data) {
//1、判断pos的合法性
if(pos < 0 || pos > usedSize){
System.out.println("插入位置不合法");
return;
}
//2、判断数组是否满了, 满了就扩容(扩容原来数组的2倍)
if (isFull()){
this.elam = Arrays.copyOf(this.elam,2*this.elam.length);
}
//3、移动覆盖数据
for (int i = usedSize-1; i >= pos ; i--) {
this.elam[i+1]=this.elam[i];
}
//4、插入数据
this.elam[pos]=data;
//5、有效数据加1
usedSize++;
}
//判断顺序表是否满
public boolean isFull(){
return this.usedSize == this.elam.length;
}
测试添加元素代码
5、判定是否包含某个元素
遍历顺序表的每个元素和要查找的元素进行比较,找到返回true,找不到返回false
// 判定是否包含某个元素
public boolean contains(int toFind) {
for (int i = 0; i < usedSize-1; i++) {
if (this.elam[i] == toFind){
return true;
}
}
return false;
}
测试代码
6、查找某个元素对应的位置
遍历顺序表的每个元素和要查找的元素进行比较,找到返回下标 i ,找不到返回-1(下标没有负数)
// 查找某个元素对应的位置
public int search(int toFind) {
for (int i = 0; i < usedSize-1; i++) {
if (this.elam[i] == toFind){
return i;
}
}
return -1;
}
代码测试
7、获取 pos 位置的元素
首先还是要判断pos的位置是否合法,顺序表是否为空
然后就是返回pos的对应元素
// 获取 pos 位置的元素
public int getPos(int pos) {
//判断pos的位置是否合法
if (pos < 0 || pos >= usedSize){
System.out.println("pos的位置不合法");
return -1;
}
//判断pos的位置是否为空
if (isFull()){
System.out.println("顺序表为空!");
return -1;
}
//返回pos位置对应的元素
return this.elam[pos];
}
//判断数组是否为空
public boolean isEmpty(){
return this.usedSize==0;
}
测试代码
8、给 pos 位置的元素设为 value
首先还是要判断pos的位置是否合法,顺序表是否为空
然后就是把pos下标的元素重新赋值为value值
//判断数组是否为空
public boolean isEmpty(){
return this.usedSize==0;
}
// 给 pos 位置的元素设为 value
public void setPos(int pos, int value) {
//判断pos的位置是否合法
if (pos < 0 || pos >= usedSize){
System.out.println("pos的位置不合法");
return;
}
if (isFull()){
System.out.println("顺序表为空!");
return;
}
this.elam[pos] = value;
}
代码测试
8、删除第一次出现的关键字key
1、如果顺序表为空的话,删除不了2、查到你要删除的数字3、从要删除的数字开始,把后一个值赋值到前一个值4、i 下标走到3就停下来,因为数组有效值会减15、下标4的元素55,不需要做任何操作(因为下次插入元素会直接覆盖55这个元素)
//删除第一次出现的关键字key
public void remove(int toRemove) {
//判断顺序表是否为空
if (isFull()){
System.out.println("顺序表为空!");
return;
}
//查到数字
int index = search(toRemove);
if(index == -1){
System.out.println("没有你要删除的关键字");
}
//覆盖元素
for (int i = index ; i < usedSize-1; i++) {
this.elam[i] = this.elam[i+1];
}
//有效个数减1
this.usedSize--;
}
代码测试
9、清空顺序表
遍历每个元素赋值为0
然后把有效个数赋值为0
// 清空顺序表
public void clear() {
for (int i = 0; i < usedSize; i++) {
this.elam[i] = 0;
}
usedSize=0;
}
测试代码
小结
1、插入和删除元素,必须要移动元素
2、扩容的时候可能会浪费空间怎么样可以解决以上两个问题呢?
答案:链表