数组存放
将数据排列成一排存放
注意
数组的下标, 在计算机领域中是从0开始的
数组最大的优点
快速索引
基础使用代码
package com.company;
public class Main {
public static void main(String[] args) {
// 创建数组
int[] scores = new int[10];
int[] scores2 = new int[]{40, 62, 72, 99}; // 创建数组的时候付初始值
// 数组赋值
for (int i = 0; i < 10; i++) {
scores[i] = i;
}
// 数组遍历
for (int i = 0; i < 10; i++) {
System.out.println(scores[i]);
}
// 增强for循环遍历
for (int score : scores) {
System.out.println(score);
}
}
}
封装自己的动态数组类
增加元素
对于数组来说, 添加指定位置的一个元素的时候, 只需要将从指定位置的元素到末尾的元素, 统统往后移动一个元素位置, 然后将添加的指定元素添加到指定位置即可. 同时, 需要维护一下size ( size是数组中元素的个数)
获取和修改元素
直接修改指定下标即可
删除元素
与添加元素原理差不多, 只是删除的时候, 将index后面的所有元素均前移一个元素位置, 则将要删除的元素覆盖了. 即达到删除的目的. 同时, 不要忘记size要减一.
修改元素
直接更改指定下标的元素即可, 但是一定要记得限制下标, 不能出现不合法的下标
查询元素
遍历数组查询元素即可
普遍性
使用泛型使数组能够存放一些自定义类
动态性
每当存放数据将要大于容器的时候, 建立新的大于原来数组的数组, 成为新的容器
删除一个元素的时候, 判断size是否小于原来数组长度的1/2, 如果是, 新建一个长度为1/2的数组作为容器
复杂度分析
O(1), O(n), O(lgn), O(nlogn), O(n^2)
大O是描述的是算法的运行时间和输入数据之间的关系
算法运行时间大致和输入数据之间存在线性关系, 但是在分析的时候是忽略常数的. 比如实际时间T=c1*n+2, 我们忽略常数, 认为算法时间复杂度为O(n)
添加和删除操作
- addLast(e) O(1) 添加resize()操作 O(n) 因为考虑到最坏情况, 所以整体来说, 我们是O(n)级别的操作
- addFirst(e) O(n)
- add(index, e) O(n/2) = O(n)
修改操作
- set(index, e) O(1)
查找操作
- get(e) O(1)
- contain(e) O(n)
- find(e) O(n)
扩容操作
- resize() O(n)
均摊复杂度
由于resize操作在addLast和removeLast不是每次调用的时候都会触发, 那么可以将resize均摊到每次操作中去,
比如 容器容量为10, 那么添加10次操作, 会触发一次resize, resize会进行10次循环拷贝到新的数组. 将resize的10次操作, 均摊到每次添加的操作中, 那么, 添加一个元素, 就相当于进行了两次基本操作.这样看起来, addLast和removeLast都是O(1)级别的操作
代码
package pers.jssd.array;
/**
* @author jssd
* Create 2019-07-21 8:24
*/
public class Array<E> {
private E[] data; // 数组的存储数据
private int size; // 数据实际存储的数据大小
/**
* 构造函数, 构造数组的初始容量
*
* @param capacity 初始的容量大小
*/
@SuppressWarnings("unchecked")
public Array(int capacity) {
data = (E[]) new Object[capacity];
size = 0;
}
/**
* 默认构造, 初始容量默认为10
*/
public Array() {
this(10);
}
/**
* 取得数组的容量大小
*
* @return int 数组的容量
*/
public int getCapactiy() {
return data.length;
}
/**
* 取得数组存储的数据大小
*
* @return 数组存储的数据大小
*/
public int getSize() {
return size;
}
/**
* 查看数组是否为空
*
* @return 如果为空true, 如果不为空false
*/
public boolean isEmpty() {
return size == 0;
}
/**
* 向指定位置添加一个元素
*
* @param index 添加元素的位置
* @param e 要添加的元素
*/
public void add(int index, E e) {
if (index < 0 || index > size) {
throw new IllegalArgumentException("add fall, index is error");
}
if (index == data.length) {
resize(data.length * 2);
}
// 将每个元素从index开始, 向后拷贝一个位置
System.arraycopy(data, index, data, index + 1, size - index);
data[index] = e;
size++;
}
/**
* 向末尾添加元素
*
* @param e 添加的元素
*/
public void addLast(E e) {
add(size, e);
}
/**
* 向开头添加元素
*
* @param e 添加的元素
*/
public void addFirst(E e) {
add(0, e);
}
/**
* 获取指定位置的元素
*
* @param index 获取元素的位置
* @return 返回获取的指定元素
*/
public E get(int index) {
if (index < 0 || index >= size)
throw new IllegalArgumentException("get fall, index is error");
return data[index];
}
/**
* 修改指定位置的元素
* @param index 修改元素的位置
* @param e 修改指定元素新的值
*/
public void set(int index, E e) {
if (index < 0 || index >= size) {
throw new IllegalArgumentException("set error, index is error");
}
data[index] = e;
}
/**
* 查找元素的索引
*
* @param e 查找的元素
* @return -1如果没有找到, 找到则返回相应的索引
*/
public int find(E e) {
for (int i = 0; i < size; i++) {
if (data[i].equals(e)) {
return i;
}
}
return -1;
}
/**
* 查看元素在数组中是否存在
*
* @param e 查看的元素
* @return true则元素存在, false则元素不存在
*/
public boolean contain(E e) {
int index = find(e);
return index != -1;
}
/**
* 删除指定位置的元素
*
* @param index 要删除的元素位置
* @return 删除的元素
*/
public E remove(int index) {
if (index < 0 || index >= size) {
throw new IllegalArgumentException("remove fall, index is error");
}
E ref = data[index];
System.arraycopy(data, index + 1, data, index, size - index - 1);
size--;
if (size == data.length / 4 && data.length / 2 != 0) {
resize(data.length / 2);
}
return ref;
}
/**
* 删除最后的元素
*
* @return 删除的元素
*/
public E removeLast() {
return remove(size - 1);
}
/**
* 删除第一个元素
*
* @return 删除的元素
*/
public E removeFirst() {
return remove(0);
}
/**
* 删除数组中第一次出现的指定元素
*
* @param e 删除的元素
* @return true删除成功, false 删除失败
*/
public boolean removeElement(E e) {
int index = find(e);
if (index != -1) {
remove(index);
return true;
}
return false;
}
/**
* 删除所有指定的元素
* @param e 要删除的元素
* @return 返回删除元素的个数, 如果为0, 则没有删除任何元素
*/
public int removeAllElement(E e){
int index = find(e);
int count = 0;
while (index != -1) {
remove(index);
count ++;
index = find(e);
}
return count;
}
/**
* 对数组进行扩容操作
* @param newCapacity 新的容量
*/
@SuppressWarnings("unchecked")
private void resize(int newCapacity) {
E[] newData = (E[]) new Object[newCapacity];
if (size >= 0) System.arraycopy(data, 0, newData, 0, size);
data = newData;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("Array: size = ").append(size).append(", capacity = ").append(data.length).append("\n");
sb.append("[");
for (int i = 0; i < size; i++) {
sb.append(data[i]);
if (i != size - 1) {
sb.append(", ");
}
}
sb.append("]");
return sb.toString();
}
}