【数据结构与算法-初学者指南】【附带力扣原题】队列

简介: 【数据结构与算法-初学者指南】【附带力扣原题】队列

队列:基本原理及操作


在计算机科学中,队列是一种常见的数据结构,它可以用于多种场景,例如任务调度、事件处理等。本篇博客将介绍队列的基本原理和常见操作,并探讨如何使用数组模拟队列的操作以及该方法的优缺点及性能影响。最后,我们将针对基于数组的队列算法题目提供解题思路和优化方法的讨论。


队列的基本概念和特点


队列是一种先进先出(First In First Out, FIFO)的数据结构。它类似于现实中的排队,即先来的人先服务,后来的人后服务。在队列中,元素从队尾入队,从队首出队。


队列具有以下几个特点:


  • 入队操作:将一个元素插入队列的尾部。
  • 出队操作:将队列头部的元素删除并返回。
  • 队列长度:队列中元素的数量。
  • 队空判断:判断队列是否为空。
  • 队满判断:当队列大小有限时,队列已满时禁止插入新元素。


队列的常见操作


队列是一种基本的数据结构,常见的操作包括以下几个:


  • 入队操作:将元素插入队列尾部。
  • 出队操作:返回队列头部元素并删除。
  • 队列长度:返回队列中元素的数量。
  • 队空判断:判断队列是否为空。
  • 队满判断:当队列大小有限时,队列已满时禁止插入新元素。


下面是使用Java实现队列的示例代码:

public class Queue<T> {
    private int maxSize;  // 队列容量
    private T[] data;     // 存储元素的数组
    private int front;    // 队头指针
    private int rear;     // 队尾指针
    
    // 构造函数
    public Queue(int maxSize) {
        this.maxSize = maxSize;
        this.data = (T[]) new Object[maxSize];
        this.front = 0;
        this.rear = 0;
    }
    
    // 入队操作
    public void enqueue(T element) {
        if (isFull()) {
            throw new RuntimeException("Queue is full!");
        }
        data[rear] = element;
        rear = (rear + 1) % maxSize;  // 循环队列
    }
    
    // 出队操作
    public T dequeue() {
        if (isEmpty()) {
            throw new RuntimeException("Queue is empty!");
        }
        T element = data[front];
        front = (front + 1) % maxSize;  // 循环队列
        return element;
    }
    
    // 获取队列长度
    public int size() {
        return (rear - front + maxSize) % maxSize;
    }
    
    // 判断队列是否为空
    public boolean isEmpty() {
        return front == rear;
    }
    
    // 判断队列是否已满
    public boolean isFull() {
        return (rear + 1) % maxSize == front;
    }
    
    // 获取队头元素
    public T peek() {
        if (isEmpty()) {
            throw new RuntimeException("Queue is empty!");
        }
        return data[front];
    }
}

上述代码中,我们使用了数组来实现队列的基本操作。其中maxSize表示队列容量,data数组用于存储队列元素,front和rear分别表示队头和队尾指针。通过上述基本操作的实现,可以构造出一个完整的队列数据结构。


数组模拟队列:实现原理与性能分析


在队列的实现中,使用数组来模拟队列是一种常见的方式。下面我们来探讨如何使用数组模拟队列的操作,以及该方法的优缺点和性能影响。


数组模拟队列的实现原理


使用数组模拟队列的实现原理是:使用数组作为队列的存储空间,通过两个指针分别指向队头和队尾,完成队列的入队、出队、队列长度等操作。


具体来说,使用数组模拟队列常用的做法是使用循环队列。循环队列可以解决顺序队列因删除元素而造成空闲空间无法利用的问题。循环队列中,队头指针front和队尾指针rear都是指向数组中的元素,当入队操作将rear指针移动到数组的最后一位时,rear指针会回到数组的第一位。同样,当出队操作将front指针移动到数组的最后一位时,front指针也会回到数组的第一位。


数组模拟队列的优缺点和性能影响


使用数组模拟队列的优点是实现简单,易于理解和掌握。同时,由于数组的内存空间是连续的,因此对于CPU缓存来说,数组的访问速度更快,性能更高。另外,使用循环队列可以避免因删除元素而造成空闲空间无法利用的问题。


但是,使用数组模拟队列也存在一些缺点。首先,如果队列大小有限,当队列已满时,禁止插入新元素,这是一种浪费空间的做法。其次,当进行元素的出队操作时,需要将队列中的所有元素向前移动一个位置,这样会导致时间复杂度为O(n),性能较差。


基于数组的队列算法题解分析


下面我们将针对基于数组的队列算法题目提供解题思路和优化方法的讨论。


题目一:用队列实现栈


这个题目是LeetCode第225题,要求使用队列来实现栈的操作。具体来说,需要实现以下几个方法:

class MyStack {
    public MyStack() {}
    
    public void push(int x) {}
    
    public int pop() {}
    
    public int top() {}
    
    public boolean empty() {}
}

