用数组实现线性表(可以随意添加数据的数组)
为什么需要线性表?
- 数组:按照索引操作都快
- 下标查找快
- 插入慢
- 不能扩容: 连续的一块内存空间(所以不能随意修改数据)
- 下标不方便管理
- 比较查找慢
- 链表:
- 查找慢
- 可以扩容: 不需要连续
- 插入快
线性表接口设计:
- 抽象方法:
- 基本信息提供: 现有元素个数
- 增删查改:
- 排序输出:(这里没有实现,大概思路是用hashCode实现,之后会专门写一篇排序)
- 合并: 数组合并数组 数组合并链表 链表合并数组 链表合并链表(这里只实现了数组的部分,链表的之后会专门写一篇)
设计数组实现的线性表:
-
存储结构: Object类型数组
-
元素个数/下标
-
长度/容量
-
默认长度/默认容量
-
初始化不同的构造方法:
- 构造方法:
- 根据 传入的容量初始化
- 根据一个现有数组/链表/同类型线性表初始化
- 默认的初始化方法
- add: 考虑扩容算法
- 单个元素
- 数据结构 数组
- get:
- 根据下标获取元素
- 根据元素获取多个下标
- 根据集合(数组、链表)获取 数组
- remove: 移位
- 根据下标获取元素,然后移位
- 根据元素获取多个下标,然后移位
- 根据集合获取,然后移位
- sort: 排序(这里没有实现,下次专门写一篇)
- 构造方法:
具体的代码
线性表(MyArrylist)类的一些参数
使用泛型是方便存取各类数据
public class MyArrayList <E> implements MyList {
private Object[] valueArray = {};
private int length; //容量 容量=下标+1
private int size; //下标
private static final int defaultLength = 10;
// 访问获取元素个数
public int size() {
return size;
}
public int getLength() {
return length;
}
初始化构造函数
public MyArrayList(int inlength) {
if ((int)inlength <= 0) {
System.err.println("输入容量越界!!"+inlength);
}
if ((int)inlength <= 10) {
length = defaultLength;
valueArray = new Object[length];
}
if ((int)inlength > 10 && (int)inlength < Integer.MAX_VALUE - 100) {
length = (int)inlength;
valueArray = new Object[length];
}
if ((int)inlength >= Integer.MAX_VALUE - 100) {
System.err.println("推荐使用大线性表!!");
}
size = 0;
}//根据传入的容量初始化构造
public MyArrayList() {
length = defaultLength;//10
valueArray = new Object[length];
size = 0;
}//默认初始化大小是10
根据数组构造
public MyArrayList(E[] objects) {
int length = objects.length;
int size =0;
Object[] newArry = new Object[length];
for (int i = 0; i < length; i++) {
newArry[i] = objects[i];
if (objects[i] !=null){
size++;
}
}
this.length = length;
this.valueArray = newArry;
this.size =size;
}//根据数组构造
根据单个元素扩容
public void add(E e) {
//size =size+1; //方法2 没有这句话
if (size >= length) {
// 扩容
// 换一个大一点的数组
int oldLength = length;
int newLength = oldLength + (oldLength >> 1); //乘以1.5,2进制退位
length = newLength;
Object[] newArray = new Object[length];
for (int i = 0; i < oldLength; i++) {
newArray[i] = valueArray[i];
}
//替换引用
valueArray = newArray;
newArray = null;
}
valueArray[size++] = e; //方法2 valueArry[Size++] =e
} //根据单个元素扩容
根据数组添加
public void add(E[] objects) {
int length_new = objects.length + this.length;
Object[] newArry = new Object[length_new];
for (int i = 0; i < this.length; i++) {
newArry[i] = valueArray[i];
}//添加原本的数组
for (int i = this.length; i < length_new; i++) {
newArry[i] = objects[(i-this.length)];
System.out.println("原来的"+i);
System.out.println("现在的"+(i-this.length));
}//添加新的的数组
this.length = length_new;
this.valueArray = newArry;
this.size = size+objects.length;
}//根据数组添加
根据下标获取元素
/**
* 根据下标遍历
* @param index 传入的下标
* @return 返回目标下标的元素
*/
public Object get(int index) {
System.out.println("获取下标为"+index);
if(index<size&&index>=0){
return valueArray[index];
}
System.err.println("数组里面没有这个对象");
return null;
} //根据下标获取元素
根据元素获取多个下标
public MyArrayList<Integer> get(E object) {
int num_add = 0;
MyArrayList<Integer> indexArr = new MyArrayList<Integer>();
for (int i = 0; i < size; i++) {
if (valueArray[i].equals(object)) {
num_add++;
indexArr.add(i);
System.out.println("numadd++");
//((Integer)valueArray[i]).equals(anoint)
}
}
System.out.println("重复的个数 "+num_add);
if(num_add==0){
return null;
}
return indexArr;
} //根据元素获取多个下标
根据数组,获取数组第一个元素位置
/**
* 这里把【1,2】看成一个整体,返回的是数组第一个元素的位置
* @param objects
* @return Interger
*/
public Integer get(E[] objects){
for (int i = 0; i < objects.length; i++) {
//查找对象
for (int j = 0; j < valueArray.length; j++) {
//原来数组
System.out.println("查找对象"+i);
System.out.println("原来数组"+j);
if (valueArray[j] .equals(objects[i]) ) {
if (i == (objects.length - 1)) {
// 循环到查找对象的最后一位了 这里的i是查找对象的最后一个,j是原来数组对应的查找对象的最后一个元素
i=0;//为返回数组做准备,这里用不到
return (j+1- objects.length); //减去长度,是第一个元素的位子
}//找到了查找对象的位子
i =i+1;
}else {
i=0;
}
}
}
System.out.println("没有这些元素");
return null;
}//根据数组返回位置
移位函数:删除所有的Null,节省空间
public void removeNull(){
int removeNumber=0;
for (int i=0; i< valueArray.length;i++){
if(valueArray[i] ==null){
removeNumber++;
}
}
Object []newarry =new Object[valueArray.length-removeNumber];
for (int i=0; i< valueArray.length;i++){
int j=0;
if(valueArray[i] !=null){
newarry[i-j]= valueArray[i];
}
else {
j++;
}
}
valueArray =newarry;
length =length -removeNumber;
}
根据下标获取单个元素,然后移位
public void remove(int object){
Object[] newArry = new Object[length-1];
for (int i=0; i<object;i++){
newArry[i] = valueArray[i];
}
for (int i=(object+1); i<length; i++){
newArry[i-1] = valueArray[i];
}
valueArray = newArry;
length=length-1;
size=size-1;
newArry=null;
System.out.println ("文件已经删除");
this.removeNull();
}//根据下标获取元素,然后移位
根据单个元素获取多个下标,然后移位
public void remove(E object) {
int number = 0;
for (int i = 0; i < size; i++) {
if(valueArray[i]!=null){
if (valueArray[i].equals(object) ) {
number++;
}
}
}
Object[] newarry = new Object[length - number];
int cut_number = 0;
for (int i = 0; i < length; i++) {
if(valueArray[i]!=null){
if (valueArray[i].equals(object) ) {
cut_number++;
} else {
newarry[i - cut_number] = valueArray[i];
}
}
}
valueArray = newarry;
length =length - number;
size =size - number;
}//根据单个元素获取多个下标,然后移位
根据数组获取多个元素的多个下标,然后移位
/**
* 这里删除传入数组中的所有元素,包括重复的
* 最后没有改length是因为 removeNull 会改length
* @param objects
*/
public void remove(E[] objects) {
int removeNumber =0;
for (int i = 0; i < objects.length; i++) {
//传入数组
for (int j = 0; j < valueArray.length; j++) {
//原来的数组
if(objects[i].equals(valueArray[j])){
objects[i] =null;
removeNumber++;
}
}
}
size =size-removeNumber;
this.removeNull();
}