admin | 女足世界杯预测
java手撸数据结构–数组(无序、有序、稀疏)
数组是java语言内置的数据类型,他是一个线性的序列,所以可以快速访问其他的元素,数组和其他语言不同,当你创建了一个数组时,他的容量是不变的,而且生命周期也是不能改变的,还有JAVA数组会做边界检查,如果发现有越界现象,会报RuntimeException异常错误,当然检查边界会以效率为代价。
数组的局限性分析
插入快:对于无序数组,即元素没有按照一定顺序排列,只是按照插入的顺序排列。无序数组增加一个元素很简单,只需要在数组末尾添加元素即可,但有序数组却不一定了,它需要在指定的位置插入。查找慢:当然通过下标查找是很快的。但是通常我们都是根据元素值来查找的,给定一个元素值,对于无序数组,我们需要从数组的第一个元素还是遍历,直到找到那个元素。有序数组通过特定算法查找的速度会比无需数组快。删除慢:根据元素值删除,我们要先找到该元素所在位置,然后将元素后端的值整体向前移动一个位置。也需要比较多的时间。数组一旦创建,大小固定:如果初始化一个很大的数组大小,那会白白浪费内存空间,如果给小了,后面的数据个数增加了又添加不进去了。
很显然,数组虽然插入快,但是查找和删除比较慢,而且扩展性差,所以我们一般不会用数组来存储数据。
无序数组
无序数组,顾名思义,就是没有顺序的数组,即元素没有按照一定顺序排列,只是按照插入的顺序排列。
创建一个类来实现无序数组
class MyArray{
//存储具体数据的数组
int[] array;
//当前数组存放数据数量
int size;
//构造函数,初始化无序数组
public MyArray(int maxPage) {
array = new int[maxPage];
size = 0;
}
}
1. 插入
/**
* 插入
*/
public void insert(int value) {
if (size < array.length) {
//数组未满,则插入
array[size++] = value;
}
}
2. 查找
/**
* 查找返回下标
*/
public int find(int value) {
int i;
for (i = 0; i < array.length; i++) {
if (array[i] == value) {
break;
}
}
if (i == size) {
System.out.println("数组中不存在当前数据");
return -1;
} else {
return i;
}
}
3. 删除
/**
* 删除
*/
public void delete(int value) {
int j;
if((j=this.find(value))>-1){
for (int i = j; i < size-1; i++) {
array[i]=array[i+1];
}
//删除完把记录-1
size--;
}
}
4. 遍历
/**
* 遍历
*/
public void forEach(){
for (int i = 0; i < size; i++) {
System.out.print(array[i]+" ");
}
System.out.println();
}
5.测试
public static void main(String[] args) {
MyArray myArray = new MyArray(10);
myArray.insert(12);
myArray.insert(5);
myArray.insert(1);
myArray.forEach();
myArray.delete(5);
myArray.forEach();
}
值:
12 5 1
12 1
有序数组
有序数组优缺点分析
优点:
采用二分查找效率高,比无序数组效率高。缺点:
插入的时候,要移动元素,比无序数组效率低。
创建一个类来实现有序数组
/**
* 有序数组
*/
class MySequenceArray {
//存储有序数组的集合
private int[] array;
//元素数量
private int size;
public MySequenceArray(int size) {
array = new int[size];
size = 0;
}
}
查找
/**
* 查找返回下标(二分查找)
*/
public int find(int value) {
if (size == 0) {
return -1;
}
int index;
//当前比对的最大下标
int maxIndex = size - 1;
// 当前比对的最小下标
int minIndex = 0;
//当前下标
int currentIndex;
while (true) {
if (minIndex > maxIndex) {
return -1;
}
currentIndex = (maxIndex + maxIndex) / 2;
if (value == array[currentIndex]) {
return currentIndex;
} else if (value > array[currentIndex]) {
minIndex = currentIndex + 1;
} else {
maxIndex = currentIndex - 1;
}
}
}
插入
/**
* 插入
*/
public void insert(int value) {
if (array.length > size) {
int index;
for (index = 0; index < size; index++) {
if (value < array[index]) {
//找到了
break;
}
}
if (index < size) {
//数组中存在比value大的数,则index以后的数向后移动一位
for (int i = size; i > index; i--) {
array[i] = array[i - 1];
}
//将value插入index处
array[index] = value;
} else {
//最后找不到比value大的数
array[index] = value;
}
size++;
}
}
删除
/**
* 删除
*/
public void delete(int value) {
int index;
if ((index = find(value)) > -1) {
for (int i = index; i < size - 1; i++) {
array[i] = array[i + 1];
}
size--;
}
}
遍历
/**
* 遍历
*/
public void forEach() {
for (int i = 0; i < size; i++) {
System.out.print(array[i] + " ");
}
System.out.println();
}
测试
public static void main(String[] args) {
MySequenceArray mySequenceArray = new MySequenceArray(10);
mySequenceArray.insert(10);
mySequenceArray.insert(1);
mySequenceArray.insert(55);
mySequenceArray.insert(3);
mySequenceArray.forEach();
mySequenceArray.delete(3);
mySequenceArray.delete(2);
mySequenceArray.forEach();
}
1 3 10 55
1 10 55
稀疏数组
所谓稀疏数组就是数组中大部分的内容值都未被使用(或都为零),在数组中仅有少部分的空间使用。
因此造成内存空间的浪费,为了节省内存空间,并且不影响数组中原有的内容值,我们可以采用一种压缩的方式来表示稀疏数组的内容。
稀疏数组实现方式
如下:
方式一:二维数组存储,用空间换取时间,占用空间大,查询效率高
int[][] array = new int[7][9]; //占用63
array[1][1] = 3;
array[3][0] = 1;
array[3][1] = 4;
array[4][2] = 7;
array[5][5] = 5;
遍历
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++) {
System.out.print(array[i][j] + " ");
}
System.out.println();
}
遍历值如下:
0 0 0 0 0 0 0 0 0
0 3 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
1 4 0 0 0 0 0 0 0
0 0 7 0 0 0 0 0 0
0 0 0 0 0 5 0 0 0
0 0 0 0 0 0 0 0 0
方式二:使用压缩方式,执行效率较低,占用空间小
创建一个类来实现稀疏数组
/**
* 稀疏数组实现
*/
class MySparseArray{
//稀疏数组的行数
private int row;
//稀疏数组的列数
private int col;
//稀疏数组当前行当前列的值
private int val;
//通过构造函数实例化
public MySparseArray(int row, int col, int val) {
this.row = row;
this.col = col;
this.val = val;
}
public int getRow() {
return row;
}
public int getCol() {
return col;
}
public int getVal() {
return val;
}
}
稀疏数组的使用
//定义五个节点的稀疏数组,这里的6不包含第一行记录
MySparseArray[] mySparseArrays = new MySparseArray[6];
//第一行为记录行数、列数、节点数,下标为0
//7行、9列
mySparseArrays[0] = new MySparseArray(7, 9, 6);
mySparseArrays[1] = new MySparseArray(1, 1, 3);
mySparseArrays[2] = new MySparseArray(3, 0, 1);
mySparseArrays[3] = new MySparseArray(3, 1, 4);
mySparseArrays[4] = new MySparseArray(4, 2, 7);
mySparseArrays[5] = new MySparseArray(5, 5, 5);
// 遍历
for (int i = 0; i < mySparseArrays[0].getRow(); i++) {
for (int j = 0; j < mySparseArrays[0].getCol(); j++) {
int k;//这个字段用来记录有值的下标
//第一行记录为0,要跳过第一行
for (k = 1; k < mySparseArrays.length; k++) {
if (mySparseArrays[k].getRow() == i && mySparseArrays[k].getCol() == j) {
break;
}
}
if (k < mySparseArrays.length) {
System.out.print(mySparseArrays[k].getVal() + " ");
} else {
System.out.print(0 + " ");
}
}
//换行
System.out.println();
}
值为:
0 0 0 0 0 0 0 0 0
0 3 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
1 4 0 0 0 0 0 0 0
0 0 7 0 0 0 0 0 0
0 0 0 0 0 5 0 0 0
0 0 0 0 0 0 0 0 0