一:定义

数组:把一些数据码成一排进行存放

数组结构之数组_数组

 

 

 Java中提供的数组具有一定的局限:索引可以是有语意,也可以是没有语意的。比如像上文我们提供数组,是按成绩最后一个位当作索引来存还是随机存放在数组中呢?当然,并非所有有语意的索引都适应与数组。例如身份证号:11010319852166666,若我们要存放在数组中,这个数字很大又很浪费,不知道要以什么索引来存放。这一篇文章主要处理没有索引语意的情况。

 

那么,接下来我们就制作属于我们的自己的数组。需要解决如下几个问题:

索引没有语意,如何表示没有元素?

如何添加元素,如何删除元素?如何修改,插入元素等等。

 

二:制作属于自己的数组

2.1 向数组中添加元素,相当于在数组末添加元素

数组结构之数组_构造函数_02

 

 

 2.2 向指定位置添加元素

数组结构之数组_i++_03

 

 数组结构之数组_时间复杂度_04

 

 数组结构之数组_数组_05

 

 数组结构之数组_i++_06

 

 

 2.3 向指定位置删除元素

删除索引为1的元素

 数组结构之数组_构造函数_07

 

 数组结构之数组_构造函数_08

 

 数组结构之数组_数组_09

 

 最后指向size这个位置的数组没必要删掉,因为我们设置了size,所以访问不到

2.4 实现代码~

数组结构之数组_时间复杂度_10数组结构之数组_构造函数_11
  1 public class Array {
  2     private int []data;
  3     private int size;
  4     //构造函数,传入数组的实际容量capacity构造函数Array
  5     public  Array(int capacity)
  6     {
  7         data = new int[capacity];
  8         size = 0;
  9     }
 10     //构造无参函数,采取默认数组的容量capacity
 11     public Array()
 12     {
 13      data = new int[10];
 14      size = 0;
 15     }
 16     //获取数组的容量(长度)
 17     public int getCapacity()
 18     {
 19         return data.length;
 20     }
 21     //获取数组的元素个数
 22     public int getSize()
 23     {
 24         return size;
 25     }
 26     //返回数组是否为空
 27     public  boolean isEmpty()
 28     {
 29         return size == 0;
 30     }
 31     //在index索引的位置插入一个新元素e
 32     public void add(int index , int e)
 33     {
 34         //判断当前数组是否为满
 35         if(size == data.length)
 36         {
 37             throw  new IllegalArgumentException("Add failded. Array is full ");
 38         }
 39         //判断插入位置是否合法
 40         if(index < 0 || index > size )
 41         {
 42             throw  new IllegalArgumentException("Add failded . Require index >= 0 and index <= size.");
 43         }
 44         for(int i =  size - 1 ;i>=index;i--)
 45         {
 46             data[ i + 1] = data[i];
 47         }
 48         data[index] = e;
 49         size++;
 50     }
 51     //在向所有元素后添加一个新元素
 52     public void addLast(int e)
 53     {
 54         add(size,e);
 55     }
 56     //在所有元素前添加一个元素
 57     public void addFirst(int e )
 58     {
 59         add(0,e);
 60     }
 61     //获取index索引位置的元素
 62     public int get(int index)
 63     {
 64         if(index < 0 || index >= size)
 65         {
 66             throw  new IllegalArgumentException("Add failded. Index is illegal. ");
 67         }
 68         return data[index];
 69     }
 70     //修改index索引位置的元素为e
 71     public void set(int index,int e)
 72     {
 73         if(index < 0 || index >= size)
 74         {
 75             throw  new IllegalArgumentException("Add failded. Index is illegal. ");
 76         }
 77         data[index] = e;
 78     }
 79     //查找数组中是否有元素e
 80     public boolean contains(int e)
 81     {
 82         for(int i = 0;i<size;i++)
 83         {
 84             if(data[i] == e)
 85             {
 86                 return true;
 87             }
 88         }
 89         return false;
 90     }
 91     //查找数组中元素e所在的索引,如果不存在元素e,则返回-1
 92     public  int find(int e)
 93     {
 94         for(int i = 0;i<size;i++)
 95         {
 96             if(data[i] == e)
 97             {
 98                 return i;
 99             }
100         }
101         return -1;
102     }
103     //从数组中删除index位置的元素,返回删除的元素     
104     public int remove(int index)
105     {
106         if(index < 0 || index >=size)
107         {
108             throw new IllegalArgumentException("Remove failed. Index is illegal.");
109         }
110         int temp = data[index];
111         for(int  i = index;i<size;i++)
112         {
113             data[i] = data[i+1];
114         }
115         size--;
116         return temp;
117     }
118     //从数组中删除第一个元素,返回删除的元素
119     public int removeFirst()
120     {
121         return remove(0);
122     }
123     //从数组中删除最后一个元素,返回删除的元素
124     public int removeLast()
125     {
126         return remove(size - 1 );
127     }
128     //从数组中删除元素e
129     public void removeElement(int e)
130     {
131         int index = find(e);
132         if(index!=-1)
133         {
134             remove(index);
135         }
136 
137     }
138     //打印Array格式
139     @Override
140     public String toString()
141     {
142         StringBuilder res = new StringBuilder();
143         res.append(String.format("Array size  = %d , capacity = %d\n",size,data.length));
144         res.append('[');
145         for(int i = 0;i<size;i++)
146         {
147             res.append(data[i]);
148             if(i!=size-1)
149             {
150                 res.append(",");
151             }
152         }
153         res.append(']');
154         return res.toString();
155     }
156 }
View Code

三:改进版的动态数组

