数组

链表

队列

1、数组实现,简易版,队尾入,队首出,没有加边界限制条件。

时间复杂度比较高,入队是O(1),出队都O(n)

  1. public class MyQueue {
  2. private int size; //元素个数
  3. private int[] data; //存储元素的数组
  4. public MyQueue(int cap){
  5. this.size = 0;
  6. this.data = new int[cap];
  7. }
  8. //入队
  9. public void push(int n){
  10. if(size == data.length){
  11. resize();
  12. }
  13. data[size] = n;
  14. size++;
  15. }
  16. //扩容,每次扩大2倍
  17. private void resize() {
  18. int[] temp = new int[data.length * 2];
  19. for (int i = 0; i < data.length; i++) {
  20. temp[i] = data[i];
  21. }
  22. this.data = temp;
  23. }
  24. //出队,从对首出,这样每出一次都需要移动一次数组
  25. public int pop(){
  26. if(size == 0){
  27. return -1;
  28. }
  29. int re = data[0];
  30. for (int i = 0; i < size - 1; i++) {
  31. data[i] = data[i + 1];
  32. }
  33. size--;
  34. return re;
  35. }
  36. //测试
  37. public static void main(String[] args) {
  38. MyQueue myQueue = new MyQueue(10);
  39. System.out.println(myQueue.size);
  40. myQueue.push(12);
  41. myQueue.push(45);
  42. myQueue.push(25);
  43. myQueue.push(66);
  44. myQueue.push(36);
  45. for (int i = 0; i <5; i++) {
  46. System.out.println(myQueue.pop());
  47. System.out.println("size:"+ myQueue.size);
  48. }
  49. System.out.println(myQueue.size);
  50. }
  51. }

2、数组实现,升级版,引入头指针,提升时间复杂度

上一种实现里,有一个size表示元素个数,可以表示队列的尾结点,这里引入一个表示头结点的指针,每次入队出队直接操作头尾指针位置的元素,时间复杂度都是O(1),当尾结点移动到数组尾部时需要进行移动数据,时间复杂度为O(n),也就是说,假使初始化大小为100,那么前面100次push的时间复杂度都是O(1),再次进行push的时候进行移动元素或者扩容,时间复杂度为O(n),等于是100次O(1)+1次O(n)。整体来说有不少提升

  1. public class MyQueuePlus {
  2. private int[] data;
  3. private int head; //头指针,用于出队
  4. private int tail; //尾指针,用于入队
  5. public MyQueuePlus(int cap){
  6. this.data = new int[cap];
  7. this.head = 0;
  8. this.tail = 0;
  9. }
  10. //入队
  11. public void push(int n){
  12. //判断扩容
  13. if(tail == data.length){
  14. resize();
  15. }
  16. data[tail] = n;
  17. tail++;
  18. }
  19. //扩容,出站后数组前面的位置就空出来了,如果元素个数不多,不需要扩容,只需重新整理一下队列中的元素位置即可
  20. private void resize() {
  21. int n = tail - head;
  22. int resize = Math.max(n * 2,data.length);
  23. int[] temp = new int[resize];
  24. for (int i = 0; i < tail-head; i++){
  25. temp[i] = data[head+i];
  26. }
  27. head = 0;
  28. tail = n;
  29. this.data = temp;
  30. }
  31. //出队
  32. public int pop(){
  33. return data[head++];
  34. }
  35. public static void main(String[] args) {
  36. MyQueuePlus queue = new MyQueuePlus(5);
  37. queue.push(2);
  38. queue.push(5);
  39. queue.push(3);
  40. queue.push(4);
  41. queue.pop();
  42. queue.pop();
  43. queue.push(8); //尾指针已到达数组最后
  44. queue.push(15); //触发一次整理(扩容)
  45. System.out.println(queue.data.length);
  46. System.out.println(queue.head);
  47. System.out.println(queue.tail);
  48. }
  49. }

3、用链表实现

用链表实现比较简单,而且时间复杂度也只有O(1),还不涉及到扩容问题,但是正因为这样,链表具有天然的扩展性,使用的时候更需要注意内存问题,只要你不限制,理论上可以占完整个内存。所以可以加在初始化的时候给一个大小,在入队列的时候进行判断一下。这里没有实现。

  1. public class MyQueueWithLinked {
  2. private int size; //记录节点数量
  3. private Node head; //头结点,用于出队
  4. private Node tail; //尾结点,用户入队
  5. //初始化
  6. public MyQueueWithLinked(){
  7. this.size = 0;
  8. this.head = null;
  9. this.tail = null;
  10. }
  11. //入队
  12. public void push(int n){
  13. Node node = new Node(n);
  14. if(size == 0){ //队列为空时
  15. head = node;
  16. tail = node;
  17. }else { //队列为空时,直接插入到队尾
  18. tail.next = node;
  19. tail = node;
  20. }
  21. size++;
  22. }
  23. //出队列
  24. public int pop(){
  25. int re;
  26. if(size == 0){ //队列为空
  27. re = -1;
  28. }else {
  29. re = head.value; //从头节点出队,
  30. head= head.next; //将头结点指向下一个节点
  31. size--;
  32. }
  33. return re;
  34. }
  35. //测试
  36. public static void main(String[] args) {
  37. MyQueueWithLinked queue = new MyQueueWithLinked();
  38. queue.push(23);
  39. queue.push(5);
  40. queue.push(66);
  41. queue.pop();
  42. queue.push(17);
  43. queue.push(99);
  44. queue.push(33);
  45. for (int i = 0; i < 5; i++) {
  46. System.out.println(queue.pop());
  47. }
  48. }
  49. }
  50. //用来表示链表的节点,其实本质上来说,一个链表就是一个节点,因为永远可以通过next来找到下一个节点,直到找到所有节点。
  51. class Node{
  52. int value;
  53. Node next;
  54. public Node(int value){
  55. this.value = value;
  56. this.next = null;
  57. }
  58. }