Queue
[TOC]
基本定义
队列实现的是一种先进先出(FIFO)策略的线性表。
队列有队头(head)和队尾(tail),当有一个元素入队时,放入队尾;出队时,即删除队头元素。
队列的基本操作
push(x):将元素x加入到队列的尾部
pop():弹出队列的第一个元素,但是,不会返回被弹元素的值
front():返回队首元素
back():返回队尾元素
empty():判断队列是否为空,当队列为空时,返回true
size():返回队列中的元素个数
注意:以上操作均基于c++模板类,位于头文件和中。以下是两个数据结构互相转换算法和程序。
队列的实现
从时间复杂度角度而言,push(), pop(), front(),back(), empty()操作只需要O(1)的时间。从实现角度而言,队列的实现方式有两种,数组和线性表。
class MyQueue
{
private:
int front, rear, size;
unsigned capacity;
int *array;
public:
MyQueue(unsigned num);
bool Push(int x);
bool Pop();
int Front();
int Back();
bool Empty();
bool Full();
};
// 初始化
MyQueue::MyQueue(unsigned num) {
capacity = num;
array = new int[capacity];
front = 0;
rear = capacity - 1;
size = 0;
}
bool MyQueue::Full() {
if(size == capacity)
return true;
else
return false;
}
bool MyQueue::Empty() {
if(size == 0)
return true;
else
return false;
}
// 入队
bool MyQueue::Push(int x) {
if(size == capacity) {
cout << "Queue is Overflow" << endl;
return false;
}
rear = (rear + 1) % capacity;
array[rear] = x;
size += 1;
return true;
}
// 出队
bool MyQueue::Pop() {
if(size == 0) {
cout << "Queue is Underflow" << endl;
return false;
}
int x = array[front];
front = (front + 1) % capacity;
size -= 1;
return x;
}
// 取队头元素
int MyQueue::Front() {
if(size == 0) {
cout << "Queue is Underflow" << endl;
return -1;
}
return array[front];
}
// 取队尾元素
int MyQueue::Back() {
if(size == 0) {
cout << "Queue is Underflow" << endl;
return -1;
}
return array[rear];
}
由栈实现队列
#include <iostream>
#include <stack>
using namespace std;
class MyQueue {
private:
stack<int> s; // 用于入队
stack<int> s2; // 用于出队
public:
void Push(int x);
void Pop();
int Front();
int Back();
bool Empty();
int Size();
};
// 入队
void MyQueue::Push(int x) {
s.push(x);
}
// 出队
void MyQueue::Pop() {
if(s2.empty()) {
if(s.empty()) {
// s2为空,s为空,表示整个队列为空
cout << "The Queue is Empty" << endl;
return;
} else {
// s2为空,s不为空,则将s中的元素依次压入s2中
while(!s.empty()) {
s2.push(s.top());
s.pop();
}
}
}
if(!s2.empty()) {
// s2不为空,其栈顶元素就是最先进入的元素,即队首元素
s2.pop();
}
}
// 获取队首元素
int MyQueue::Front() {
// 与出队原理一样,只是将pop()变为top()
if(s2.empty()) {
if(s.empty()) {
cout << "The Queue is Empty" << endl;
return -1;
} else {
while(!s.empty()) {
s2.push(s.top());
s.pop();
}
}
}
if(!s2.empty()) {
return s2.top();
}
}
// 获取队尾元素
int MyQueue::Back() {
// 因为每次入队均将元素压入s中,因此s的栈顶元素即为队尾元素
// 同样的道理,当s为空使,s2不为空时,s2中的栈顶->栈底 对应 队首->队尾
// 因此,需要将s2中的元素依次压入s中
if(s.empty()) {
if(s2.empty()) {
// s为空,s2为空,即整个队列为空
cout << "The Queue is Empty" << endl;
return -1;
} else {
// s为空,s2不为空,则将s2中的元素依次压入s中
while(!s2.empty()) {
s.push(s2.top());
s2.pop();
}
}
}
if(!s.empty()) {
// s不为空,其栈顶元素就是队列的队尾元素
return s.top();
}
}
// 判断队列是否为空
bool MyQueue::Empty() {
return (s.empty() && s2.empty());
}
// 获取栈中元素的个数
int MyQueue::Size() {
return (s.size() + s2.size());
}
相关题目
[TOC]
621 Task Scheduler【任务调度器】
题目描述:
给定一个用字符数组表示的 CPU 需要执行的任务列表。其中包含使用大写的 A - Z 字母表示的26 种不同种类的任务。任务可以以任意顺序执行,并且每个任务都可以在 1 个单位时间内执行完。CPU 在任何一个单位时间内都可以执行一个任务,或者在待命状态。
然而,两个相同种类的任务之间必须有长度为 n 的冷却时间,因此至少有连续 n 个单位时间内 CPU 在执行不同的任务,或者在待命状态。
你需要计算完成所有任务所需要的最短时间。
示例1:
输入: tasks = ["A","A","A","B","B","B"], n = 2
输出: 8
执行顺序: A -> B -> (待命) -> A -> B -> (待命) -> A -> B.
// 算法1:优先安排出现次数最多的任务
func leastInterval(tasks []byte, n int) int {
m := make([]int, 26)
for _, t := range tasks {
m[t - 'A']++
}
sort.Slice(m, func(i, j int) bool {
return m[i] < m[j]
})
var res int
for m[25] > 0 {
i := 0
for i <= n {
if m[25] == 0 {
break
}
if i < 16 && m[25-i] > 0 {
m[25-i]--
}
res++
i++
}
sort.Slice(m, func(i, j int) bool {
return m[i] < m[j]
})
}
return res
}
// 算法二:设计,利用空闲时间[leetcode-cn]
func leastInterval(tasks []byte, n int) int {
m := make([]int, 26)
for _, t := range tasks {
m[t - 'A']++
}
sort.Slice(m, func(i, j int) bool {
return m[i] < m[j]
})
max_val := m[25] - 1
idle := n * max_val
for i := 24; i >= 0 && m[i] > 0; i-- {
if m[i] <= max_val {
idle -= m[i]
} else {
idle -= max_val
}
}
if idle > 0 {
return idle + len(tasks)
}
return len(tasks)
}
最后更新于