有人说,数据结构与算法,计算机网络,与操作系统都一样,脱离日常开发,除了面试这辈子可能都用不到呀!

有人说,我是做业务开发的,只要熟练API,熟练框架,熟练各种中间件,写的代码不也能“飞”起来吗?

于是问题来了:为什么还要学习数据结构与算法呢?

  1. #理由一:
  2. 面试的时候,千万不要被数据结构与算法拖了后腿
  3. #理由二:
  4. 你真的愿意做一辈子CRUD Boy
  5. #理由三:
  6. 不想写出开源框架,中间件的工程师,不是好厨子

我想好了,还是需要学习数据结构与算法。但是我有两个困惑:

1.如何着手学习呢?

2.有哪些内容要学习呢?

学习方法推荐:

  1. #学习方法
  2. 1.从基础开始,系统化学习
  3. 2.多动手,每一种数据结构与算法,都自己用代码实现出来
  4. 3.思路更重要:理解实现思想,不要背代码
  5. 4.与日常开发结合,对应应用场景

学习内容推荐:

数据结构与算法内容比较多,我们本着实用原则,学习经典的、常用的数据结构、与常用算法

  1. #学习内容:
  2. 1.数据结构的定义
  3. 2.算法的定义
  4. 3.复杂度分析
  5. 4.常用数据结构
  6. 数组、链表、栈、队列
  7. 散列表、二叉树、堆
  8. 跳表、图
  9. 5.常用算法
  10. 递归、排序、二分查找
  11. 搜索、哈希、贪心、分治
  12. 动态规划、字符串匹配

你还记得在数组那一篇中,我们说过基于线性表的数据结构有哪些吗?它们是:数组、链表、栈、队列。

上一篇【数据结构与算法系列六(栈)】中,我们已经详细了解了栈这种数据结构:栈是一种操作受限的数据结构。队列是基于线性表的数据结构中,最后一种了,很巧!它也是一种操作受限的数据结构。

队列同样可以基于数组实现:顺序队列;也可以基于链表实现:链式队列

那么问题来了:具体如何实现一个队列呢?它都有哪些应用场景呢?

  1. #考考你:
  2. 1.你能用自己的话描述队列吗?
  3. 2.你知道常见的队列分类吗?
  4. 3.你知道队列代码实现的关键吗?
  5. 4.你知道如何实现一个循环队列吗?
  6. 5.你知道队列的常见的应用场景吗?

队列是一种基于线性表的数据结构,与栈一样,都是操作受限的数据结构。的特点是后进先出,而队列的特点是先进先出(FIFO),就像我们平常在火车站排队候车一样。

队列有两头:队头,和队尾。从队头出队元素,在队尾入队新的元素。

 

 

顺序队列代码:

  1. package com.anan.struct.linetable;
  2. /**
  3. * 顺序队列:基于数组实现
  4. * @param <E>
  5. */
  6. public class ArrayQueue<E> {
  7. private Object[] items;
  8. private int n;
  9. // 队列需要两个下标:对头下标索引、队尾下标索引
  10. private int head;
  11. private int tail;
  12. public ArrayQueue(int capacity){
  13. this.items = new Object[capacity];
  14. this.n = capacity;
  15. }
  16. /**
  17. * 入队操作:
  18. */
  19. public boolean enqueue(E e){
  20. // 检查队列是否满
  21. // 队列满条件 tail==n && head == 0
  22. if(tail == n){
  23. // 检查对头是否没有出队
  24. if(head == 0){
  25. return false;
  26. }
  27. // 如果已经有元素出队,则向对头移动数据
  28. for (int i = head; i < tail ; i++) {
  29. items[i - head] = items[i];
  30. }
  31. tail = tail - head;
  32. head = 0;
  33. }
  34. // 入队
  35. items[tail] = e;
  36. tail ++;
  37. return true;
  38. }
  39. /**
  40. * 出队操作:
  41. */
  42. public E dequeue(){
  43. // 检查队列是否空
  44. // 队列空条件:head == tail
  45. if(head == tail){
  46. return null;
  47. }
  48. // 出队
  49. E e = (E)items[head];
  50. head ++;
  51. return e;
  52. }
  53. }

