数据结构101:如何在Java中使用栈和队列(一)

简介: 数据结构101:如何在Java中使用栈和队列

什么是堆栈?

在编程中,堆栈是一种抽象的线性数据类型,具有预定义的容量(或边界)。它遵循添加或删除元素的特定顺序。线性数据结构以直线组织它们的组件,所以如果我们添加或删除一个元素,它们将分别增长或收缩。

网络异常,图片无法展示
|

让我们使用放置在盒子中的一堆盘子来概念化堆栈。放置在堆叠中的第一个盘子(堆叠底部的盘子)将是最后一个被移除的盘子,最后添加的盘子将是第一个被移除的盘子。

这称为后进先出 (LIFO)先进后出 (FILO) 排序。

当我们编码时,堆栈以多种方式使用。我们使用堆栈来实现函数、解析器、表达式求值和一些算法。堆栈非常适合处理嵌套结构,因此它们对于理解递归很重要。

堆栈的一个简单的实际应用是逐个字母地反转字符串。数据堆栈的另一个很好的例子是计算机或文本编辑器上的撤消和重做功能。撤消删除您最近的更改,重做建立在现有更改的基础上。

堆栈如何工作?

栈的实现相对容易。如上图所示,功能取决于pop和方法。pushpop方法从堆栈中移除push或删除元素,同时该方法将项目添加到堆栈。

当一个元素被插入到栈中时,它会占据栈顶位置,存储这个位置的变量指向它下面的数字。每当向其中插入或删除元素时,都应更新顶部变量。

注意: 重要的是要记住插入和删除发生在堆栈的同一端。

在本文后面,我们将学习如何在 Java 中手动实现 Stack 数据结构。

什么是队列?

队列很像堆栈。队列也是一种遵循先进先出 (FIFO) 顺序的线性结构,但它们在删除元素的方式上有所不同。队列从两端开放:一端用于插入数据 ( enqueue),另一端用于删除数据 ( dequeue)。堆栈仅从一端打开。

简化: 对于堆栈,我们删除最近添加的元素,但对于队列,我们删除“最旧”的元素。

网络异常,图片无法展示
|

说到排队,想想你最喜欢的杂货店的结账柜台。结账队伍中排在第一位的人将在其他人之前得到最先的接待,而排队的最后一个人将得到最后的接待。这就是队列的工作原理。它有两端,前部和后部。元素从后面进入,从前面离开。

队列类型

您可能会遇到三种常见类型的队列。至此,我们了解了线性队列。另外两个队列是:

  1. 循环队列: 在循环队列中,最后一个元素与第一个元素相连形成一个圆圈。最初,队列的前部和后部指向相同的位置,但随着更多元素插入队列,它们会分开。循环队列的一个真实示例是自动交通信号系统。
  2. 优先队列: 在优先队列中,元素根据优先级排序。最重要的元素最先出现,最不重要的元素最后出现。[优先级队列在操作系统]中用于负载平衡,以确定应给予哪些程序更高的优先级。

栈和队列的优缺点

堆栈

优点

  • 对于初学者来说很容易实现并且合乎逻辑
  • 它允许您控制内存的分配方式
  • 比队列更容易使用

缺点

  • 既不灵活也不可扩展
  • 随机访问堆栈中的元素几乎是不可能的

队列

优点

  • 队列是灵活的。
  • 他们可以处理多种数据类型。
  • 数据队列快速且优化

缺点

  • 从中间插入/删除元素很复杂。
  • 队列不容易搜索

栈和队列的基本操作

典型的堆栈必须包含以下方法:

  • pop():此方法从堆栈顶部删除一个元素并将其返回。
  • push():此方法将一个元素添加到堆栈的顶部。

队列允许进行以下操作:

  • enqueue():此方法将一个元素添加到队列的尾部/尾部
  • dequeue():此方法从队列的前面删除一个元素
  • top():返回队列中的第一个元素
  • initialize(): 创建一个空队列

从那里,我们可以应用各种方法来获得更多功能和信息检索:

  • top(): 返回最近添加到堆栈的元素
  • intStack.peek(): 返回栈顶而不移除元素
  • poll():删除队列的头部并返回它
  • size():返回队列的大小作为元素的数量
  • isEmpty()``true:如果堆栈/队列已满则返回
  • isFull()``true:如果堆栈/队列已满则返回

如何在 Java 中实现堆栈

每种编程语言都带有堆栈的基本功能。但是,在 Java 中,堆栈数据类型是Adapter 类。这意味着它建立在其他数据结构之上。因此,它可以使用 Array、Vector、Linked List 或任何其他集合来实现。

注意: 堆栈通常使用数组来实现,因为它占用的内存更少。

无论使用何种底层数据结构或编程语言,堆栈都必须实现相同的基本功能。在 Java 中,您可以导入堆栈的预构建类或手动实现堆栈并扩展其功能。为了实现内置的 Stack 类,我们使用java.util以下导入语句来使用包:

