在路上

 找回密码
 立即注册
在路上 站点首页 学习 查看内容

Java模拟栈和队列数据结构的基本示例讲解

2016-7-29 15:41| 发布者: zhangjf| 查看: 575| 评论: 0

摘要: 栈和队列: 一般是作为程序员的工具,用于辅助构思算法,生命周期较短,运行时才被创建; 访问受限,在特定时刻,只有一个数据可被读取或删除; 是一种抽象的结构,内部的实现机制,对用户不可见,比如用数组、链表 ...

栈和队列:
一般是作为程序员的工具,用于辅助构思算法,生命周期较短,运行时才被创建;
访问受限,在特定时刻,只有一个数据可被读取或删除;
是一种抽象的结构,内部的实现机制,对用户不可见,比如用数组、链表来实现栈。

模拟栈结构
同时,只允许一个数据被访问,后进先出
对于入栈和出栈的时间复杂度都为O(1),即不依赖栈内数据项的个数,操作比较快
例,使用数组作为栈的存储结构

  1. public class StackS<T> {
  2. private int max;
  3. private T[] ary;
  4. private int top; //指针,指向栈顶元素的下标
  5. public StackS(int size) {
  6. this.max = size;
  7. ary = (T[]) new Object[max];
  8. top = -1;
  9. }
  10. // 入栈
  11. public void push(T data) {
  12. if (!isFull())
  13. ary[++top] = data;
  14. }
  15. // 出栈
  16. public T pop() {
  17. if (isEmpty()) {
  18. return null;
  19. }
  20. return ary[top--];
  21. }
  22. // 查看栈顶
  23. public T peek() {
  24. return ary[top];
  25. }
  26. //栈是否为空
  27. public boolean isEmpty() {
  28. return top == -1;
  29. }
  30. //栈是否满
  31. public boolean isFull() {
  32. return top == max - 1;
  33. }
  34. //size
  35. public int size() {
  36. return top + 1;
  37. }
  38. public static void main(String[] args) {
  39. StackS<Integer> stack = new StackS<Integer>(3);
  40. for (int i = 0; i < 5; i++) {
  41. stack.push(i);
  42. System.out.println("size:" + stack.size());
  43. }
  44. for (int i = 0; i < 5; i++) {
  45. Integer peek = stack.peek();
  46. System.out.println("peek:" + peek);
  47. System.out.println("size:" + stack.size());
  48. }
  49. for (int i = 0; i < 5; i++) {
  50. Integer pop = stack.pop();
  51. System.out.println("pop:" + pop);
  52. System.out.println("size:" + stack.size());
  53. }
  54. System.out.println("----");
  55. for (int i = 5; i > 0; i--) {
  56. stack.push(i);
  57. System.out.println("size:" + stack.size());
  58. }
  59. for (int i = 5; i > 0; i--) {
  60. Integer peek = stack.peek();
  61. System.out.println("peek:" + peek);
  62. System.out.println("size:" + stack.size());
  63. }
  64. for (int i = 5; i > 0; i--) {
  65. Integer pop = stack.pop();
  66. System.out.println("pop:" + pop);
  67. System.out.println("size:" + stack.size());
  68. }
  69. }
  70. }
复制代码

