Java数据结构之栈与队列实例详解

Java数据结构之栈与队列实例详解攻略

简介

栈和队列是常见的数据结构,在Java中也有对应的实现方式。本文将介绍栈和队列的概念、常见实现方式、应用场景和两个示例。

概念

栈是一种具有后进先出(Last In First Out)特性的数据结构。栈可以使用数组或链表实现。

常见实现方式

基于数组的栈实现

使用数组作为底层存储结构实现栈时,需要注意栈顶指针和数组的下标对应的关系。在栈中,栈顶指针指向栈顶元素的下标,而数组下标从0开始,因此需要额外维护一个变量记录栈顶指针。

public class ArrayStack<E> {

    private final Object[] arr;
    private int top = -1;

    public ArrayStack(int capacity) {
        arr = new Object[capacity];
    }

    public boolean push(E e) {
        if (top == arr.length - 1) {
            return false;
        }
        arr[++top] = e;
        return true;
    }

    public E pop() {
        if (top == -1) {
            return null;
        }
        return (E) arr[top--];
    }

    public E peek() {
        if (top == -1) {
            return null;
        }
        return (E) arr[top];
    }

    public boolean isEmpty() {
        return top == -1;
    }

}

基于链表的栈实现

使用链表作为底层存储结构实现栈时,每次插入或删除一个元素只需要改变指针的指向就可以了。

public class LinkedListStack<E> {

    private Node<E> top = null;

    private static class Node<E> {

        private final E value;
        private Node<E> next;

        public Node(E value) {
            this.value = value;
        }

    }

    public boolean push(E e) {
        Node<E> newNode = new Node<>(e);
        newNode.next = top;
        top = newNode;
        return true;
    }

    public E pop() {
        if (top == null) {
            return null;
        }
        E value = top.value;
        top = top.next;
        return value;
    }

    public E peek() {
        if (top == null) {
            return null;
        }
        return top.value;
    }

    public boolean isEmpty() {
        return top == null;
    }

}

应用场景

栈的应用场景非常广泛,下面简单列举一些:

  1. 函数调用栈:在函数调用的时候,每个函数都有自己的局部变量和参数。这些变量和参数都保存在栈中,每次函数调用结束之后,这些变量和参数都会从栈中弹出。

  2. 浏览器历史记录:在浏览器中,每次访问一个新的页面都会把这个页面的信息压入栈中,每次返回上一个页面的时候就从栈中弹出最新的页面信息。

  3. 表达式求值:在计算机中,表达式求值的时候会用到栈。例如,中缀表达式需要转化成后缀表达式后再进行计算,转化过程中需要借助栈来存储操作符。

...

示例

示例一

给定一个仅由括号和字母组成的字符串,判断这个字符串中的括号是否成对出现。