import java.util.*;
// or
import java.util.Stack;
复制代码

导入包后,我们可以创建一个堆栈对象,如下所示:

Stack mystack = new Stack();
复制代码

然后,我们向舞台添加元素。例如,我们可以使用 . 添加整数push()

Stack<Integer> myStack = new Stack<>();
 myStack.push(5);
 myStack.push(6);
 myStack.push(7);
复制代码

基本语法如下所示:

public class Stack <V> {
    private int maxSize;
    private int top;
    private V arr[];
复制代码

要手动创建堆栈,我们构造一个 Stack 类并创建一个实例。该类具有以下三个数据成员:

  • 一个包含所有元素的数组
  • 这个数组的大小/边界
  • 栈顶元素的变量

以下代码显示了如何构造 Stack 类:

主要的java:

class StackDemo {
    public static void main( String args[] ) {
        Stack<Integer> stack = new Stack<Integer>(10);
        System.out.print("You have successfully created a Stack!");
    }
}
复制代码

堆栈.java:

public class Stack <V> {
    private int maxSize;
    private int top;
    private V arr[];
    /*
    Java does not allow generic type arrays. So we have used an 
    array of Object type and type-casted it to the generic type V.
    This type-casting is unsafe and produces a warning.
    Comment out the line below and execute again to see the warning.
    */
    @SuppressWarnings("unchecked")
    public Stack(int max_size) {
        this.maxSize = max_size;
        this.top = -1; //initially when stack is empty
        arr = (V[]) new Object[max_size];//type casting Object[] to V[]
    }
    public int getCapacity() {
        return maxSize;
    }
}
复制代码

输出:

You have successfully created a Stack!
复制代码

在将 push 和 pop 方法添加到这段代码之前,我们需要实现一些辅助方法。辅助方法使代码简单易懂。下面是我们将在下面的代码中实现的辅助函数列表:

