自定义数组类
功能
- 获取元素个数
- 获取数组容量
- 动态扩容
-
注意点
移除节点
移除时,索引位置之后的元素全部往前移一位,从前往后移
for (int i = index + 1; i < size; i++) {data[i - 1] = data[i];}
添加节点
添加时,索引位置开始的元素全部往后移一位,从后往前移
for (int i = size - 1; i >= index; i--) {data[i + 1] = data[i];}
代码
```java public class MyArray
{ private T[] data; private Integer size;
public MyArray(Integer capacity) {
data = (T[]) new Object[capacity];size = 0;
}
public MyArray() {
this(10);
}
/**
- 元素个数 *
- @return java.lang.Integer
- @author YangYudi
@date 2020/12/25 15:25 */ public Integer getSize() { return size; }
/**
- 数组容量 *
- @return java.lang.Integer
- @author YangYudi
@date 2020/12/25 15:25 */ public Integer getCapacity() { return data.length; }
/**
- 判空 *
- @return boolean
- @author YangYudi
@date 2020/12/28 15:50 */ public boolean isEmpty() { return size == 0; }
/**
- 数组扩容 *
- @param newSize 新大小
- @return void
- @author YangYudi
@date 2020/12/25 15:46 */ private void resize(Integer newSize) { T[] newData = (T[]) new Object[newSize]; for (int i = 0; i < size; i++) {
newData[i] = data[i];
} data = newData; }
public void addLast(T e) { add(size, e); }
public void addFirst(T e) { add(0, e); }
/**
- 添加 *
- @param index 下标
- @param e 对象
- @author YangYudi
@date 2020/12/28 15:50 */ public void add(Integer index, T e) { if (size == data.length) {
Integer length = data.length;//通过位运算得到新长度 借鉴arraylistInteger resize = length + (length >> 1);resize(resize);
} if (index < 0 || index > size) {
throw new IllegalArgumentException("下标不合法");
} for (int i = size - 1; i >= index; i—) {
data[i + 1] = data[i];
} data[index] = e; size++; }
/**
- 判断有没有 *
- @param e 对象
- @author YangYudi
- @date 2020/12/28 15:50
@return boolean */ public boolean contains(T e) { for (int i = 0; i < size; i++) {
if (data[i].equals(e)) {return true;}
} return false; }
/**
- 判断对象存不存在 *
- @param e 对象
- @author YangYudi
- @date 2020/12/28 15:51
@return java.lang.Integer */ public Integer find(T e) { for (int i = 0; i < size; i++) {
if (data[i].equals(e)) {return i;}
} return -1; }
public T get(Integer index) { if (index < 0 || index >= size) {
throw new IllegalArgumentException("下标不合法");
} return data[index]; }
public T getLast() { return get(size - 1); }
public T getFirst() { return get(0); }
public void set(Integer index, T e) { if (index < 0 || index >= size) {
throw new IllegalArgumentException("下标不合法");
} data[index] = e; }
public T removeFirst() { return remove(0); }
public T removeLast() { return remove(size - 1); }
public void removeElement(T e) { int index = find(e); if (index != -1) {
remove(index);
} }
public T remove(Integer index) { if (index < 0 || index >= size) {
throw new IllegalArgumentException("下标不合法");
} T temp = data[index]; for (int i = index + 1; i < size; i++) {
data[i - 1] = data[i];
} size—; data[size] = null; return temp; }
@Override public String toString() { return “MyArray{“ +
"data=" + Arrays.toString(data) +", size=" + size +'}';
}
}
<a name="vp7G4"></a># 基于数组实现栈<a name="DqAWP"></a>## 功能先进后出,判空,获取元素个数,查看栈顶<a name="wj6TR"></a>## 代码刚好调用之前自定义的数组类,使得自定义栈变得非常简单<br />Stack<E>是自定义接口```javapublic class ArrayStack<E> implements Stack<E> {private MyArray<E> array;public ArrayStack(int capacity){array = new MyArray<>(capacity);}public ArrayStack() {array = new MyArray<>();}@Overridepublic int getSize() {return array.getSize();}@Overridepublic boolean isEmpty() {return array.isEmpty();}@Overridepublic void push(E e) {array.addLast(e);}@Overridepublic E pop() {return array.removeLast();}@Overridepublic E peek() {return array.getLast();}@Overridepublic String toString() {return "ArrayStack{" +"array=" + array +'}';}}
基于数组实现队列
功能
先进先出,判空,获取元素个数,获取队头队尾
代码
同样使用自定义数组类实现起来变得很简单
Queue
public class ArrayQueue<E> implements Queue<E> {private MyArray<E> array;public ArrayQueue(int capacity) {array = new MyArray<>(capacity);}public ArrayQueue() {array = new MyArray<>();}@Overridepublic int getSize() {return array.getSize();}@Overridepublic boolean isEmpty() {return array.isEmpty();}@Overridepublic void enqueue(E e) {array.addLast(e);}@Overridepublic E dequeue() {return array.removeFirst();}@Overridepublic E getFirst() {return array.getFirst();}@Overridepublic E getEnd() {return array.getLast();}@Overridepublic String toString() {return "ArrayQueue{" +"array=" + array +'}';}
此队列不是循环队列
测试一下每次出队完,后面的元素也覆盖
问题
出队时,移出队头元素,然后每个元素向前挪一位,时间复杂度是O(N),所以要使用循环队列进行改善
循环队列
注意点
需要定义两个变量front和tail用于指向队头元素和队尾元素下标,tail指向队尾元素的下一个下标
循环队列定义:
队空 front == tail
队满 (tail + 1) % data.length == front
出队 front = (front + 1) % data.length
入队 tail = (tail + 1) % data.length
需要浪费一个空间用于判断
代码
public class LoopQueue<E> implements Queue<E> {private E[] data;private int front;private int tail;private int size;public LoopQueue(int capacity) {//因为要有意浪费一个数组所以容量要比传来的+1data = (E[]) new Object[capacity + 1];front = 0;tail = 0;size = 0;}public LoopQueue() {this(10);}private int getCapacity() {return data.length - 1;}@Overridepublic int getSize() {return size;}@Overridepublic boolean isEmpty() {return front == tail;}@Overridepublic void enqueue(E e) {if ((tail + 1) % data.length == front) {resize(getCapacity() * 2);}data[tail] = e;tail = (tail + 1) % data.length;size++;}private void resize(int newSize) {E[] newData = (E[]) new Object[newSize + 1];for (int i = 0; i < size; i++) {//原数组要通过偏移量获取下标newData[i] = data[(i + front) % data.length];}data = newData;front = 0;tail = size;}@Overridepublic E dequeue() {if (isEmpty()) {throw new IllegalArgumentException("队列为空");}E temp = data[front];data[front] = null;front = (front + 1) % data.length;size--;//如果数组元素个数为数组容量的4分之1就进行缩容if (size == getCapacity() / 4 && getCapacity() / 2 != 0) {resize(getCapacity() / 2);}return temp;}@Overridepublic E getFirst() {if (isEmpty()) {throw new IllegalArgumentException("队列为空");}return data[front];}@Overridepublic E getEnd() {return data[tail - 1];}@Overridepublic String toString() {return "LoopQueue{" +"data=" + Arrays.toString(data) +", front=" + front +", tail=" + tail +", size=" + size +'}';}}
