> 文档中心 > java手撸数据结构--数组(无序、有序、稀疏)

java手撸数据结构--数组(无序、有序、稀疏)


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 

jcg路由器知识网