数据结构和算法(一)–动态数组(Arraylist)
什么是数据结构
- 线性结构;举例:线性表,链表,数组,栈,队列
- 树形结构;举例:二叉树,红黑树,b树
- 图形结构;举例:邻接表,邻接矩形
线性表的特点:
- 表示一组相同类型的数据的有限序列
- 有头节点,尾节点,前驱,后继的概念
头节点:线性表的第一个节点 尾节点:线性表的最后一个节点 前驱:前一个元素是后一个元素的前驱 后继:后一个元素是前一个元素的后继
- 数组也是线性表
数组Array
- 数组是一个连续存储的线性表,它们元素的内存地址是连续的
- 数组本身无法动态的修改容量
- 可以使用动态数组的方法来进行扩容
动态数组的总结和实现(ArrayList)
-
图解动态数组数据结构
-
中心思想和总结
容器里面有一个真正存储数据的数组,然后有一个可以被外部访问到的范围,增加和删除都会改变容器可访问的范围值,访问不能访问的地方会报索引越界错误,动态扩容和缩容是在访问范围和数组长度相差太小或太大时生效,此时会新建一个数组把旧的数组的内容存储到新数组中。 -
代码实现
package com.yldct.gis.custom.list;
public class CustomArrayList<E> implements CustomList {
/**
* 长度
*/
private int size;
/**
* 数组
*/
private Object[] array;
public CustomArrayList() {
this(5);
}
public CustomArrayList(int length) {
array = new Object[length > 5 ? length : 5];
size = 0;
}
/**
* 获取元素的数量
*
* @return
*/
public int size() {
return size;
}
/**
* 是否为空
*
* @return
*/
public boolean isEmpty() {
return size == 0;
}
/**
* 是否包含这个元素
*
* @param element
* @return
*/
public boolean contains(Object element) {
return indexOf(element) != -1;
}
/**
* 添加一个元素
*
* @param element
*/
public void add(Object element) {
dynamicExpansion();
array[size] = element;
size++;
}
/**
* 获取索引处的元素
*
* @param index
* @return
*/
public E get(int index) {
checkIndex(index);
return (E) array[index];
}
/**
* 设置索引位置的值
*
* @param index
* @param element
* @return
*/
public E set(int index, Object element) {
checkIndex(index);
Object oldString = array[index];
array[index] = element;
return (E) oldString;
}
/**
* 在索引处添加一个元素
*
* @param index
* @param element
*/
public void add(int index, Object element) {
if (index < 0 || index > size) {
throw new IndexOutOfBoundsException("索引越界错误:index => " + index + ", size => " + size);
}
dynamicExpansion();
for (int i = size; i >= index; i--) {
array[i] = array[i - 1];
}
array[index] = element;
size++;
}
/**
* 删除索引处元素并返回
*
* @param index
* @return
*/
public E remove(int index) {
checkIndex(index);
dynamicShrinkage();
Object oldString = array[index];
for (int i = index; i < size; i++) {
array[i] = array[i + 1];
}
size--;
return (E) oldString;
}
/**
* 返回元素在数组中的索引
*
* @param element
* @return
*/
public int indexOf(Object element) {
for (int i = 0; i < size; i++) {
if (array[i].equals(element)) return i;
}
return -1;
}
/**
* 清空数组
*/
public void clear() {
size = 0;
}
/**
* 动态扩容
* 左移变大,右移变小(左边是高位,右边是低位)
*/
private void dynamicExpansion() {
// array.length + array.length >> 1;
if (size > array.length >> 1) {
Object[] temp = new Object[array.length << 1];
for (int i = 0; i < size; i++) {
temp[i] = array[i];
}
array = temp;
System.out.println("数组容量变为:" + array.length);
}
}
/**
* 动态缩容
*/
private void dynamicShrinkage() {
if (size < array.length >> 2) {
Object[] temp = new Object[array.length >> 1];
for (int i = 0; i < size; i++) {
temp[i] = array[i];
}
array = temp;
System.out.println("数组容量变为:" + array.length);
}
}
/**
* 检查索引范围
*
* @param index
*/
private void checkIndex(int index) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException("索引越界错误:index => " + index + ", size => " + size);
}
}
@Override
public String toString() {
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < size; i++) {
if (i == 0) {
stringBuilder.append("[");
} else {
stringBuilder.append(",");
}
stringBuilder.append(array[i]);
}
stringBuilder.append("]").append(" ==> 数组长度为:").append(size);
return stringBuilder.toString();
}
}