上面的例子,有一个maxSize的规定,因为数组是要规定大小的,若想无限制,可以使用其他结构来做存储,当然也可以new一个新的长度的数组。
例,使用LinkedList存储来实现栈

  1. public class StackSS<T> {
  2. private LinkedList<T> datas;
  3. public StackSS() {
  4. datas = new LinkedList<T>();
  5. }
  6. // 入栈
  7. public void push(T data) {
  8. datas.addLast(data);
  9. }
  10. // 出栈
  11. public T pop() {
  12. return datas.removeLast();
  13. }
  14. // 查看栈顶
  15. public T peek() {
  16. return datas.getLast();
  17. }
  18. //栈是否为空
  19. public boolean isEmpty() {
  20. return datas.isEmpty();
  21. }
  22. //size
  23. public int size() {
  24. return datas.size();
  25. }
  26. public static void main(String[] args) {
  27. StackS<Integer> stack = new StackS<Integer>(3);
  28. for (int i = 0; i < 5; i++) {
  29. stack.push(i);
  30. System.out.println("size:" + stack.size());
  31. }
  32. for (int i = 0; i < 5; i++) {
  33. Integer peek = stack.peek();
  34. System.out.println("peek:" + peek);
  35. System.out.println("size:" + stack.size());
  36. }
  37. for (int i = 0; i < 5; i++) {
  38. Integer pop = stack.pop();
  39. System.out.println("pop:" + pop);
  40. System.out.println("size:" + stack.size());
  41. }
  42. System.out.println("----");
  43. for (int i = 5; i > 0; i--) {
  44. stack.push(i);
  45. System.out.println("size:" + stack.size());
  46. }
  47. for (int i = 5; i > 0; i--) {
  48. Integer peek = stack.peek();
  49. System.out.println("peek:" + peek);
  50. System.out.println("size:" + stack.size());
  51. }
  52. for (int i = 5; i > 0; i--) {
  53. Integer pop = stack.pop();
  54. System.out.println("pop:" + pop);
  55. System.out.println("size:" + stack.size());
  56. }
  57. }
  58. }
复制代码

例,单词逆序,使用Statck结构

  1. public class WordReverse {
  2. public static void main(String[] args) {
  3. reverse("株式会社");
  4. }
  5. static void reverse(String word) {
  6. if (word == null) return;
  7. StackSS<Character> stack = new StackSS<Character>();
  8. char[] charArray = word.toCharArray();
  9. int len = charArray.length;
  10. for (int i = 0; i <len; i++ ) {
  11. stack.push(charArray[i]);
  12. }
  13. StringBuilder sb = new StringBuilder();
  14. while (!stack.isEmpty()) {
  15. sb.append(stack.pop());
  16. }
  17. System.out.println("反转后:" + sb.toString());
  18. }
  19. }
复制代码

打印:

  1. 反转后:社会式株
复制代码


模拟队列(一般队列、双端队列、优先级队列)
队列:
先进先出,处理类似排队的问题,先排的,先处理,后排的等前面的处理完了,再处理
对于插入和移除操作的时间复杂度都为O(1),从后面插入,从前面移除
双端队列:
即在队列两端都可以insert和remove:insertLeft、insertRight,removeLeft、removeRight
含有栈和队列的功能,如去掉insertLeft、removeLeft,那就跟栈一样了;如去掉insertLeft、removeRight,那就跟队列一样了
一般使用频率较低,时间复杂度 O(1)
优先级队列:
内部维护一个按优先级排序的序列。插入时需要比较查找插入的位置,时间复杂度O(N), 删除O(1)

  1. /*
  2. * 队列 先进先出,一个指针指示插入的位置,一个指针指示取出数据项的位置
  3. */
  4. public class QueueQ<T> {
  5. private int max;
  6. private T[] ary;
  7. private int front; //队头指针 指示取出数据项的位置
  8. private int rear; //队尾指针 指示插入的位置
  9. private int nItems; //实际数据项个数
  10. public QueueQ(int size) {
  11. this.max = size;
  12. ary = (T[]) new Object[max];
  13. front = 0;
  14. rear = -1;
  15. nItems = 0;
  16. }
  17. //插入队尾
  18. public void insert(T t) {
  19. if (rear == max - 1) {//已到实际队尾,从头开始
  20. rear = -1;
  21. }
  22. ary[++rear] = t;
  23. nItems++;
  24. }
  25. //移除队头
  26. public T remove() {
  27. T temp = ary[front++];
  28. if (front == max) {//列队到尾了,从头开始
  29. front = 0;
  30. }
  31. nItems--;
  32. return temp;
  33. }
  34. //查看队头
  35. public T peek() {
  36. return ary[front];
  37. }
  38. public boolean isEmpty() {
  39. return nItems == 0;
  40. }
  41. public boolean isFull() {
  42. return nItems == max;
  43. }
  44. public int size() {
  45. return nItems;
  46. }
  47. public static void main(String[] args) {
  48. QueueQ<Integer> queue = new QueueQ<Integer>(3);
  49. for (int i = 0; i < 5; i++) {
  50. queue.insert(i);
  51. System.out.println("size:" + queue.size());
  52. }
  53. for (int i = 0; i < 5; i++) {
  54. Integer peek = queue.peek();
  55. System.out.println("peek:" + peek);
  56. System.out.println("size:" + queue.size());
  57. }
  58. for (int i = 0; i < 5; i++) {
  59. Integer remove = queue.remove();
  60. System.out.println("remove:" + remove);
  61. System.out.println("size:" + queue.size());
  62. }
  63. System.out.println("----");
  64. for (int i = 5; i > 0; i--) {
  65. queue.insert(i);
  66. System.out.println("size:" + queue.size());
  67. }
  68. for (int i = 5; i > 0; i--) {
  69. Integer peek = queue.peek();
  70. System.out.println("peek:" + peek);
  71. System.out.println("size:" + queue.size());
  72. }
  73. for (int i = 5; i > 0; i--) {
  74. Integer remove = queue.remove();
  75. System.out.println("remove:" + remove);
  76. System.out.println("size:" + queue.size());
  77. }
  78. }
  79. }