测试代码:

  1. package com.anan.struct.linetable;
  2. /**
  3. * 测试队列
  4. */
  5. public class ArrayQueueTest {
  6. public static void main(String[] args) {
  7. // 1.创建队列
  8. int capacity = 10;
  9. ArrayQueue<Integer> queue = new ArrayQueue<Integer>(capacity);
  10. System.out.println("1.创建队列---------队列容量:" + capacity);
  11. // 2.入队操作
  12. System.out.println("2.入队操作---------");
  13. int count = 5;
  14. for (int i = 0; i < count; i++) {
  15. queue.enqueue(i);
  16. System.out.println("入队元素:" + i);
  17. }
  18. // 3.出队操作
  19. System.out.println("3.出队操作---------");
  20. for (int i = 0; i < count; i++) {
  21. System.out.println("出队元素:" + queue.dequeue());
  22. }
  23. }
  24. }

测试结果:

  1. D:\02teach\01soft\jdk8\bin\java com.anan.struct.linetable.ArrayQueueTest
  2. 1.创建队列---------队列容量:10
  3. 2.入队操作---------
  4. 入队元素:0
  5. 入队元素:1
  6. 入队元素:2
  7. 入队元素:3
  8. 入队元素:4
  9. 3.出队操作---------
  10. 出队元素:0
  11. 出队元素:1
  12. 出队元素:2
  13. 出队元素:3
  14. 出队元素:4
  15. Process finished with exit code 0
  1. package com.anan.struct.linetable;
  2. /**
  3. * 循环队列
  4. */
  5. public class CircularQueue<E> {
  6. private Object[] items;
  7. private int n;
  8. // 队头、对尾指针
  9. private int head;
  10. private int tail;
  11. public CircularQueue(int capacity){
  12. items = new Object[capacity];
  13. n = capacity;
  14. }
  15. /**
  16. * 入队操作
  17. */
  18. public boolean enqueue(E e){
  19. // 判断队列是否满
  20. // 队列满条件:(tail + 1) % n == head
  21. if((tail + 1) % n == head){
  22. return false;
  23. }
  24. items[tail] = e;
  25. tail = (tail + 1) % n;
  26. return true;
  27. }
  28. /**
  29. * 出队操作
  30. */
  31. public E dequeue(){
  32. // 判断队列是否空
  33. // 队列空条件:tail == head
  34. if(tail == head){
  35. return null;
  36. }
  37. E e = (E)items[head];
  38. head = (head + 1) % n;
  39. return e;
  40. }
  41. }
  1. #考考你答案:
  2. 1.你能用自己的话描述队列吗?
  3. 1.1.队列是基于线性表的数据结构
  4. 1.2.队列是一种操作受限的数据结构
  5. 1.3.队列满足先进先出(FIFO)的特点
  6. 1.4.队列在队头出队元素,在队尾入队元素
  7. 2.你知道常见的队列分类吗?
  8. 2.1.从底层数据结构分类有:顺序队列、链式队列
  9. 2.2.从实现特点分类有:循环队列、阻塞队列、并发队列
  10. 3.你知道队列代码实现的关键吗?
  11. 3.1.队列满足先进先出(FIFO)特点
  12. 3.2.队列在队头出队元素,在队尾入队元素
  13. 3.3.实现队列的关键:
  14. a.需要两个指针:headtail分别指向队头和队尾
  15. b.入队时,判断队列满条件:tail == n && head == 0
  16. c.出队时,判断队列空条件:tail == head
  17. 4.你知道如何实现一个循环队列吗?
  18. 4.1.在案例中,基于数组实现了一个普通的队列
  19. 4.2.入队操作的时候,如果队列满,需要移动数据
  20. // 如果队列满,且已经有元素出队,则向对头移动数据
  21. for (int i = head; i < tail ; i++) {
  22. items[i - head] = items[i];
  23. }
  24. 4.3.这样会将入队操作,时间复杂度从O(1),转变成O(n),执行效率下降
  25. 4.4.有没有更好的方式,保持入队操作的时间复杂度为O(1)不变呢?
  26. 4.5.答案是:通过循环队列来实现
  27. 4.6.关于循环队列的代码,你可以参考【3.3】循环队列实现
  28. 4.7.重点关注队列满的条件:(tail + 1) % n == head
  29. 4.8.看你是否能理解,欢迎留言我们一起讨论
  30. 5.你知道队列的常见的应用场景吗?
  31. 5.1.队列主要针对有限资源控制的应用场景
  32. 5.2.比如数据库连接池的应用
  33. 5.3.比如线程池的应用
  34. 5.4.如果你有兴趣,可以看一下JUC中线程池的底层实现
  35. 5.5.JUC线程池的底层,应用了:阻塞队列
  36. 5.6.通过队列还能实现:生产者---消费者模型

JUC创建线程池

 

版权声明:本文为itall原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/itall/p/12394980.html