其中,push方法将元素推入栈顶,pop方法将栈顶元素弹出并返回,top方法获取栈顶元素,empty方法判断栈是否为空。


使用队列来实现栈的操作,可以使用两个队列来模拟。当需要进行入栈操作时,将元素插入到一个非空队列的队尾即可。当需要进行出栈、获取栈顶元素或判断栈是否为空等操作时,则需要将元素从一个队列中取出,并将其余的元素依次插入到另外一个队列中。下面是基于数组的队列实现栈的示例代码:

class MyStack {
    private Queue<Integer> queue1;
    private Queue<Integer> queue2;
 
    /** Initialize your data structure here. */
    public MyStack() {
        queue1 = new LinkedList<>();
        queue2 = new LinkedList<>();
    }
    
    /** Push element x onto stack. */
    public void push(int x) {
        if (!queue1.isEmpty()) {
            queue1.offer(x);
        } else {
            queue2.offer(x);
        }
    }
    
    /** Removes the element on top of the stack and returns that element. */
    public int pop() {
        if (empty()) {
            throw new RuntimeException("Stack is empty!");
        }
        if (!queue1.isEmpty()) {
            while (queue1.size() > 1) {
                queue2.offer(queue1.poll());
            }
            return queue1.poll();
        } else {
            while (queue2.size() > 1) {
                queue1.offer(queue2.poll());
            }
            return queue2.poll();
        }
    }
    
    /** Get the top element. */
    public int top() {
        if (empty()) {
            throw new RuntimeException("Stack is empty!");
        }
        if (!queue1.isEmpty()) {
            while (queue1.size() > 1) {
                queue2.offer(queue1.poll());
            }
            int top = queue1.poll();
            queue2.offer(top);
            return top;
        } else {
            while (queue2.size() > 1) {
                queue1.offer(queue2.poll());
            }
            int top = queue2.poll();
            queue1.offer(top);
            return top;
        }
    }
    
    /** Returns whether the stack is empty. */
    public boolean empty() {
        return queue1.isEmpty() && queue2.isEmpty();
    }
}

题目要求使用队列实现栈的操作,即要实现push、pop、top和empty这几个方法。


首先,我们可以考虑使用两个队列来模拟栈的操作。其中一个队列用于存储栈中的元素,另一个队列用于辅助操作。具体思路如下:


  1. 初始化两个空队列queue1和queue2。


  1. push操作:将元素插入到非空队列的队尾。

如果queue1不为空,则将元素插入到queue1的队尾。

如果queue1为空,则将元素插入到queue2的队尾。


  1. pop操作:弹出栈顶元素并返回。

如果queue1不为空,则将queue1中除最后一个元素外的所有元素依次出队并入队到queue2,然后返回queue1的最后一个元素。

如果queue1为空,则将queue2中除最后一个元素外的所有元素依次出队并入队到queue1,然后返回queue2的最后一个元素。


  1. top操作:获取栈顶元素。

如果queue1不为空,则将queue1中除最后一个元素外的所有元素依次出队并入队到queue2,然后返回queue1的最后一个元素,并将该元素插入到queue2的队尾。

如果queue1为空,则将queue2中除最后一个元素外的所有元素依次出队并入队到queue1,然后返回queue2的最后一个元素,并将该元素插入到queue1的队尾。


  1. empty操作:判断栈是否为空。

当两个队列都为空时,栈为空。


相关文章
|
14天前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
90 9
|
17天前
|
算法 安全 NoSQL
2024重生之回溯数据结构与算法系列学习之栈和队列精题汇总(10)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构王道第3章之IKUN和I原达人之数据结构与算法系列学习栈与队列精题详解、数据结构、C++、排序算法、java、动态规划你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
1月前
初步认识栈和队列
初步认识栈和队列
58 10
|
1月前
|
存储 算法 定位技术
数据结构与算法学习二、稀疏数组与队列,数组模拟队列,模拟环形队列
这篇文章主要介绍了稀疏数组和队列的概念、应用实例以及如何使用数组模拟队列和环形队列的实现方法。
20 0
数据结构与算法学习二、稀疏数组与队列,数组模拟队列,模拟环形队列
|
1月前
|
存储 安全 Java
【用Java学习数据结构系列】探索栈和队列的无尽秘密
【用Java学习数据结构系列】探索栈和队列的无尽秘密
30 2
|
1月前
【数据结构】-- 栈和队列
【数据结构】-- 栈和队列
16 0
|
1月前
探索数据结构:队列的的实现与应用
探索数据结构:队列的的实现与应用
|
1月前
|
存储 C语言
栈和队列题目练习
栈和队列题目练习
16 0
|
1月前
【LeetCode 24】225.用队列实现栈
【LeetCode 24】225.用队列实现栈
10 0
|
1月前
|
存储 算法 Java
【用Java学习数据结构系列】用堆实现优先级队列
【用Java学习数据结构系列】用堆实现优先级队列
29 0