目录
模拟实现简单的ArrayList
初始化
打印顺序表
判断顺序表是是否已满
增加元素
指定位置插入元素
判断是否包含某个元素
按值查找元素
获取对应位置的元素
修改指定位置的值
删除元素
获取顺序表的长度
清空顺序表
完整代码
什么是顺序表?
顺序表是指在计算机内存中以数组的形式保存的线性表,是指用一组地址连续的存储单元依次存储数据元素的线性结构.
了解ArrayList类
在Java中,ArrayList是一个普通的类,实现了List接口,除了实现了List接口外,还实现了RandomAccess、Cloneable、Serializable接口,这些接口的实现表明了ArrayList支持随机访问、可以clone、支持序列化.
ArrayList不是线程安全的,在单线程下使用.ArrayList底层是一段连续的空间,并且可以动态扩容,是一个动态类型的顺序表.
ArrayList中常见的操作有增、删、查、改、插等等,这些也是每个数据结构都有的基本操作.
在自己实现的ArrayList类中需要包括以下功能:增加元素(默认插入到最后一个位置)、查找元素(按值、按位置)、修改元素、删除元素、获取顺序表的长度、清空顺序表.
因为线性表的底层其实是一个数组,因此定义出一个数组elem,usedSize用来记录顺序表的长度,初始化顺序表的存储空间为10.
public class MyArrayList {
public int[] elem;//定义数组
public int usedSize;//用来记录顺序表的长度
public MyArrayList(){
this.elem = new int[10];//初始化顺序表
}
}
// 打印顺序表
public void myToString(){
for (int i = 0; i < this.usedSize; i++) {
System.out.print(this.elem[i] + " ");
}
}
该方法主要是为了检测顺序表是否已满,方便后续代码中的扩容操作.
//判断线性表是否已满
public boolean isFull(){
if(this.usedSize == this.elem.length){
return true;
}
return false;
}
在给顺序表中增加元素之前,首先需要判断顺序表是否已满,如果已满则需要进行扩容,如果未满,则正常插入,插入的元素默认插入到最后一个位置.
//新增元素,默认添加到最后一个位置
public void add(int data){
if(isFull()){
this.elem = Arrays.copyOf(this.elem, this.elem.length*2);
}
this.elem[this.usedSize] = data;
this.usedSize++;
}
在进行插入操作之前首先进行如下两个步骤:
①判断插入位置是否合法,如果不合法,则抛出异常;
②判断顺序表是否已满,如果已满则进行扩容;
如果插入位置合法且顺序表未满,则进行插入.
假设目前顺序表的存储空间为5,存储元素为3个,此时usedSize = 3;假设要在下标为1的位置插入元素,则此时令i = usedSize - 1,并将下标为1的位置后的所有元素后移一位
之后再将要插入的值插入下标为1的位置即可,再将usedSize+1.
// 在 pos 位置新增元素
public void add(int pos, int data){
if(pos<0 || pos > this.usedSize){
throw new RuntimeException("插入位置不合法");
}
if(isFull()){
this.elem = Arrays.copyOf(this.elem, this.elem.length*2);
}
for (int i = this.usedSize-1; i >= pos; i--) {
this.elem[i + 1] = this.elem[i];
}
this.elem[pos] = data;
this.usedSize++;
}
直接遍历顺序表,找到与待查元素相同的值则返回true,否则返回false
// 判定是否包含某个元素
public boolean contains(int data){
for (int i = 0; i < this.usedSize; i++) {
if(this.elem[i] == data){
return true;
}
}
return false;
}
利用for循环遍历顺序表,如果找到要查找的元素则返回该元素的下标,否则返回-1.
// 查找某个元素对应的位置
public int indexSearch(int data){
for (int i = 0; i < this.usedSize; i++) {
if(this.elem[i] == data){
return i;
}
}
return -1;
}
首先判断要查找的位置是否合法,如果不合法,抛出异常,反之利用for循环遍历顺序表,如果找到,返回对应元素的值.
// 获取 pos 位置的元素
public int get(int pos){
if(pos<0 || pos > this.usedSize-1){
throw new RuntimeException("操作位置不合法");
}
return elem[pos];
}
由于顺序表是支持随机访问的,因此可以直接利用下标找到对应位置修改即可,在修改之前首先需要判断操作位置是否合法.
// 给 pos 位置的元素设为 value
public void set(int pos, int data){
if(pos<0 || pos > this.usedSize-1){
throw new RuntimeException("操作位置不合法");
}
this.elem[pos] = data;
}
在进行删除操作之前,首先需要判断,顺序表是否为空,如果为空,则不需要进行后序操作;之后利用上述的按值查找方法找到对应的元素下标,再将该位置之后的元素往前顺移一位,再将usedSize-1.
假设要删除的元素为2,则只需如下操作即可
// 判断顺序表是否为空
public boolean isEmpty(){
if(this.usedSize == 0){
return true;
}
return false;
}
// 删除第一次出现的关键字key
public void del(int key){
if(isEmpty()){
throw new RuntimeException("顺序表为空,非法操作");
}
int index = indexSearch(key);
if(index == -1){
System.out.println("未找到该元素");
}
for(int i = index; i < this.usedSize-1; i++){
this.elem[i] = this.elem[i+1];
}
this.usedSize--;
}
// 获取顺序表长度
public int length(){
return this.usedSize;
}
因为Java的垃圾回收机制会自动回收未引用的对象,因此直接将usedSize置为0即可.
// 清空顺序表
public void clear(){
this.usedSize = 0;
}
import java.util.Arrays;
public class MyArrayList {
public int[] elem;
public int usedSize;
public MyArrayList(){
this.elem = new int[10];
}
//判断线性表是否已满
public boolean isFull(){
if(this.usedSize == this.elem.length){
return true;
}
return false;
}
//新增元素,默认添加到最后一个位置
public void add(int data){
if(isFull()){
this.elem = Arrays.copyOf(this.elem, this.elem.length*2);
}
this.elem[this.usedSize] = data;
this.usedSize++;
}
// 打印顺序表
public void myToString(){
for (int i = 0; i < this.usedSize; i++) {
System.out.print(this.elem[i] + " ");
}
}
// 在 pos 位置新增元素
public void add(int pos, int data){
if(pos<0 || pos > this.usedSize){
throw new RuntimeException("插入位置不合法");
}
if(isFull()){
this.elem = Arrays.copyOf(this.elem, this.elem.length*2);
}
for (int i = this.usedSize-1; i >= pos; i--) {
this.elem[i + 1] = this.elem[i];
}
this.elem[pos] = data;
this.usedSize++;
}
// 判定是否包含某个元素
public boolean contains(int data){
for (int i = 0; i < this.usedSize; i++) {
if(this.elem[i] == data){
return true;
}
}
return false;
}
// 查找某个元素对应的位置
public int indexSearch(int data){
for (int i = 0; i < this.usedSize; i++) {
if(this.elem[i] == data){
return i;
}
}
return -1;
}
// 获取 pos 位置的元素
public int get(int pos){
if(pos<0 || pos > this.usedSize-1){
throw new RuntimeException("操作位置不合法");
}
return elem[pos];
}
// 给 pos 位置的元素设为 value
public void set(int pos, int data){
if(pos<0 || pos > this.usedSize-1){
throw new RuntimeException("操作位置不合法");
}
this.elem[pos] = data;
}
// 删除第一次出现的关键字key
public void del(int key){
if(isEmpty()){
throw new RuntimeException("顺序表为空,非法操作");
}
int index = indexSearch(key);
if(index == -1){
System.out.println("未找到该元素");
}
for(int i = index; i < this.usedSize-1; i++){
this.elem[i] = this.elem[i+1];
}
this.usedSize--;
}
// 判断顺序表是否为空
public boolean isEmpty(){
if(this.usedSize == 0){
return true;
}
return false;
}
// 获取顺序表长度
public int length(){
return this.usedSize;
}
// 清空顺序表
public void clear(){
this.usedSize = 0;
}
}