Java数据结构与算法-队列

àì夳堔傛蜴生んèń 2021-11-17 10:32 536阅读 0赞

参考《算法》(第四版)

一、队列的作用

队列是基于先进先出(FIFO)的集合。现实中类似的场景有在银行大厅排队、汽车过收费站排队等。队列的作用在于1)将数据保存在容器中,2)同时还保存了元素间相对顺序。

比如一个从文件中读取整数,并返回int数组的实现就可以用到队列,这样就不必提前知道文件大小:

  1. 1 public static int[] readInts(String name){
  2. 2 In in = new In(Name);
  3. 3 Queue<Integer> q = new Queue<Integer>();
  4. 4 while(!in.isEmpty()) {
  5. 5 q.enqueue(in.readInt());
  6. 6 }
  7. 7
  8. 8 int N = q.size();
  9. 9 int[] a = new int[N];
  10. 10 for(int i =0; i < N; i++) {
  11. 11 a[i] = q.dequeue();
  12. 12 }
  13. 13 return a;
  14. 14 }

二、队列的实现

队列可以用1)链表 2)数组 来实现。

1、链表实现:

algs4中实现方法:

  1. 1 public class Queue<Item> implements Iterable<Item> {
  2. 2 private Node<Item> first; // 指向对首
  3. 3 private Node<Item> last; // 指向队尾
  4. 4 private int n; // 元素数量
  5. 5
  6. 6 // 静态内部类存储元素,及链表指针
  7. 7 private static class Node<Item> {
  8. 8 private Item item;
  9. 9 private Node<Item> next;
  10. 10 }
  11. 11
  12. 12 public Queue() {
  13. 13 first = null;
  14. 14 last = null;
  15. 15 n = 0;
  16. 16 }
  17. 17
  18. 18 public boolean isEmpty() {
  19. 19 return first == null;
  20. 20 }
  21. 21
  22. 22 public int size() {
  23. 23 return n;
  24. 24 }
  25. 25
  26. 26 // 返回对首
  27. 27 public Item peek() {
  28. 28 if (isEmpty()) throw new NoSuchElementException("Queue underflow");
  29. 29 return first.item;
  30. 30 }
  31. 31
  32. 32 //入队
  33. 33 public void enqueue(Item item) {
  34. 34 Node<Item> oldlast = last;
  35. 35 last = new Node<Item>();
  36. 36 last.item = item;
  37. 37 last.next = null;
  38. 38 if (isEmpty()) first = last;
  39. 39 else oldlast.next = last;
  40. 40 n++;
  41. 41 }
  42. 42 //出队
  43. 43 public Item dequeue() {
  44. 44 if (isEmpty()) throw new NoSuchElementException("Queue underflow");
  45. 45 Item item = first.item;
  46. 46 first = first.next;
  47. 47 n--;
  48. 48 if (isEmpty()) last = null; // to avoid loitering
  49. 49 return item;
  50. 50 }
  51. 51
  52. 52
  53. 53 public Iterator<Item> iterator() {
  54. 54 return new ListIterator<Item>(first);
  55. 55 }
  56. 56
  57. 57
  58. 58 private class ListIterator<Item> implements Iterator<Item> {
  59. 59 private Node<Item> current;
  60. 60
  61. 61 public ListIterator(Node<Item> first) {
  62. 62 current = first;
  63. 63 }
  64. 64
  65. 65 public boolean hasNext() { return current != null; }
  66. 66 public void remove() { throw new UnsupportedOperationException(); }
  67. 67
  68. 68 public Item next() {
  69. 69 if (!hasNext()) throw new NoSuchElementException();
  70. 70 Item item = current.item;
  71. 71 current = current.next;
  72. 72 return item;
  73. 73 }
  74. 74 }
  75. 75 }

2、数组实现:

参考ArrayQueue实现,利用环形数组,(数组长度取模):

注意:

1)head,tail含义,head:队首;tail队尾可加入的空位。

