• 数据结构与算法——14.栈


    目录

    1.概述

    2.栈的接口设计

    3.用链表来实现栈

    4.用数组来实现栈

    5.用两个栈来实现一个队列

    6.用一个队列来实现一个栈

    7.总结

    1.概述

    计算机科学中,stack是一种线性的数据结构,只能在其一端添加数据和移除数据。习惯来说,这一端称之为栈顶,另一端不能操作数据的称之为栈底,就如同生活中的一摞书。

    说明:栈是线性的,只能在一端进行操作,分为栈顶和栈底两部分,包括入栈和出栈操作。

    2.栈的接口设计

    下面看一下栈的接口设计:

    很简单,就是入栈,出栈,判断是否为空等操作。

    3.用链表来实现栈

    下面看一下如何用链表来实现栈:

    代码:

    1. public class L12_LinkedListStack implements L12_Stack {
    2. /**定义节点类*/
    3. public class Node{
    4. E value;
    5. Node next;
    6. public Node() {
    7. }
    8. public Node(E value, Node next) {
    9. this.value = value;
    10. this.next = next;
    11. }
    12. }
    13. private int capacity;//栈的容量
    14. private int size;//栈中有效数据个数
    15. Node head = new Node(null,null);
    16. /*向栈顶添加元素*/
    17. @Override
    18. public boolean push(E value) {
    19. if(isFUll())
    20. return false;
    21. Node node = new Node(value, head.next);
    22. head.next = node;
    23. size++;
    24. return true;
    25. }
    26. /*弹出栈顶的元素*/
    27. @Override
    28. public E pop() {
    29. if (isEmpty())
    30. return null;
    31. Node p = head.next;
    32. head.next = p.next;
    33. size--;
    34. return p.value;
    35. }
    36. /*返回栈顶元素*/
    37. @Override
    38. public E peek() {
    39. if (isEmpty())
    40. return null;
    41. return head.next.value;
    42. }
    43. @Override
    44. public boolean isEmpty() {
    45. return head.next==null;
    46. }
    47. @Override
    48. public boolean isFUll() {
    49. return size == capacity;
    50. }
    51. }

    说明:总的来说还是很简单的,只要会链表的相关操作,那么就可以轻松实现

    4.用数组来实现栈

    下面来看一下如何用数组来实现栈:

    代码:
     

    1. public class L12_ArrayStack implements L12_Stack{
    2. private E[] array;
    3. private int top;//栈顶指针
    4. public L12_ArrayStack(int capacity) {
    5. this.array = (E[])new Object[capacity];
    6. }
    7. @Override
    8. public boolean push(E value) {
    9. if (isFUll())
    10. return false;
    11. array[top] = value;
    12. top++;
    13. return true;
    14. }
    15. @Override
    16. public E pop() {
    17. if (isEmpty())
    18. return null;
    19. E value = array[--top];
    20. //top--;
    21. return value;
    22. }
    23. @Override
    24. public E peek() {
    25. if (isEmpty())
    26. return null;
    27. return array[top-1];
    28. }
    29. @Override
    30. public boolean isEmpty() {
    31. return top == 0 ;
    32. }
    33. @Override
    34. public boolean isFUll() {
    35. return top == array.length;
    36. }
    37. }

    说明:用数组实现栈也很简单。其中的关键点就是定义了一个指针top,你可以理解其为指针,也可以理解其为栈中有效元素的个数。这就是数组来实现一些线性数据的好处,数组的元素个数相当于一个指针,一个指针的值也相当于数组中元素的个数。

    5.用两个栈来实现一个队列

    下面俩看一下如何用两个栈来模拟一个队列:

    代码:

    1. public class L13_TwoStackToQueue {
    2. L12_ArrayStack s1 = new L12_ArrayStack(100);//前半个
    3. L12_ArrayStack s2 = new L12_ArrayStack(100);//后半个
    4. /**入队操作,就是直接在后半个栈中压栈就行*/
    5. public void push(int x){
    6. s2.push(x);
    7. }
    8. /**出队操作*/
    9. public int pop(){
    10. if (s1.isEmpty()){
    11. while (!s2.isEmpty()){
    12. s1.push(s2.pop());
    13. }
    14. }
    15. return s1.pop();
    16. }
    17. /**返回队首元素*/
    18. public int peek(){
    19. if (s1.isEmpty()){
    20. while (!s2.isEmpty()){
    21. s1.push(s2.pop());
    22. }
    23. }
    24. return s1.peek();
    25. }
    26. public boolean empty(){
    27. return s1.isEmpty() && s2.isEmpty();
    28. }
    29. }

    说明:

    栈只有一端可以操作,是先入后出的,队列是两端都可以操作,是先入先出的。那么肯定要有两个栈,一个做队首,一个做队尾。入队操作就是后面栈的入栈操作。关键在与于出队。我们可以将后面栈的元素依次出栈,然后再将这些元素依次压入到前面的一个栈中,这样就改变了元素的顺序,再使用前面一个栈的出栈操作,就实现了出队操作。判断空就是两个栈都为空时队列才为空。

    6.用一个队列来实现一个栈

    下面来看一下如何用一个队列来实现一个栈:

    代码:

    1. public class L14_QueueToStack {
    2. L9_ArrayQueue1 q1 = new L9_ArrayQueue1(100);
    3. private int size = 0;//记录队列中元素的个数
    4. public void push(int x){
    5. q1.offer(x);
    6. for (int i = 0; i < size; i++) {
    7. q1.offer(q1.poll());
    8. }
    9. size++;
    10. }
    11. public int poll(){
    12. size--;
    13. return q1.poll();
    14. }
    15. public int pop(){
    16. return q1.peek();
    17. }
    18. public boolean empty(){
    19. return q1.isEmpty();
    20. }
    21. }

    说明:

    首先,我们要明确哪里是栈顶,哪里相当于栈底。结合题目看,队首为栈顶,队尾为栈底。这个实现的关键在与入栈操作。当我们从队尾入队后,前面已经入队的元素就跑到栈顶了,这不符合栈的规则。怎么才能让后入的元素在栈顶即在队首?我们可以将前面已经入队的元素依次弹出,然后再将这些元素依次入队,这样我们新加入的元素就这栈顶了,也就是队首了。然后出栈操作和判断空就很简单了。

    7.总结

    栈其实也很简单。就是很简单入栈,出栈等操作。栈是单端口操作的数据结构,入栈和出栈都只在一个端口。栈可以用链表和数组来实现。栈的特点就是先入后出。

    暂时就这么多吧

  • 相关阅读:
    Java设计模式——工厂模式讲解以及在JDK中源码分析
    走近Harvest Moon:Moonbeam DeFi狂欢会
    计算机学院2022级新生邀请赛(一)
    gd32f303在IAR下的printf串口助手打印+串口收发配置
    QT实现相关功能
    当 SQL DELETE 邂逅 Table aliases,会擦出怎样的火花
    Python 教程之将网页内容专为语音mp3
    Java核心编程(19)
    开源数字基础设施 项目 -- Speckle
    C++ 迷宫问题
  • 原文地址:https://blog.csdn.net/m0_52096593/article/details/132892358