上面我们创建的数组是静态数组,也就是长度是固定的~当我们的数组长度不够怎么办或者我们不知道要创建多大的数组怎么办?那么我们就要创建一个动态数组

思路:

1、当data数组不够用的时候,那么我们创建一个比当前数组newData大一倍的数组

数组结构之数组_构造函数_12

 

2、将当前数组的元素全部复制一份到newData

 

数组结构之数组_构造函数_13

 

 

 

 

 

 3、把data指向newData,完成~

 数组结构之数组_构造函数_14

 

 这里存在1个疑问:

1、为什么要创建一个比我们原先的数组大一倍,而直接在原来的基础上增加100 or 1000的长度呢?

因为有时候我们创建100或者1000,可能不需要这么大的空间,而且还有一个可能就是我们创建太小的话,可能需要多次从原来的数组复制到另外一个数组上,这样的频率会比较高,很浪费空间。

2、当我们正在删除元素的时候,发现删除之后数组的空间利用率比较小的时候,我们可以尝试把容积变小

if(size  == data.length / 2)
{
resize(data.length/2);
}
return ret;

 3、实现代码:

数组结构之数组_时间复杂度_10数组结构之数组_构造函数_11
  1 public class Array {
  2 
  3     private int[] data;
  4     private int size;
  5 
  6     // 构造函数,传入数组的容量capacity构造Array
  7     public Array(int capacity){
  8         data = new int[capacity];
  9         size = 0;
 10     }
 11 
 12     // 无参数的构造函数,默认数组的容量capacity=10
 13     public Array(){
 14         this(10);
 15     }
 16 
 17     // 获取数组的容量
 18     public int getCapacity(){
 19         return data.length;
 20     }
 21 
 22     // 获取数组中的元素个数
 23     public int getSize(){
 24         return size;
 25     }
 26 
 27     // 返回数组是否为空
 28     public boolean isEmpty(){
 29         return size == 0;
 30     }
 31 
 32     // 在index索引的位置插入一个新元素e
 33     public void add(int index, int e){
 34 
 35         if(index < 0 || index > size)
 36             throw new IllegalArgumentException("Add failed. Require index >= 0 and index <= size.");
 37 
 38         if(size == data.length)
 39             resize(2 * data.length);
 40 
 41         for(int i = size - 1; i >= index ; i --)
 42             data[i + 1] = data[i];
 43 
 44         data[index] = e;
 45 
 46         size ++;
 47     }
 48 
 49     // 向所有元素后添加一个新元素
 50     public void addLast(int e){
 51         add(size, e);
 52     }
 53 
 54     // 在所有元素前添加一个新元素
 55     public void addFirst(int e){
 56         add(0, e);
 57     }
 58 
 59     // 获取index索引位置的元素
 60     public int get(int index){
 61         if(index < 0 || index >= size)
 62             throw new IllegalArgumentException("Get failed. Index is illegal.");
 63         return data[index];
 64     }
 65 
 66     // 修改index索引位置的元素为e
 67     public void set(int index, int e){
 68         if(index < 0 || index >= size)
 69             throw new IllegalArgumentException("Set failed. Index is illegal.");
 70         data[index] = e;
 71     }
 72 
 73     // 查找数组中是否有元素e
 74     public boolean contains(int e){
 75         for(int i = 0 ; i < size ; i ++){
 76             if(data[i] == e)
 77                 return true;
 78         }
 79         return false;
 80     }
 81 
 82     // 查找数组中元素e所在的索引,如果不存在元素e,则返回-1
 83     public int find(int e){
 84         for(int i = 0 ; i < size ; i ++){
 85             if(data[i] == e)
 86                 return i;
 87         }
 88         return -1;
 89     }
 90 
 91     // 从数组中删除index位置的元素, 返回删除的元素
 92     public int remove(int index){
 93         if(index < 0 || index >= size)
 94             throw new IllegalArgumentException("Remove failed. Index is illegal.");
 95 
 96         int ret = data[index];
 97         for(int i = index + 1 ; i < size ; i ++)
 98             data[i - 1] = data[i];
 99         size --;
100         if(size == data.length / 2)
101             resize(data.length / 2);
102         return ret;
103     }
104 
105     // 从数组中删除第一个元素, 返回删除的元素
106     public int removeFirst(){
107         return remove(0);
108     }
109 
110     // 从数组中删除最后一个元素, 返回删除的元素
111     public int removeLast(){
112         return remove(size - 1);
113     }
114 
115     // 从数组中删除元素e
116     public void removeElement(int e){
117         int index = find(e);
118         if(index != -1)
119             remove(index);
120     }
121 
122     @Override
123     public String toString(){
124 
125         StringBuilder res = new StringBuilder();
126         res.append(String.format("Array: size = %d , capacity = %d\n", size, data.length));
127         res.append('[');
128         for(int i = 0 ; i < size ; i ++){
129             res.append(data[i]);
130             if(i != size - 1)
131                 res.append(", ");
132         }
133         res.append(']');
134         return res.toString();
135     }
136 
137     // 将数组空间的容量变成newCapacity大小
138     private void resize(int newCapacity){
139 
140         int[] newData = new int[newCapacity];
141         for(int i = 0 ; i < size ; i ++)
142             newData[i] = data[i];
143         data = newData;
144     }
145 }
View Code

这二段代码其实本质没发生多大变化,只是修改个别东西!

 

四、总结

数组最大的优点:快速查询,最好应用于“索引有语意”的情况。

增、删 的时间复杂度为:O(n)。

改、查 在未知索引的情况下时间复杂度为:O(n), 在已知索引的情况下时间复杂度为:O(1)。