2)有意保留一个空单元

  1. 1 public class ArrayQueue<T> extends AbstractList<T> {
  2. 2 public ArrayQueue(int capacity) {
  3. 3 this.capacity = capacity + 1;
  4. 4 this.queue = newArray(capacity + 1);
  5. 5 this.head = 0;
  6. 6 this.tail = 0;
  7. 7 }
  8. 8
  9. 9 public void resize(int newcapacity) {
  10. 10 int size = size();
  11. 11 if (newcapacity < size)
  12. 12 throw new IndexOutOfBoundsException("Resizing would lose data");
  13. 13 newcapacity++;
  14. 14 if (newcapacity == this.capacity)
  15. 15 return;
  16. 16 T[] newqueue = newArray(newcapacity);
  17. 17 for (int i = 0; i < size; i++)
  18. 18 newqueue[i] = get(i);
  19. 19 this.capacity = newcapacity;
  20. 20 this.queue = newqueue;
  21. 21 this.head = 0;
  22. 22 this.tail = size;
  23. 23 }
  24. 24
  25. 25 @SuppressWarnings("unchecked")
  26. 26 private T[] newArray(int size) {
  27. 27 return (T[]) new Object[size];
  28. 28 }
  29. 29
  30. 30 public boolean add(T o) {
  31. 31 queue[tail] = o;
  32. 32 int newtail = (tail + 1) % capacity;
  33. 33 if (newtail == head)
  34. 34 throw new IndexOutOfBoundsException("Queue full");
  35. 35 tail = newtail;
  36. 36 return true; // we did add something
  37. 37 }
  38. 38
  39. 39 public T remove(int i) {
  40. 40 if (i != 0)
  41. 41 throw new IllegalArgumentException("Can only remove head of queue");
  42. 42 if (head == tail)
  43. 43 throw new IndexOutOfBoundsException("Queue empty");
  44. 44 T removed = queue[head];
  45. 45 queue[head] = null;
  46. 46 head = (head + 1) % capacity;
  47. 47 return removed;
  48. 48 }
  49. 49
  50. 50 public T get(int i) {
  51. 51 int size = size();
  52. 52 if (i < 0 || i >= size) {
  53. 53 final String msg = "Index " + i + ", queue size " + size;
  54. 54 throw new IndexOutOfBoundsException(msg);
  55. 55 }
  56. 56 int index = (head + i) % capacity;
  57. 57 return queue[index];
  58. 58 }
  59. 59
  60. 60 public int size() {
  61. 61 // Can't use % here because it's not mod: -3 % 2 is -1, not +1.
  62. 62 int diff = tail - head;
  63. 63 if (diff < 0)
  64. 64 diff += capacity;
  65. 65 return diff;
  66. 66 }
  67. 67
  68. 68 private int capacity;
  69. 69 private T[] queue;
  70. 70 private int head;
  71. 71 private int tail;
  72. 72 }

size() 计算:

初始化capacity的设定

判满条件:

tail + 1 == head,(注意:tail表示当前空位,tail + 1当前空位再往后一个,就是整个capacity不填满的)

head > tail 的时候,

转载于:https://www.cnblogs.com/mysqlstudygroup/p/10952377.html

发表评论

表情:
评论列表 (有 0 条评论,536人围观)

还没有评论,来说两句吧...

相关阅读

    相关 数据结构算法-队列

    什么是队列 队列是一种特殊的线性表,说特殊是因为它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。

    相关 数据结构算法队列

    基本介绍 队列是一个有序列表,可以使用数组或链表来实现。 队列遵循先进先出的原则。即:先存入队列的数据,要先取出。后存入的要后取出。 数组模拟队列 因为队列的输

    相关 java数据结构算法学习】队列

    队列是一种先进先出的数据结构,和栈一样,是以线性表为基础的。队列可以用顺序存储结构或者是链式存储结构来实现,一般来说,我们都是用链式存储结构来实现的。 下面就是链式存储结构队