例如:字符串“{}”是符合规则的,而字符串“{”就不符合规则。

public boolean isValid(String s) {
    Stack<Character> stack = new Stack<>();
    for (int i = 0; i < s.length(); i++) {
        char c = s.charAt(i);
        if (c == '(' || c == '{' || c == '[') {
            stack.push(c);
        } else {
            if (stack.isEmpty()) {
                return false;
            }
            char top = stack.pop();
            if (c == ')' && top != '(') {
                return false;
            }
            if (c == '}' && top != '{') {
                return false;
            }
            if (c == ']' && top != '[') {
                return false;
            }
        }
    }
    return stack.isEmpty();
}

示例二

将一个数组中的元素从头到尾依次压入栈中,再依次从栈中弹出元素,输出的结果与原来的数组顺序相反。

public void reverse(int[] nums) {
    Stack<Integer> stack = new Stack<>();
    for (int i = 0; i < nums.length; i++) {
        stack.push(nums[i]);
    }
    for (int i = 0; i < nums.length; i++) {
        nums[i] = stack.pop();
    }
}

队列

概念

队列是一种具有先进先出(First In First Out)特性的数据结构。队列也可以使用数组或链表实现。

常见实现方式

基于数组的队列实现

使用数组作为底层存储结构实现队列时,需要注意队头指针和队尾指针的指向关系。在队列中,队头指针指向队列中第一个元素,队尾指针指向队列中最后一个元素的下一个位置。在入队或出队的时候分别更新队尾指针和队头指针即可。

public class ArrayQueue<E> {

    private final Object[] arr;
    private int front = 0;
    private int rear = 0;

    public ArrayQueue(int capacity) {
        arr = new Object[capacity + 1];
    }

    public boolean enqueue(E e) {
        if (front == (rear + 1) % arr.length) {
            return false;
        }
        arr[rear] = e;
        rear = (rear + 1) % arr.length;
        return true;
    }

    public E dequeue() {
        if (front == rear) {
            return null;
        }
        E value = (E) arr[front];
        front = (front + 1) % arr.length;
        return value;
    }

    public E peek() {
        if (front == rear) {
            return null;
        }
        return (E) arr[front];
    }

    public boolean isEmpty() {
        return front == rear;
    }

}

基于链表的队列实现

使用链表作为底层存储结构实现队列时,入队和出队操作只需要改变指针的指向就可以了。

public class LinkedListQueue<E> {

    private Node<E> head = null;
    private Node<E> tail = null;

    private static class Node<E> {

        private final E value;
        private Node<E> next;

        public Node(E value) {
            this.value = value;
        }

    }

    public boolean enqueue(E e) {
        Node<E> newNode = new Node<>(e);
        if (tail == null) {
            head = newNode;
        } else {
            tail.next = newNode;
        }
        tail = newNode;
        return true;
    }

    public E dequeue() {
        if (head == null) {
            return null;
        }
        E value = head.value;
        head = head.next;
        if (head == null) {
            tail = null;
        }
        return value;
    }

    public E peek() {
        if (head == null) {
            return null;
        }
        return head.value;
    }

    public boolean isEmpty() {
        return head == null;
    }

}

应用场景

队列的应用场景也非常广泛,下面简单列举一些:

  1. 任务队列:在线程池等多线程应用中,需要通过队列来存储任务,等待线程池中的线程来处理。

  2. 消息队列:在分布式系统中,需要通过消息队列来协调各个模块的数据交换。

  3. 广度优先搜索:在算法中,广度优先搜索需要用到队列。

...

示例

示例一

给定一个由数字组成的数组和一个数字k,求这个数组中所有长度为k的连续子数组的和。

例如:给定数组[1,2,3,4,5,6]和k=3,输出[6,9,12,15]。

public int[] findSubArraySum(int[] nums, int k) {
    int[] result = new int[nums.length - k + 1];
    LinkedListQueue<Integer> queue = new LinkedListQueue<>();
    int index = 0;
    int sum = 0;
    for (int i = 0; i < nums.length; i++) {
        queue.enqueue(nums[i]);
        sum += nums[i];
        if (queue.size() > k) {
            sum -= queue.dequeue();
        }
        if (queue.size() == k) {
            result[index++] = sum;
        }
    }
    return result;
}

示例二

将一个数组中的元素从头到尾依次加入队列中,再依次从队列中取出元素,输出的结果与原来的数组顺序相同。

public void print(int[] nums) {
    LinkedListQueue<Integer> queue = new LinkedListQueue<>();
    for (int i = 0; i < nums.length; i++) {
        queue.enqueue(nums[i]);
    }
    while (!queue.isEmpty()) {
        System.out.println(queue.dequeue());
    }
}

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java数据结构之栈与队列实例详解 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • C语言实题讲解快速掌握单链表下

    C语言实题讲解快速掌握单链表下 简介 单链表是常见的一种数据结构,可以存储任意数量的数据,并且可以高效的进行插入、删除和查找操作。本篇文章将介绍如何使用C语言实现单链表,以及如何应对在实现单链表时所遇到的常见问题。 实现过程 数据结构设计 为了实现单链表,我们需要设计一个数据结构来存储节点信息,一般包含两个成员,一个是数据域,用来存储实际的数据,另一个是指针…

    数据结构 2023年5月17日
    00
  • Java红黑树的数据结构与算法解析

    Java红黑树的数据结构与算法解析 红黑树简介 红黑树是一种平衡二叉搜索树,其中的每个节点上都有一个黑色或红色的标记,并且满足以下性质: 根节点是黑色的; 叶子节点是黑色的空节点(NULL); 如果一个节点是红色的,则其子节点必须是黑色的; 从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点; 新插入的节点默认是红色的。 具体来说,只有在删除或者某…

    数据结构 2023年5月17日
    00
  • 常用内核架构

      本文分享自天翼云开发者社区《常用内核架构》,作者:JackW   宏内核 应用程序调用内存分配的 API(应用程序接口)函数。 处理器切换到特权模式,开始运行内核代码。 内核里的内存管理代码按照特定的算法,分配一块内存。 把分配的内存块的首地址,返回给内存分配的 API 函数。 内存分配的 API 函数返回,处理器开始运行用户模式下的应用程序,应用程序就…

    算法与数据结构 2023年4月22日
    00
  • java数据结构排序算法之树形选择排序详解

    Java数据结构排序算法之树形选择排序详解 什么是树形选择排序 树形选择排序是对选择排序的一种改进和优化,它是通过利用完全二叉树的性质对选择排序进行了改进而得到的一种高效的排序算法。 树形选择排序通过将待排序的元素构建成一颗完全二叉树,然后从叶子节点向上比较,选择出最小的元素,并交换位置。这样子,每次选择最小元素的时候,减少了元素之间的比较次数,从而提高了排…

    数据结构 2023年5月17日
    00
  • C语言中数据结构之链式基数排序

    C语言中数据结构之链式基数排序 概述 链式基数排序是基数排序的一种实现方式。基数排序是一种桶排序算法,它通过将需要排序的数据分成多个桶,并且按照一定的顺序将数据从桶中取出来,以达到排序的目的。链式基数排序则使用了链表结构来实现桶的功能。 实现步骤 链式基数排序的实现步骤如下: 申请链表节点数组,并初始化链表头结点数组。链表的数量等于指定的基数,例如10进制的…

    数据结构 2023年5月17日
    00
  • redis中的数据结构和编码详解

    Redis中的数据结构和编码详解 Redis中的数据结构 Redis支持以下五种数据结构: 字符串(string):最基本的数据类型,Redis中的字符串是二进制安全的,意味着您可以在字符串中存储任何数据。例如,您可以将图像文件或序列化对象存储为Redis字符串。字符串最大可以容纳512MB。 列表(list):Redis列表是字符串列表,其中的元素按照插入…

    数据结构 2023年5月17日
    00
  • C语言数据结构之迷宫问题

    C语言数据结构之迷宫问题 迷宫问题是一种基本的搜索问题,其中需要在一个矩阵中寻找从起点到终点的路径。在本篇文章中,我们将以C语言为例,介绍迷宫问题的完整攻略。 准备工作 在开始之前,我们先要准备好数据结构。为了表示迷宫,我们使用一个二维数组。其中,0表示可以通过的路,1表示障碍物不可通过。为了记录路径,我们还需要使用一个二维数组来表示每个格子是否已经被访问过…

    数据结构 2023年5月17日
    00
  • 在matlab中创建类似字典的数据结构方式

    当需要使用类似字典的数据结构时,Matlab中可以使用结构体来实现。结构体是一种有序的数据集合,每个元素都可以包含不同类型的数据(如字符串、数值等),并通过指定一个名称来唯一地标识该元素。 创建一个空结构体 使用struct函数可以创建一个空的结构体,可以使用下面的代码: st = struct; 添加键值对 可以将键值对添加到结构体中,可以使用下面的代码向…

    数据结构 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部