经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » 编程经验 » 查看文章
队列
来源:cnblogs  作者:hardyyao  时间:2018/10/21 20:08:03  对本文有异议

队列是什么?

队列是一种先进先出的数据结构。

跟栈一样,队列也是一种操作受限的线性表数据结构。

用数组实现一个队列

如果用数组来实现一个栈,我们只需要一个栈顶指针就够了。但是队列需要两个指针:一个是 head 指针,指向队头;一个是 tail 指针,指向队尾。

下面用代码来实现一个数组队列:

  1. 1 // 用数组实现的队列
  2. 2 public class ArrayQueue {
  3. 3 // 数组:items,数组大小:n
  4. 4 private String[] items;
  5. 5 private int n = 0;
  6. 6 // head 表示队头下标,tail 表示队尾下标
  7. 7 private int head = 0;
  8. 8 private int tail = 0;
  9. 9
  10. 10 // 申请一个大小为 capacity 的数组
  11. 11 public ArrayQueue(int capacity) {
  12. 12 items = new String[capacity];
  13. 13 n = capacity;
  14. 14 }
  15. 15
  16. 16 // 入队
  17. 17 public boolean enqueue(String item) {
  18. 18 // 如果 tail == n 表示队列已经满了
  19. 19 if (tail == n) {
  20. 20 return false;
  21. 21 }
  22. 22 items[tail] = item;
  23. 23 ++tail;
  24. 24 return true;
  25. 25 }
  26. 26
  27. 27 // 出队
  28. 28 public String dequeue() {
  29. 29 // 如果 head == tail 表示队列为空
  30. 30 if (head == tail) {
  31. 31 return null;
  32. 32 }
  33. 33 String ret = items[head];
  34. 34 ++head;
  35. 35 return ret;
  36. 36 }
  37. 37 }

用链表实现一个队列

基于链表实现的队列,同样需要两个指针:head 指针 和 tail 指针,分别指向链表的第一个结点和最后一个结点。

下面用代码来实现一个链表队列:

  1. 1 public class QueueBasedOnLinkedList {
  2. 2
  3. 3 // 队列的队首和队尾
  4. 4 private Node head = null;
  5. 5 private Node tail = null;
  6. 6
  7. 7 // 入队
  8. 8 public void enqueue(String value) {
  9. 9 if (tail == null) {
  10. 10 Node newNode = new Node(value, null);
  11. 11 head = newNode;
  12. 12 tail = newNode;
  13. 13 } else {
  14. 14 tail.next = new Node(value, null);
  15. 15 tail = tail.next;
  16. 16 }
  17. 17 }
  18. 18
  19. 19 // 出队
  20. 20 public String dequeue() {
  21. 21 if (head == null) {
  22. 22 return null;
  23. 23 }
  24. 24 String value = head.data;
  25. 25 head = head.next;
  26. 26 if (head == null) {
  27. 27 tail = null;
  28. 28 }
  29. 29 return value;
  30. 30 }
  31. 31
  32. 32 public void printAll() {
  33. 33 Node p = head;
  34. 34 while (p != null) {
  35. 35 System.out.print(p.data + " ");
  36. 36 p = p.next;
  37. 37 }
  38. 38 System.out.println();
  39. 39 }
  40. 40
  41. 41 private static class Node {
  42. 42 private String data;
  43. 43 private Node next;
  44. 44
  45. 45 public Node(String data, Node next) {
  46. 46 this.data = data;
  47. 47 this.next = next;
  48. 48 }
  49. 49
  50. 50 public String getData() {
  51. 51 return data;
  52. 52 }
  53. 53 }
  54. 54
  55. 55 }

循环队列

当我们用数组实现队列的时候,若 tail==n && head!=0 时,即队列末尾没有空间但整个队列未满的时候,会有数组搬移操作,这样入队操作性能就会受到影响,这种时候可以用循环队列来解决这个问题。

在用数组实现的非循环队列中,队满的判断条件是 tail==n,队空的判断条件是 head==tail。

针对循环队列,队空的判断条件仍然是 head==tail,但队列满的判断条件为 (tail+1)%n=head。

下面用代码来实现一个循环队列:

  1. 1 public class CircularQueue {
  2. 2 // 数组:items,数组大小:n
  3. 3 private String[] items;
  4. 4 private int n = 0;
  5. 5 // head 表示队头下标,tail 表示队尾下标
  6. 6 private int head = 0;
  7. 7 private int tail = 0;
  8. 8
  9. 9 // 申请一个大小为 capacity 的数组
  10. 10 public CircularQueue(int capacity) {
  11. 11 items = new String[capacity];
  12. 12 n = capacity;
  13. 13 }
  14. 14
  15. 15 // 入队
  16. 16 public boolean enqueue(String item) {
  17. 17 // 队列满了
  18. 18 if ((tail + 1) % n == head) {
  19. 19 return false;
  20. 20 }
  21. 21 items[tail] = item;
  22. 22 tail = (tail + 1) % n;
  23. 23 return true;
  24. 24 }
  25. 25
  26. 26 // 出队
  27. 27 public String dequeue() {
  28. 28 // 如果 head == tail 表示队列为空
  29. 29 if (head == tail) {
  30. 30 return null;
  31. 31 }
  32. 32 String ret = items[head];
  33. 33 head = (head + 1) % n;
  34. 34 return ret;
  35. 35 }
  36. 36 }

阻塞队列和并发队列

阻塞队列就是在队列基础上增加了阻塞操作。简单来说,就是在队列为空的时候,从队头取数据会被阻塞。因为此时还没有数据可取,直到队列中有数据了才能返回;如果队列已经满了,那么插入数据的操作就会被阻塞,直到队列中有空闲位置后再插入数据,然后再返回。

并发队列就是在多线程情况下,实现的一个避免线程安全问题的队列。最简单的实现方式就是在 enqueue()、dequeue() 方法上加锁,但是锁粒度大并发度会比较低,同一时刻仅允许一个存或者取操作。

总结

  • 队列最大的特点就是先进先出,主要的两个操作是入队和出队。
  • 队列和栈一样,既可以用数组来实现,也可以用链表来实现。

(PS:最近比较忙,没那么多时间认真学习算法课程,就先看一下课程大概内容,记一些笔记而已,起码掌握一下算法思想,等忙完这段时间再进行补充。)

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号