  • isEmpty()
  • isFull()
  • top()

下面是使用新辅助方法的堆栈代码。

main.java:

class HelloWorld {
    public static void main( String args[] ) {
        Stack<Integer> stack = new Stack<Integer>(10);
        //output if stack is empty or not
        if(stack.isEmpty())
        System.out.print("Stack is empty");
        else
        System.out.print("Stack is not empty");
        System.out.printf("%n");
        //output if stack is full or not
        if(stack.isFull())
        System.out.print("Stack is full");
        else
        System.out.print("Stack is not full");
    }
}
复制代码

堆栈.java:

public class Stack <V> {
    private int maxSize;
    private int top;
    private V array[];
    /*
    Java does not allow generic type arrays. So we have used an
    array of Object type and type-casted it to the generic type V.
    This type-casting is unsafe and produces a warning.
    Comment out the line below and execute again to see the warning.
    */
    @SuppressWarnings("unchecked")
    public Stack(int max_size) {
        this.maxSize = max_size;
        this.top = -1; //initially when stack is empty
        array = (V[]) new Object[max_size];//type casting Object[] to V[]
    }
    //returns the maximum size capacity
    public int getMaxSize() {
        return maxSize;
    }
    //returns true if Stack is empty
    public boolean isEmpty(){
        return top == -1;
    }
    //returns true if Stack is full
    public boolean isFull(){
        return top == maxSize -1;
    }
    //returns the value at top of Stack
    public V top(){
        if(isEmpty())
            return null;
        return array[top];
    }
}
复制代码

输出:

Stack is empty
Stack is not full
复制代码

如果您的输出返回trueforisEmpty()falsefor isFull(),则表示这些辅助函数正常工作!现在,看看这个扩展代码,其中添加了 push 和pop添加到 Stack 类定义的函数。我们将尝试从这个堆栈中添加和删除一些元素。

主要的java:

class StackDemo {
    public static void main(String[] args) {
        Stack<Integer> stack = new Stack<Integer>(5); 
        System.out.print("Elements pushed in the Stack: ");
        for (int i = 0; i < 5; i++) {
            stack.push(i); //pushes 5 elements (0-4 inclusive) to the stack
            System.out.print(i + " ");
        }
        System.out.println("\nIs Stack full? \n" + stack.isFull());
        System.out.print("Elements popped from the Stack: ");
        for (int i = 0; i < 5; i++) {
            System.out.print(stack.pop()+" "); //pops all 5 elements from the stack and prints them
        }
        System.out.println("\nIs Stack empty? \n" + stack.isEmpty());
    }//end of main 
}
复制代码



相关文章
|
8月前
|
前端开发 Java
java实现队列数据结构代码详解
本文详细解析了Java中队列数据结构的实现,包括队列的基本概念、应用场景及代码实现。队列是一种遵循“先进先出”原则的线性结构,支持在队尾插入和队头删除操作。文章介绍了顺序队列与链式队列,并重点分析了循环队列的实现方式以解决溢出问题。通过具体代码示例(如`enqueue`入队和`dequeue`出队),展示了队列的操作逻辑,帮助读者深入理解其工作机制。
277 1
|
6月前
|
存储 安全 Java
Java 集合面试题从数据结构到 HashMap 源码剖析详解及长尾考点梳理
本文深入解析Java集合框架,涵盖基础概念、常见集合类型及HashMap的底层数据结构与源码实现。从Collection、Map到Iterator接口,逐一剖析其特性与应用场景。重点解读HashMap在JDK1.7与1.8中的数据结构演变,包括数组+链表+红黑树优化,以及put方法和扩容机制的实现细节。结合订单管理与用户权限管理等实际案例,展示集合框架的应用价值,助你全面掌握相关知识,轻松应对面试与开发需求。
336 3
|
6月前
|
编译器 C语言 C++
栈区的非法访问导致的死循环(x64)
这段内容主要分析了一段C语言代码在VS2022中形成死循环的原因,涉及栈区内存布局和数组越界问题。代码中`arr[15]`越界访问,修改了变量`i`的值,导致`for`循环条件始终为真,形成死循环。原因是VS2022栈区从低地址到高地址分配内存,`arr`数组与`i`相邻,`arr[15]`恰好覆盖`i`的地址。而在VS2019中,栈区先分配高地址再分配低地址,因此相同代码表现不同。这说明编译器对栈区内存分配顺序的实现差异会导致程序行为不一致,需避免数组越界以确保代码健壮性。
136 0
栈区的非法访问导致的死循环(x64)
232.用栈实现队列,225. 用队列实现栈
在232题中,通过两个栈(`stIn`和`stOut`)模拟队列的先入先出(FIFO)行为。`push`操作将元素压入`stIn`,`pop`和`peek`操作则通过将`stIn`的元素转移到`stOut`来实现队列的顺序访问。 225题则是利用单个队列(`que`)模拟栈的后入先出(LIFO)特性。通过多次调整队列头部元素的位置,确保弹出顺序符合栈的要求。`top`操作直接返回队列尾部元素,`empty`判断队列是否为空。 两题均仅使用基础数据结构操作,展示了栈与队列之间的转换逻辑。
|
11月前
|
存储 C语言 C++
【C++数据结构——栈与队列】顺序栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现顺序栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 1.初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储
550 77
|
8月前
|
存储 Java 编译器
Java 中 .length 的使用方法:深入理解 Java 数据结构中的长度获取机制
本文深入解析了 Java 中 `.length` 的使用方法及其在不同数据结构中的应用。对于数组,通过 `.length` 属性获取元素数量;字符串则使用 `.length()` 方法计算字符数;集合类如 `ArrayList` 采用 `.size()` 方法统计元素个数。此外,基本数据类型和包装类不支持长度属性。掌握这些区别,有助于开发者避免常见错误,提升代码质量。
814 1
|
10月前
|
算法 调度 C++
STL——栈和队列和优先队列
通过以上对栈、队列和优先队列的详细解释和示例,希望能帮助读者更好地理解和应用这些重要的数据结构。
250 11
|
10月前
|
DataX
☀☀☀☀☀☀☀有关栈和队列应用的oj题讲解☼☼☼☼☼☼☼
### 简介 本文介绍了三种数据结构的实现方法:用两个队列实现栈、用两个栈实现队列以及设计循环队列。具体思路如下: 1. **用两个队列实现栈**: - 插入元素时,选择非空队列进行插入。 - 移除栈顶元素时,将非空队列中的元素依次转移到另一个队列,直到只剩下一个元素,然后弹出该元素。 - 判空条件为两个队列均为空。 2. **用两个栈实现队列**: - 插入元素时,选择非空栈进行插入。 - 移除队首元素时,将非空栈中的元素依次转移到另一个栈,再将这些元素重新放回原栈以保持顺序。 - 判空条件为两个栈均为空。
|
10月前
|
存储 IDE Java
java设置栈内存大小
在Java应用中合理设置栈内存大小是确保程序稳定性和性能的重要措施。通过JVM参数 `-Xss`,可以灵活调整栈内存大小,以适应不同的应用场景。本文介绍了设置栈内存大小的方法、应用场景和注意事项,希望能帮助开发者更好地管理Java应用的内存资源。
525 4
|
11月前
|
C++
【C++数据结构——栈和队列】括号配对(头歌实践教学平台习题)【合集】
【数据结构——栈和队列】括号配对(头歌实践教学平台习题)【合集】(1)遇到左括号:进栈Push()(2)遇到右括号:若栈顶元素为左括号,则出栈Pop();否则返回false。(3)当遍历表达式结束,且栈为空时,则返回true,否则返回false。本关任务:编写一个程序利用栈判断左、右圆括号是否配对。为了完成本关任务,你需要掌握:栈对括号的处理。(1)遇到左括号:进栈Push()开始你的任务吧,祝你成功!测试输入:(()))
258 7

热门文章

最新文章