数据结构学习笔记(一)数组

基本概念

所谓数组,是有序的元素序列。也就是把数据码成一排存放的一种结构。

最大的优点

快速查询,根据索引可以快速查找相应的元素

二次封装自己的数组(相当于Java中的ArrayList)

一个数组应该具备的功能(并不固定,还可以扩充一些功能)

  • 获取数组的初始容量
  • 获取数组中元素的个数
  • 判断数组是否为空
  • 添加元素
  • 删除元素
  • 修改元素
  • 查找元素
  1 /**
  2  * 动态数组
  3  * @param <E>
  4  */
  5 public class MyArray<E> {
  6     /**
  7      * 元素集合
  8      */
  9     private E[] data;
 10 
 11     /**
 12      * 数组中元素个数
 13      */
 14     private int size;
 15 
 16     /**
 17      * 数组当前容量
 18      */
 19     private int capacity;
 20 
 21     public MyArray(int capacity) {
 22         data = (E[]) new Object[capacity];
 23         size = 0;
 24     }
 25 
 26     public MyArray() {
 27         capacity = 10;
 28         data = (E[]) new Object[capacity];
 29         size = 0;
 30     }
 31 
 32     public int getSize() {
 33         return size;
 34     }
 35 
 36     public int getCapacity() {
 37         return capacity;
 38     }
 39 
 40     /**
 41      * 判断数组是否为空
 42      */
 43     public boolean isEmpty() {
 44         return size == 0;
 45     }
 46 
 47     /**
 48      * 在指定位置添加元素--O(n)
 49      * @param index -索引
 50      * @param e     -元素
 51      */
 52     public void add(int index, E e) {
 53         if (size == capacity) {
 54             //扩容2倍大小
 55             resize(2 * capacity);
 56         }
 57         if (index < 0 || index > size) {
 58             throw new IllegalArgumentException("add fail, Required index >=0 && index <=size");
 59         }
 60         for (int i = size - 1; i >= index; i--) {
 61             data[i + 1] = data[i];
 62         }
 63         data[index] = e;
 64         size++;
 65     }
 66 
 67     /**
 68      * 在数组尾部添加元素--O(1)
 69      */
 70     public void addLast(E e) {
 71         add(size, e);
 72     }
 73 
 74     /**
 75      * 在数组首部添加元素--O(n)
 76      */
 77     public void addFirst(E e) {
 78         add(0, e);
 79     }
 80 
 81     /**
 82      * 删除数组中index位置的元素并返回--O(n)
 83      * @param index -索引
 84      * @return
 85      */
 86     public E remove(int index) {
 87         if (index < 0 || index >= size) {
 88             throw new IllegalArgumentException("remove fail, index is illegal");
 89         }
 90         E ret = data[index];
 91         for (int i = index + 1; i < size; i++) {
 92             data[i - 1] = data[i];
 93         }
 94         size--;
 95         //使用泛型后 数组中size位置存放的是类对象的引用 手动释放空间
 96         data[size] = null;
 97         //防止复杂度震荡--以及数组长度为1的情况
 98         if (size == capacity / 4 && capacity / 2 != 0) {
 99             //缩容
100             resize(capacity / 2);
101         }
102         return ret;
103     }
104 
105     /**
106      * 删除数组中第一个元素--O(n)
107      */
108     public E removeFirst() {
109         return remove(0);
110     }
111 
112     /**
113      * 删除数组中最后一个元素--O(n)
114      */
115     public E removeLast() {
116         return remove(size - 1);
117     }
118 
119     /**
120      * 设置数组某个位置的元素
121      * @param index -索引
122      * @param e     -元素
123      */
124     public void set(int index, E e) {
125         if (index < 0 || index >= size)
126             throw new IllegalArgumentException("set fail, index is illegal");
127         data[index] = e;
128     }
129 
130     /**
131      * 查询数组某个索引的元素
132      * @param index -索引
133      * @return E
134      */
135     public E get(int index) {
136         if (index < 0 || index > size) {
137             throw new IllegalArgumentException("get fail, index is illegal");
138         }
139         return data[index];
140     }
141 
142     /**
143      * 查询数组中是否存在元素
144      */
145     public boolean contains(E e) {
146         for (int i = 0; i < size; i++) {
147             if (data[i] == e)
148                 return true;
149         }
150         return false;
151     }
152 
153     /**
154      * 数组长度动态变化
155      * @param newCapacity --新的容量
156      */
157     private void resize(int newCapacity) {
158         E[] newData = (E[]) new Object[newCapacity];
159         for (int i = 0; i < size; i++) {
160             newData[i] = data[i];
161         }
162         data = newData;
163         capacity = newCapacity;
164     }
165 
166     @Override
167     public String toString() {
168         StringBuilder res = new StringBuilder();
169         res.append(String.format("Array: size = %d , capacity = %d\n", size, capacity));
170         res.append('[');
171         for (int i = 0; i < size; i++) {
172             res.append(data[i]);
173             if (i != size - 1) {
174                 res.append(',');
175             }
176         }
177         res.append(']');
178         return res.toString();
179     }
180 }

 

复杂度分析

什么是时间复杂度这里看另外一篇文章https://blog.csdn.net/qq_41523096/article/details/82142747

  • 添加元素---O(n)-------复杂度分析一般考虑最坏的情况
    • 在数组首部添加元素---O(n)---因为向数组头添加元素 需要把每个元素向后挪
    • 在数组尾部添加元素)---O(1)  
    • 在数组指定位置添加元素---O(n/2)=O(n)---平均的情况下添加元素每次需要挪n/2个元素
    • 扩容resize()---O(n)--最坏情况
  • 删除元素---O(n)
    • 删除数组首部元素---O(n)---因为向数组头添加元素 需要把每个元素向前挪
    • 删除数组尾部元素---O(1)  
    • 删除数组指定位置元素---O(n/2)=O(n)
    • 缩容resize()---O(n)--最坏情况
  • 修改元素---set(index,e)---已知索引是O(1)---未知索引是O(n)--因为需要遍历数组中每一个元素
  • 查找元素---已知索引是O(1)---未知索引是O(n)--因为需要遍历数组中每一个元素
    • 根据索引查找元素--O(1)
    • 判断元素是否存在---O(n)---因为需要遍历数组中每一个元素
    • 查找元素对应的索引---O(n)
  • 容量动态变化resize()--不应该考虑最坏情况,这是不合理的,因为不可能每次都触发这个方法--均摊复杂度

假设数组容量是8,使用addLast()方法需要9次操作才触发一次resize(转移8个元素到新数组),一共17次操作,相当于平均每次addLast,进行2次操作,所以均摊计算它的复杂度是O(1);

同理removeLast也是O(1); 同时考虑这两个方法,特殊情况当添加一个元素触发了扩容,然后有删除这个元素触发缩容,造成复杂度震荡.解决方法Lazy 也就是缩容的时候不用那么急

 

转载于:https://www.cnblogs.com/phperpxy/p/10263698.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值