一,数组基础及注意事项
1,用来储存一组相同的类型的数据.
2,在内存中,分配连续的空姐,数组创建时要指定容量(大小).
3,创建格式: 数据类型 []数组名
int[] arr = new int[10] int[] arr2 = {1,2,3,4}.
4,索引--访问数组时通过索引进行操作.
(注意:一定要理解索引的含义,在数据结构的学习中基本每次都用,索引简单的可以理解为,待插入元素,即,还没有赋值的第一个元素.)
5.索引从0开始,最大为数组名.length-1;
6,常见的错误:
NullPointException ArrayIndexOutOfBoundsException 即我们常说的空指针h=和越界.
7,常见的数组:字符串,对象数组,哈希表
二,演示数组的使用,及数组的方法使用
使用数组时,最重要的就是数组的
索引
,通过索引可以对数组进行改和查操作。
接下来用图 来演示
1,向数组中添加元素
2,向指定位置添加元素
3,向数组头添加元素
4,获取指定位置的元素和修改指定位置的元素
5,包含、搜索和删除元素
首先:对int类型的数组进行操作
接下来让我们手撕代码.:
import java.util.Arrays; import java.util.Random; // 封装属于自己的数组 public class MyArray { private int[] data; // 底层数据结构 private int size;// 用来保存实际存放元素的个数 public MyArray() { this(100); } public MyArray(int capacity) { this.data = new int[capacity]; this.size = 0; } // 判断数组是否为空 public boolean isEmpty() { return this.size == 0; } // 获取数组实际存放元素的个数 public int getSize() { return this.size; } // 对数组进行操作 /* * 1、增加的方法 发现:this.size指向待插入元素的位置,因此,可以在this.size位置增加元素 在头部增加: 1》 将数组中的元素后移,2》 将val添加到索引为0的位置 * 在任意位置添加 */ /** * 在尾部添加 * * @param val val */ public void addTail(int val) { add(this.size, val); } /** * 在头部添加 * * @param val val */ public void addHead(int val) { add(0, val); } /** * 在任意位置添加 * * @param position 插入的位置 * @param val 插入的值 */ public void add(int position, int val) { if (position < 0 || position > this.size) { throw new IllegalArgumentException("position is invalid"); } for (int i = this.size - 1; i >= position; i--) { this.data[i + 1] = this.data[i]; } this.data[position] = val; this.size += 1; } @Override public String toString() { StringBuilder sb = new StringBuilder(); for (int i = 0; i < this.size; i++) { sb.append(this.data[i] + ","); } String result = sb.toString(); return result.substring(0, result.length() - 1); } //获取指定位置的元素 public int getElementByIndex(int index) { if (index < 0 || index >= this.size) { throw new IllegalArgumentException("index is invalid"); } return this.data[index]; } // 修改指定位置的元素 public void setElementByIndex(int index, int val) { if (index < 0 || index >= this.size) { throw new IllegalArgumentException("index is invalid"); } this.data[index] = val; } // cotains 用来判断数组中是否包含指定的元素 public boolean contains(int searchVal) { for (int i = 0; i < this.size; i++) { if (this.data[i] == searchVal) { return true; } } return false; } // 查找指定元素在数组中的索引 public int findIndex(int searchVal) { for (int i = 0; i < this.size; i++) { if (this.data[i] == searchVal) { return i; } } return -1; } // 删除数组中最后一个元素 public int removeFromTail() { if (isEmpty()) { throw new IllegalArgumentException("this array is null!"); } return this.data[--this.size]; } // 删除数组中的第一个元素 public int removeFromHead() { if (isEmpty()) { throw new IllegalArgumentException("this array is null!"); } // 1、先保存数组中的第一个元素 int result = this.data[0]; // 2、将数组从索引为1的位置进行前移 for (int i = 1; i < this.size; i++) { this.data[i - 1] = this.data[i]; } this.size--; return result; } // 删除指定位置的元素 public int removeByIndex(int index) { if (index < 0 || index >= this.size) { throw new IllegalArgumentException("index is invalid!"); } int result = this.data[index]; // 从索引为index位置的元素进行前移 for (int i = index; i < this.size - 1; i++) { this.data[i] = this.data[i + 1]; } this.size--; return result; } // 删除指定的元素 public void remove(int val) { for (int i = 0; i < this.size; ) { if (this.data[i] == val) { // 删除元素---将后面的元素前移,然后更新size for (int j = i; j < this.size - 1; j++) { this.data[j] = this.data[j + 1]; } this.size -= 1; } else { i++; } } }
}
我们要进行任意数据类型的数组,这时就要使用泛型来进行操作.
接下来让我们手撕代码.在上述我们自己写的int类型数组进行修改,添加泛型.
import java.util.Random; // 封装属于自己的数组,使用泛型 public class MyArray2<T> { private T[] data; // 底层数据结构 private int size;// 用来保存实际存放元素的个数 private int capacity; // 表示容积 public MyArray2() { this(100); } public MyArray2(int capacity) { this.capacity = capacity; this.data = (T[]) new Object[this.capacity]; this.size = 0; } // 获取容积的方法 public int getCapacity() { return this.capacity; } // 判断数组是否为空 public boolean isEmpty() { return this.size == 0; } // 获取数组实际存放元素的个数 public int getSize() { return this.size; } // 对数组进行操作 /* * 1、增加的方法 发现:this.size指向待插入元素的位置,因此,可以在this.size位置增加元素 在头部增加: 1》 将数组中的元素后移,2》 将val添加到索引为0的位置 * 在任意位置添加 */ /** * 在尾部添加 * * @param val val */ public void addTail(T val) { add(this.size, val); } /** * 在头部添加 * * @param val val */ public void addHead(T val) { add(0, val); } /** * 在任意位置添加 * * @param position 插入的位置 * @param val 插入的值 */ public void add(int position, T val) { if (position < 0 || position > this.size) { throw new IllegalArgumentException("position is invalid"); } // 在增加之前,判断数组是否已满,如果已满,要进行扩容 if (this.size == this.capacity) { // 扩容操作 resize(this.capacity*2); } for (int i = this.size - 1; i >= position; i--) { this.data[i + 1] = this.data[i]; } this.data[position] = val; this.size += 1; } // 改变容积的方法 private void resize(int newCapacity) { System.out.println("--------resize--------"); // 2、 创建一个新数组 T[] newArr = (T[]) new Object[newCapacity]; // 3、将原来数组的内容转移到新数组 for (int i = 0; i < this.size; i++) { newArr[i] = this.data[i]; } // 4、将newArr赋值给 this.data this.data = newArr; // 5、将newCapacity 赋值给this.capacity this.capacity = newCapacity; } @Override public String toString() { StringBuilder sb = new StringBuilder(); for (int i = 0; i < this.size; i++) { sb.append(this.data[i] + ","); } String result = sb.toString(); return result.substring(0, result.length() - 1); } //获取指定位置的元素 public T getElementByIndex(int index) { if (index < 0 || index >= this.size) { throw new IllegalArgumentException("index is invalid"); } return this.data[index]; } // 修改指定位置的元素 public void setElementByIndex(int index, T val) { if (index < 0 || index >= this.size) { throw new IllegalArgumentException("index is invalid"); } this.data[index] = val; } // cotains 用来判断数组中是否包含指定的元素 public boolean contains(T searchVal) { for (int i = 0; i < this.size; i++) { if (this.data[i].equals(searchVal)) { return true; } } return false; } // 查找指定元素在数组中的索引 public int findIndex(T searchVal) { for (int i = 0; i < this.size; i++) { if (this.data[i].equals(searchVal)) { return i; } } return -1; } // 删除数组中最后一个元素 public T removeFromTail() { return removeByIndex(this.size-1); } // 删除数组中的第一个元素 public T removeFromHead() { return removeByIndex(0); } // 删除指定位置的元素 public T removeByIndex(int index) { if (index < 0 || index >= this.size) { throw new IllegalArgumentException("index is invalid!"); } T result = this.data[index]; // 从索引为index位置的元素进行前移 for (int i = index; i < this.size - 1; i++) { this.data[i] = this.data[i + 1]; } this.size--; if(this.size <= this.capacity/2 && this.capacity/2>1){ resize(this.capacity/2); } return result; } // 删除指定的元素 public void remove(int val) { for (int i = 0; i < this.size; ) { if (this.data[i].equals(val)) { // 删除元素---将后面的元素前移,然后更新size for (int j = i; j < this.size - 1; j++) { this.data[j] = this.data[j + 1]; } this.size -= 1; } else { i++; } } // 删除之后,进行判断是否要进行缩容,如果需要缩容,缩到原容积的1/2 if(this.size <= this.capacity/2 && this.capacity/2>1){ resize(this.capacity/2); } } }
代码较长希望有心人可以看完.
三,数组的复杂度分析.
我们对数组的逻辑有了简单的了解,就对数组的复杂度进行分析,后面可以通过比较复杂度,来选择合适的数据结构来储存数据.
1,分析动态数组的时间复杂度
(1),添加操作
1,addLast(e) O(n)
2,addFirst(e) O(1) 渐进时间复杂度
3,add(index,e) O(n^2) 描述n趋近于无穷的情况