数据结构之数组

1、数据结构研究的是数据如何在计算机中进行组织和存储,使得我们可以高效的获取数据或者修改数据。

  数据结构包含三种结构,线性结构,树结构,图结构。其中,线性结构包含数组,栈,队列,链表,哈希表等等。树结构包含二叉树,二分搜索树,AVL树,红黑树,Treap,Splay,堆,Tril,K-D树,并查集,哈夫曼树等等。图结构包含邻接矩阵,邻接表。

 

2、时间复杂度O(1), O(n), O(logn), O(nlogn),O(n^2),其中,大O描述的是算法的运行时间和输入数据之间的关系,n是指数据元素的个数。O后面的括号中有一个函数,指明某个算法的耗时/耗空间与数据增长量之间的关系。其中的n代表输入数据的量。

 

3、数据结构之数组。数据的查询,修改,删除,增加,动态扩容以及数组的缩容。

  3.1、添加元素的时间复杂度分析。
    1)、addLast(e),时间复杂度O(1),直接在数组最后赋值即可,和数组的容量无关。如果是进行了扩容reszie操作,那么时间复杂度是O(n)。
    2)、addFirst(e),时间复杂度O(n),在数组头部添加元素,需要将所有元素后移一位。
    3)、add(index,e),按照概率论,时间复杂度近似O(n),在该索引index位置插入一个元素e,和index的值有关的,比如index的值等于0或者index等于size。
  3.2、删除元素的时间复杂度分析。
    1)、removeFirst(e),时间复杂度是O(1),如果是进行了缩容reszie操作,那么时间复杂度是O(n)。
    2)、removeLast(e),时间复杂度是O(n)。
    3)、remove(index,e),时间复杂度是O(n)。
  3.3、修改元素的时间复杂度分析。
    1)、set(index,e),时间复杂度是O(1),数组支持随机访问哦。
  3.4、查询元素的时间复杂度分析。
    1)、get(index),时间复杂度是O(1)。
    2)、contains(e),时间复杂度是O(n)。
    3)、find(e),时间复杂度是O(n)。
  3.5、综上所述,增加的时间复杂度是O(n)。删除的时间复杂度是O(n)。修改的时间复杂度是,如果已知索引O(1),未知索引O(n)。查找的时间复杂度是,如果已知索引O(1),未知索引O(n)。

  1 package com.company;
  2 
  3 
  4 /**
  5  *
  6  */
  7 public class Array<E> {
  8 
  9     private E[] data;//定义数组
 10     private int size;//数组实际的长度
 11 
 12     /**
 13      * 构造函数,传入数组的容量capacity构造Array
 14      *
 15      * @param capacity 初始化数据的容量长度
 16      */
 17     public Array(int capacity) {
 18         // 使用泛型,可以创建任意类型的数组类型
 19         data = (E[]) new Object[capacity];
 20         // 初始化数组的实际内容的长度为0
 21         size = 0;
 22     }
 23 
 24     /**
 25      * 无参数的构造函数,默认数组的容量capacity=10
 26      */
 27     public Array() {
 28         // 无参构造函数,指定初始化数组容量长度为0
 29         this(10);
 30     }
 31 
 32     /**
 33      * 获取数组中的元素个数
 34      *
 35      * @return
 36      */
 37     public int getSize() {
 38         // 获取到数组中的元素个数
 39         return size;
 40     }
 41 
 42     /**
 43      * 获取数组的容量
 44      *
 45      * @return
 46      */
 47     public int getCapacity() {
 48         // 获取到数组的容量
 49         return data.length;
 50     }
 51 
 52     /**
 53      * 返回数组是否为空
 54      *
 55      * @return
 56      */
 57     public boolean isEmpty() {
 58         // 判断数组的长度是否为空
 59         return size == 0;
 60     }
 61 
 62 
 63     /**
 64      * 向所有元素后添加一个新元素
 65      *
 66      * @param e
 67      */
 68     public void addLast(E e) {
 69 //        if (size == data.length) {
 70 //            throw new IllegalArgumentException("AddLast failed,Array is full......");
 71 //        } else {
 72 //            在数组的末尾添加一个元素
 73 //            data[size] = e;
 74 //            添加元素以后数组长度加一
 75 //            size++;
 76 //        }
 77 
 78         // 调用公共的方法,其实就是在数组的实际长度后面添加指定的元素的。
 79 
 80         // 调用添加数组的方法,参数一,传入数组实际的长度,参数二,添加的元素
 81         add(size, e);
 82     }
 83 
 84     /**
 85      * 在第一个位置添加元素,在所有元素前添加一个新元素
 86      *
 87      * @param e
 88      */
 89     public void addFirst(E e) {
 90         // 在数组的第一个位置添加元素
 91         add(0, e);
 92     }
 93 
 94 
 95     /**
 96      * 在第index个位置插入一个新元素e
 97      *
 98      * @param index 在第index个位置
 99      * @param e     添加的元素内容
100      */
101     public void add(int index, E e) {
102         // 判断位置index是否小于0或者索引index是否大于数组的实际长度size
103         if (index < 0 || index > size) {
104             throw new IllegalArgumentException("add failed,Require index >= 0 and index <= size.......");
105         }
106 
107         // 判断实际长度size是否等于数组的长度
108         if (size == data.length) {
109             // 可以直接抛出异常
110             // throw new IllegalArgumentException("add failed,Array is full......");
111             // 调用数组扩容的方法,扩容的长度为元数组长度的2倍
112             resize(2 * data.length);
113         }
114 
115         // 添加元素,就是在最后一个位置,将元素添加进去,即size的位置
116         // 从后向前移动,从后面的元素向后移动
117         // 如果传入的index是size,则初始化的位置是size-1,那么i的值大于等于传入的index(即size的值),i递减
118 
119         // int i = size - 1是数组的实际长度的,即最后一个位置的元素
120         // i >= index,是在指定索引位置添加索引
121         // i--是为了将前面的元素向后面移动的。
122         for (int i = size - 1; i >= index; i--) {
123             // 后一个索引位置赋予前一个索引位置的值
124             data[i + 1] = data[i];
125         }
126         // 将元素的内容插入到数组的index索引位置
127         data[index] = e;
128         // 数组的size递增
129         size++;
130     }
131 
132     /**
133      * 私用扩容,扩容数组的长度
134      *
135      * @param newCapacity
136      */
137     private void resize(int newCapacity) {
138         // 使用泛型创建对象,使用new Object的方法创建泛型的对象
139         E[] newData = (E[]) new Object[newCapacity];
140         // 循环,将原数组里面的内容放入到新数组里面,新数组的长度为元素组的2倍
141         for (int i = 0; i < size; i++) {
142             // 将原数组的值赋值给新数组的值
143             newData[i] = data[i];
144         }
145         // 将原数组的值指向新数组,此操作,不影响原数组的正常使用
146         data = newData;
147     }
148 
149     /**
150      * 获取Index索引位置的元素
151      *
152      * @param index
153      * @return
154      */
155     public E get(int index) {
156         // 如果索引index小于0或者索引的长度大于等于实际长度size,则抛出异常
157         if (index < 0 || index >= size) {
158             throw new IllegalArgumentException("add failed,Index is illegal......");
159         }
160         // 返回指定索引位置的数组元素
161         return data[index];
162     }
163 
164     /**
165      * 修改index索引位置的元素e
166      *
167      * @param index
168      */
169     public void set(int index, E e) {
170         // 如果索引index小于0或者索引的长度大于等于实际长度size,则抛出异常
171         if (index < 0 || index >= size) {
172             throw new IllegalArgumentException("add failed,Index is illegal......");
173         }
174         // 则将元素放入到数组的索引index位置
175         data[index] = e;
176     }
177 
178 
179     /**
180      * @return
181      */
182     @Override
183     public String toString() {
184         // 封装数组遍历的内容
185         StringBuilder sb = new StringBuilder();
186         sb.append(String.format("Array : size = %d,capacity = %d\n", size, data.length));
187         sb.append('[');
188         for (int i = 0; i < size; i++) {
189             sb.append(data[i]);
190             if (i != size - 1) {
191                 sb.append(", ");
192             }
193         }
194         sb.append(']');
195         return sb.toString();
196     }
197 
198     /**
199      * 查找数据中是否包含元素e
200      *
201      * @param e
202      * @return
203      */
204     public boolean contains(E e) {
205         // 查看是否包含元素,进行遍历
206         for (int i = 0; i < size; i++) {
207             // 如果数组元素等于传入的元素e
208             if (data[i].equals(e)) {
209                 // 返回true
210                 return true;
211             }
212         }
213         return false;
214     }
215 
216     /**
217      * 查找数组中元素e所在的索引,如果不存在元素e,则返回-1
218      *
219      * @param e
220      * @return
221      */
222     public int find(E e) {
223         // 查看是否包含元素,进行遍历
224         for (int i = 0; i < size; i++) {
225             // 如果数组元素等于传入的元素e
226             if (data[i].equals(e)) {
227                 // 返回该索引位置的索引
228                 return i;
229             }
230         }
231         return -1;
232     }
233 
234     /**
235      * 从数组中删除index位置的元素,返回删除的元素
236      *
237      * @param index 此参数是索引参数
238      * @return
239      */
240     public E remove(int index) {
241         // 如果索引位置小于等于0或者索引位置大于等于数组的实际长度size
242         if (index < 0 || index >= size) {
243             throw new IllegalArgumentException("remove failed,Index is illegal......");
244         }
245 
246         // 返回删除的元素,先获取到要删除的元素
247         E result = data[index];
248         System.out.println(result);
249 
250         // 初始化值是要删除索引的位置加1,且i的值小于实际size的大小,i递减
251 
252         // int i = index + 1,传入进去的删除索引位置的元素
253         // i < size,i小于数组的实际长度
254         // i++,i递增
255         for (int i = index + 1; i < size; i++) {
256             // 将数组元素的值赋值被删除元素的位置上面
257             // 即将数组元素向前移动,即第i位置的索引的数据移动到第i-1位置索引的数据
258             data[i - 1] = data[i];
259         }
260         // 删除元素以后,数组长度size递减1
261         size--;
262         // 将不可访问的位置置空
263         data[size] = null;
264 
265         // 避免出现复杂度震荡
266         // 删除数组长度,缩小容量
267         // data.length / 2 != 0,避免出现创建数组长度为0的数组
268         if (size == data.length / 4 && data.length / 2 != 0) {
269             // 缩容数组的长度
270             resize(data.length / 2);
271         }
272         return result;
273     }
274 
275     /**
276      * 删除数组的第一个元素的值
277      * <p>
278      * 从删除中删除第一个元素,返回删除的元素
279      *
280      * @return
281      */
282     public E removeFirst() {
283         // 删除数组的第一个位置的元素
284         return remove(0);
285     }
286 
287     /**
288      * 从数组中删除最后一个元素,返回删除的元素。
289      *
290      * @return
291      */
292     public E removeLast() {
293         // 删除数组最后一个位置的元素
294         return remove(size - 1);
295     }
296 
297     /**
298      * 从数组中删除元素e
299      *
300      * @param e
301      */
302     public void removeElement(E e) {
303         // 查看数组里面是否有该元素
304         int index = find(e);
305         // 如果查找到存在该元素
306         if (index != -1) {
307             // 调用删除数组元素的方法
308             remove(index);
309         }
310     }
311 
312     public static void main(String[] args) {
313         // 数组添加元素
314         Array<Integer> array = new Array<>(20);
315         for (int i = 0; i < 10; i++) {
316             array.addLast(i);
317         }
318 
319         System.out.println(array.toString());
320 
321         // 在指定位置添加元素
322         array.add(1, 110);
323         System.out.println(array.toString());
324 
325         // 在第一个位置添加元素
326         array.addFirst(-1);
327         System.out.println(array.toString());
328 
329         // 修改index索引位置的元素e
330         array.set(1, 120);
331         System.out.println(array.toString());
332 
333         // 是否包含某个元素
334         boolean contains = array.contains(9);
335         System.out.println(contains);
336 
337         // 删除指定索引位置的元素
338         array.remove(2);
339         System.out.println(array);
340 
341         // 删除第一个索引位置的元素
342         array.removeFirst();
343         System.out.println(array);
344 
345         // 删除最后一个位置的元素
346         array.removeLast();
347         System.out.println(array);
348 
349         // 从数组中删除元素e
350         array.removeElement(110);
351         System.out.println(array);
352     }
353 
354 }

 

作者:别先生

博客园:https://www.cnblogs.com/biehongli/

如果您想及时得到个人撰写文章以及著作的消息推送,可以扫描上方二维码,关注个人公众号哦。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值