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