数组
链表
栈
队列
1、数组实现,简易版,队尾入,队首出,没有加边界限制条件。
时间复杂度比较高,入队是O(1),出队都O(n)
public class MyQueue {private int size; //元素个数private int[] data; //存储元素的数组public MyQueue(int cap){this.size = 0;this.data = new int[cap];}//入队public void push(int n){if(size == data.length){resize();}data[size] = n;size++;}//扩容,每次扩大2倍private void resize() {int[] temp = new int[data.length * 2];for (int i = 0; i < data.length; i++) {temp[i] = data[i];}this.data = temp;}//出队,从对首出,这样每出一次都需要移动一次数组public int pop(){if(size == 0){return -1;}int re = data[0];for (int i = 0; i < size - 1; i++) {data[i] = data[i + 1];}size--;return re;}//测试public static void main(String[] args) {MyQueue myQueue = new MyQueue(10);System.out.println(myQueue.size);myQueue.push(12);myQueue.push(45);myQueue.push(25);myQueue.push(66);myQueue.push(36);for (int i = 0; i <5; i++) {System.out.println(myQueue.pop());System.out.println("size:"+ myQueue.size);}System.out.println(myQueue.size);}}
2、数组实现,升级版,引入头指针,提升时间复杂度
上一种实现里,有一个size表示元素个数,可以表示队列的尾结点,这里引入一个表示头结点的指针,每次入队出队直接操作头尾指针位置的元素,时间复杂度都是O(1),当尾结点移动到数组尾部时需要进行移动数据,时间复杂度为O(n),也就是说,假使初始化大小为100,那么前面100次push的时间复杂度都是O(1),再次进行push的时候进行移动元素或者扩容,时间复杂度为O(n),等于是100次O(1)+1次O(n)。整体来说有不少提升
public class MyQueuePlus {private int[] data;private int head; //头指针,用于出队private int tail; //尾指针,用于入队public MyQueuePlus(int cap){this.data = new int[cap];this.head = 0;this.tail = 0;}//入队public void push(int n){//判断扩容if(tail == data.length){resize();}data[tail] = n;tail++;}//扩容,出站后数组前面的位置就空出来了,如果元素个数不多,不需要扩容,只需重新整理一下队列中的元素位置即可private void resize() {int n = tail - head;int resize = Math.max(n * 2,data.length);int[] temp = new int[resize];for (int i = 0; i < tail-head; i++){temp[i] = data[head+i];}head = 0;tail = n;this.data = temp;}//出队public int pop(){return data[head++];}public static void main(String[] args) {MyQueuePlus queue = new MyQueuePlus(5);queue.push(2);queue.push(5);queue.push(3);queue.push(4);queue.pop();queue.pop();queue.push(8); //尾指针已到达数组最后queue.push(15); //触发一次整理(扩容)System.out.println(queue.data.length);System.out.println(queue.head);System.out.println(queue.tail);}}
3、用链表实现
用链表实现比较简单,而且时间复杂度也只有O(1),还不涉及到扩容问题,但是正因为这样,链表具有天然的扩展性,使用的时候更需要注意内存问题,只要你不限制,理论上可以占完整个内存。所以可以加在初始化的时候给一个大小,在入队列的时候进行判断一下。这里没有实现。
public class MyQueueWithLinked {private int size; //记录节点数量private Node head; //头结点,用于出队private Node tail; //尾结点,用户入队//初始化public MyQueueWithLinked(){this.size = 0;this.head = null;this.tail = null;}//入队public void push(int n){Node node = new Node(n);if(size == 0){ //队列为空时head = node;tail = node;}else { //队列为空时,直接插入到队尾tail.next = node;tail = node;}size++;}//出队列public int pop(){int re;if(size == 0){ //队列为空re = -1;}else {re = head.value; //从头节点出队,head= head.next; //将头结点指向下一个节点size--;}return re;}//测试public static void main(String[] args) {MyQueueWithLinked queue = new MyQueueWithLinked();queue.push(23);queue.push(5);queue.push(66);queue.pop();queue.push(17);queue.push(99);queue.push(33);for (int i = 0; i < 5; i++) {System.out.println(queue.pop());}}}//用来表示链表的节点,其实本质上来说,一个链表就是一个节点,因为永远可以通过next来找到下一个节点,直到找到所有节点。class Node{int value;Node next;public Node(int value){this.value = value;this.next = null;}}