复制代码
  1. /*
  2. * 双端队列<span style="white-space:pre"> </span>两端插入、删除
  3. */
  4. public class QueueQT<T> {
  5. private LinkedList<T> list;
  6. public QueueQT() {
  7. list = new LinkedList<T>();
  8. }
  9. // 插入队头
  10. public void insertLeft(T t) {
  11. list.addFirst(t);
  12. }
  13. // 插入队尾
  14. public void insertRight(T t) {
  15. list.addLast(t);
  16. }
  17. // 移除队头
  18. public T removeLeft() {
  19. return list.removeFirst();
  20. }
  21. // 移除队尾
  22. public T removeRight() {
  23. return list.removeLast();
  24. }
  25. // 查看队头
  26. public T peekLeft() {
  27. return list.getFirst();
  28. }
  29. // 查看队尾
  30. public T peekRight() {
  31. return list.getLast();
  32. }
  33. public boolean isEmpty() {
  34. return list.isEmpty();
  35. }
  36. public int size() {
  37. return list.size();
  38. }
  39. }
复制代码
  1. /*
  2. * 优先级队列 队列中按优先级排序,是一个有序的队列
  3. */
  4. public class QueueQP {
  5. private int max;
  6. private int[] ary;
  7. private int nItems; //实际数据项个数
  8. public QueueQP(int size) {
  9. this.max = size;
  10. ary = new int[max];
  11. nItems = 0;
  12. }
  13. //插入队尾
  14. public void insert(int t) {
  15. int j;
  16. if (nItems == 0) {
  17. ary[nItems++] = t;
  18. } else {
  19. for (j = nItems - 1; j >= 0; j--) {
  20. if (t > ary[j]) {
  21. ary[j + 1] = ary[j]; //前一个赋给后一个 小的在后 相当于用了插入排序,给定序列本来就是有序的,所以效率O(N)
  22. } else {
  23. break;
  24. }
  25. }
  26. ary[j + 1] = t;
  27. nItems++;
  28. }
  29. System.out.println(Arrays.toString(ary));
  30. }
  31. //移除队头
  32. public int remove() {
  33. return ary[--nItems]; //移除优先级小的
  34. }
  35. //查看队尾 优先级最低的
  36. public int peekMin() {
  37. return ary[nItems - 1];
  38. }
  39. public boolean isEmpty() {
  40. return nItems == 0;
  41. }
  42. public boolean isFull() {
  43. return nItems == max;
  44. }
  45. public int size() {
  46. return nItems;
  47. }
  48. public static void main(String[] args) {
  49. QueueQP queue = new QueueQP(3);
  50. queue.insert(1);
  51. queue.insert(2);
  52. queue.insert(3);
  53. int remove = queue.remove();
  54. System.out.println("remove:" + remove);
  55. }
  56. }
复制代码


最新评论

小黑屋|在路上 ( 蜀ICP备15035742号-1 

;

GMT+8, 2025-5-6 12:40

Copyright 2015-2025 djqfx

返回顶部