泛型:泛指一切类型
泛型栈:先进后出,不指定栈类型的栈,用E来指定类型,也可以用其他的,任意,意思就是E可以是int(但是此时不应该是int,而是Integer)、String等,使用时想要什么类型,E就写什么类型
public class Stack<E> {
private E[] arr = (E[]) new Object[10];
// private E[] arr2 = new E[10]; 这种是错误写法,不允许
private int flag = 0;
public void add(E x){
if (flag == arr.length) { //判断数组已满,那就扩容一倍
E[] newArr = (E[]) new Object[arr.length*2];
for (int i=0;i<arr.length;i++){
newArr[i] = arr[i];
}
//此时,原来的arr已经没有被其他变量所指向,内存会将其清除,回收资源
arr = newArr;
}
arr[flag] = x;
flag++;
}
public E get(){
if (flag == 0) {
return null;
}else {
E x = arr[flag-1];
flag--;
return x;
}
}
}
泛型队列:
- 一般用数组来存,因为数组申请的空间很小,而链表则非常大,因为链表是按内存页为单位申请的,一个内存页就4KB,而int类型的数组一个空间就4B
- 普通的队列入队复杂度为O(1),出队是O(n)
- 循环队列用数组存储(因为只有数组能实现循环,链表实现没有意义),入队出队都是O(1),优点很明显,在相同数据量下,所占空间最少且入队、出队的时间复杂度也很低,这就是使用循坏队列的目的
- 循坏队列判断队满:入队指针➖出对指针 = 数组长度,判断队空:入队指针 = 出队指针,同时,只有入队指针与出队指针之间的数据才是有效的(出队就是将其标为无效)
- 循环队列的扩容:
/**
* 泛型队列,即可以适配任何类的队列,这里E就代表队列存放的的类型
* 泛型循环队列
* @param <E>
*/
public class Queue<E> {
private E[] arr = (E[]) new Object[10];
private int addIndex; //入队指针
private int getIndex; //出队指针
/**
* 入队
* @param x
*/
public void add(E x) {
if(addIndex - getIndex == arr.length) { //判断是否满了
E[] arr2 = (E[]) new Object[arr.length * 2];
for(int i = getIndex; i < addIndex; i++) {
arr2[ i % arr2.length ] = arr[i% arr.length ];
}
arr = arr2;
}
arr[addIndex%arr.length] = x;
addIndex++;
}
/**
* 出队
* @return
*/
public E get() {
if(addIndex == getIndex) {//判断是否满了
return null;
}else {
E x = arr[getIndex%arr.length];
getIndex++;
return x;
}
}
}