Heap是一种先进先出的数据结构,当然经过了改进,后面有了双向的deque和极值在堆顶的特殊结构。这一篇主要讲的就是通用的queue,另外的deque和priority_queue可以进一步看看。
queue
queue:
- init with list instead of default deque is fast. queue<int, list
> is better. - Constructor like: queue
que({1,2,3}); list/deque - operation:empty, size, front(non-const reference), back, push, pop.
- Non-member: swap, swap two queue.
deque:
- Constructor: deque
(4, 5); 4 个 5;deque (iter.begin(), iter.end()) - push_front, push_back, insert, pop_front, pop_back, emplace, emplace_front, emplace_back, front, back, begin, end, r(c)begin, clear, at(boundary check), [], resize, erase
- Empty, size, swap, max_size, shrink_to_fit(an optimization skill), assign
- Non-member: swap
priority_queue:
- heap sort
- Top(const reference), push, emplace, pop, empty, swap, size, swap
- emplace 可以直接调用构造函数,直接传构造函数的参数即可。push先需要构造出对象,多了一次拷贝。
- https://blog.csdn.net/Kprogram/article/details/82055673
- Non-member: swap
- 常用初始化方法:(默认最大堆,top是最大的元素)
class mycomparison
{
bool reverse;
public:
mycomparison(const bool& revparam=false)
{reverse=revparam;}
bool operator() (const int& lhs, const int&rhs) const
{
if (reverse) return (lhs>rhs);
else return (lhs<rhs);
}
};
int myints[]= {10,60,50,20};
std::priority_queue<int> first;
std::priority_queue<int> second (myints,myints+4);
std::priority_queue<int, std::vector<int>, std::greater<int> >
third (myints,myints+4);
// using mycomparison:
typedef std::priority_queue<int,std::vector<int>,mycomparison> mypq_type;
mypq_type fourth; // less-than comparison
mypq_type fifth (mycomparison(true)); // greater-than comparison
初始化的时候,如果是自定义的话,需要把这个自定义加上
std::priority_queue<mergeRecord, std::vector<mergeRecord>, mycomparison>
recsHeap(std::begin(initialRecords), std::end(initialRecords), mycomparison(false,field));
// 621. Task Scheduler
// Method 1: mathematics
int leastInterval(vector<char>& tasks, int n) {
int frequency[26] = {0};
for (const auto task : tasks) {
++frequency[task-'A'];
}
int max_frequency = 0;
int max_num = 0;
for (int i = 0; i < 26; ++i) {
if (frequency[i] > max_frequency) {
max_frequency = frequency[i];
max_num = 1;
} else if (frequency[i] == max_frequency) {
++max_num;
}
}
return max(tasks.size(), static_cast<unsigned long>((max_frequency - 1) * (n + 1) + max_num));
}
// Method 2: priority_queue
int leastInterval(vector<char>& tasks, int n) {
unordered_map<char, int> record;
for (const auto task : tasks) {
++record[task];
}
priority_queue<int> status;
for (const auto [name, frequency] : record) {
status.push(frequency);
}
int ans = 0;
while (!status.empty()) {
vector<int> tmp;
int count = 0;
for (int i = 0; i <= n; ++i) {
if (status.empty()) break;
tmp.push_back(status.top());
++count;
status.pop();
}
for (auto& t : tmp) {
if (--t > 0) {
status.push(t);
}
}
ans += status.empty() ? count : n + 1;
}
return ans;
}
// 622. Design Circular Queue
class MyCircularQueue {
public:
int size_ = 0;
int front_idx_ = -1;
int rear_idx_ = -1;
vector<int> data_;
MyCircularQueue(int k) {
size_ = k;
data_.resize(k);
}
bool enQueue(int value) {
if (isFull()) return false;
if (isEmpty()) {
front_idx_ = rear_idx_ = 0;
} else {
++rear_idx_;
rear_idx_ %= size_;
}
data_[rear_idx_] = value;
return true;
}
bool deQueue() {
if (isEmpty()) return false;
if (front_idx_ == rear_idx_) {
front_idx_ = rear_idx_ = -1;
} else {
front_idx_ = ++front_idx_ % size_;
}
return true;
}
int Front() {
return front_idx_ == -1? -1:data_[front_idx_];
}
int Rear() {
return rear_idx_ == -1 ? -1:data_[rear_idx_];
}
bool isEmpty() {
return front_idx_ < 0 && rear_idx_ < 0;
}
bool isFull() {
return (front_idx_ - rear_idx_ == 1) || ((rear_idx_ == size_ - 1) && (front_idx_ == 0));
}
};
// 641. Design Circular Deque
class MyCircularDeque {
public:
int size_ = 0;
int count_ = 0;
int front_index_ = -1;
int rear_index_ = -1;
vector<int> data_;
/** Initialize your data structure here. Set the size of the deque to be k. */
MyCircularDeque(int k) {
size_ = k;
data_.resize(k);
}
/** Adds an item at the front of Deque. Return true if the operation is successful. */
bool insertFront(int value) {
if (isFull()) return false;
if (isEmpty()) {
front_index_ = rear_index_ = 0;
}
else {
front_index_ = (front_index_ - 1 + size_) % size_;
}
data_[front_index_] = value;
++count_;
return true;
}
/** Adds an item at the rear of Deque. Return true if the operation is successful. */
bool insertLast(int value) {
if (isFull()) return false;
if (isEmpty()) {
rear_index_ = front_index_ = 0;
} else {
rear_index_ = (rear_index_ + 1) % size_;
}
data_[rear_index_] = value;
++count_;
return true;
}
/** Deletes an item from the front of Deque. Return true if the operation is successful. */
bool deleteFront() {
if (isEmpty()) return false;
front_index_ = (front_index_ + 1) % size_;
--count_;
return true;
}
/** Deletes an item from the rear of Deque. Return true if the operation is successful. */
bool deleteLast() {
if (isEmpty()) return false;
rear_index_ = (rear_index_ - 1 + size_) % size_;
--count_;
return true;
}
/** Get the front item from the deque. */
int getFront() {
return isEmpty() ? -1: data_[front_index_];
}
/** Get the last item from the deque. */
int getRear() {
return isEmpty() ? -1: data_[rear_index_];
}
/** Checks whether the circular deque is empty or not. */
bool isEmpty() {
return !count_;
}
/** Checks whether the circular deque is full or not. */
bool isFull() {
return count_ == size_;
}
};
/**
* Your MyCircularDeque object will be instantiated and called as such:
* MyCircularDeque* obj = new MyCircularDeque(k);
* bool param_1 = obj->insertFront(value);
* bool param_2 = obj->insertLast(value);
* bool param_3 = obj->deleteFront();
* bool param_4 = obj->deleteLast();
* int param_5 = obj->getFront();
* int param_6 = obj->getRear();
* bool param_7 = obj->isEmpty();
* bool param_8 = obj->isFull();
*/
// 353. Design Snake Game
class SnakeGame {
public:
/** Initialize your data structure here.
@param width - screen width
@param height - screen height
@param food - A list of food positions
E.g food = [[1,1], [1,0]] means the first food is positioned at [1,1], the second is at [1,0]. */
deque<pair<int, int>> snake_;
unordered_map<int, bool> record_;
int width_ = 0;
int height_ = 0;
int food_index_ = 0;
vector<vector<int>> food_;
SnakeGame(int width, int height, vector<vector<int>>& food) {
width_ = width;
height_ = height;
food_ = std::move(food);
snake_.emplace_back(make_pair(0, 0));
}
/** Moves the snake.
@param direction - 'U' = Up, 'L' = Left, 'R' = Right, 'D' = Down
@return The game's score after the move. Return -1 if game over.
Game over when snake crosses the screen boundary or bites its body. */
int move(string direction) {
auto tp = snake_.front();
if (direction == "U") {
--tp.first;
} else if (direction == "D") {
++tp.first;
} else if (direction == "L") {
--tp.second;
} else {
++tp.second;
}
if (tp.first < 0 || tp.first >= height_ ||
tp.second < 0 || tp.second >= width_) {
return -1;
}
snake_.emplace_front(tp);
if (food_index_ < food_.size() && (tp.first == food_[food_index_][0]
&& tp.second == food_[food_index_][1])) {
++food_index_;
} else {
const auto tmp = snake_.back();
record_[tmp.first * width_ + tmp.second] = false;
snake_.pop_back();
if (record_[tp.first * width_ + tp.second]) {
return -1;
}
}
record_[tp.first * width_ + tp.second] = true;
return snake_.size() - 1;
}
};
/**
* Your SnakeGame object will be instantiated and called as such:
* SnakeGame* obj = new SnakeGame(width, height, food);
* int param_1 = obj->move(direction);
*/
