1.队列的实现
#include<iostream>
#include<vector>
using namespace std;
class MyQueue {
private:
// store elements
vector<int> data;
// a pointer to indicate the start position
int p_start;
public:
MyQueue() {p_start = 0;}
/** Insert an element into the queue. Return true if the operation is successful. */
bool enQueue(int x) {
data.push_back(x);
return true;
}
/** Delete an element from the queue. Return true if the operation is successful. */
bool deQueue() {
if (isEmpty()) {
return false;
}
p_start++;
return true;
};
/** Get the front item from the queue. */
int Front() {
return data[p_start];
};
/** Checks whether the queue is empty or not. */
bool isEmpty() {
return p_start >= data.size();
}
};
int main() {
MyQueue q;
q.enQueue(5);
q.enQueue(3);
if (!q.isEmpty()) {
cout << q.Front() << endl;
}
q.deQueue();
if (!q.isEmpty()) {
cout << q.Front() << endl;
}
q.deQueue();
if (!q.isEmpty()) {
cout << q.Front() << endl;
}
}
在这种情况下很容易造成内存空间的浪费。
2.循环队列
注意这里内存大小k+1
#include<iostream>
using namespace std;
class MyCircularQueue {
private:
int* data;
int size;
int head;
int tail;
public:
/** Initialize your data structure here. Set the size of the queue to be k. */
MyCircularQueue(int k) {
data = new int[k+1];
size = k+1;
head = 0;
tail = 0;
}
/** Insert an element into the circular queue. Return true if the operation is successful. */
bool enQueue(int value) {
if(!isFull())
{
tail = (tail + 1)%size;
data[tail] = value;
return true;
}
return false;
}
/** Delete an element from the circular queue. Return true if the operation is successful. */
bool deQueue() {
if(isEmpty())
return false;
head = (head + 1) %size;
return true;
}
/** Get the front item from the queue. */
int Front() {
if(isEmpty())
return -1;
return data[(head+1)%size];
}
/** Get the last item from the queue. */
int Rear() {
if(isEmpty())
return -1;
return data[tail];
}
/** Checks whether the circular queue is empty or not. */
bool isEmpty() {
if(head == tail)
return true;
return false;
}
/** Checks whether the circular queue is full or not. */
bool isFull() {
if((tail + 1) %size == head)
return true;
return false;
}
};
int main() {
MyCircularQueue q(3);
cout<<q.enQueue(1)<<endl;
cout<<q.enQueue(2)<<endl;
cout<<q.enQueue(3)<<endl;
cout<<q.enQueue(4)<<endl;
cout<<q.Rear()<<endl;
cout<<q.isFull()<<endl;
cout<<q.deQueue()<<endl;
cout<<q.enQueue(4)<<endl;
cout<<q.Rear()<<endl;
}
3.队列和 BFS
BFS 的两个主要方案:遍历
或找出最短路径
。
(1)BFS模板1
/**
* Return the length of the shortest path between root and target node.
*/
int BFS(Node root, Node target) {
Queue<Node> queue; // store all nodes which are waiting to be processed
int step = 0; // number of steps neeeded from root to current node
// initialize
add root to queue;
// BFS
while (queue is not empty) {
step = step + 1;
// iterate the nodes which are already in the queue
int size = queue.size();
for (int i = 0; i < size; ++i) {
Node cur = the first node in queue;
return step if cur is target;
for (Node next : the neighbors of cur) {
add next to queue;
}
remove the first node from queue;
}
}
return -1; // there is no path from root to target
}
- 如代码所示,在每一轮中,队列中的结点是
等待处理的结点
。 - 在每个更外一层的
while
循环之后,我们距离根结点更远一步
。变量step
指示从根结点到我们正在访问的当前结点的距离。
(2)BFS模板2
有时,确保我们永远不会访问一个结点两次
很重要。否则,我们可能陷入无限循环。如果是这样,我们可以在上面的代码中添加一个哈希集来解决这个问题。这是修改后的伪代码:
/**
* Return the length of the shortest path between root and target node.
*/
int BFS(Node root, Node target) {
Queue<Node> queue; // store all nodes which are waiting to be processed
Set<Node> used; // store all the used nodes
int step = 0; // number of steps neeeded from root to current node
// initialize
add root to queue;
add root to used;
// BFS
while (queue is not empty) {
step = step + 1;
// iterate the nodes which are already in the queue
int size = queue.size();
for (int i = 0; i < size; ++i) {
Node cur = the first node in queue;
return step if cur is target;
for (Node next : the neighbors of cur) {
if (next is not in used) {
add next to queue;
add next to used;
}
}
remove the first node from queue;
}
}
return -1; // there is no path from root to target
}
200.岛屿的个数
给定一个由 '1'
(陆地)和 '0'
(水)组成的的二维网格,计算岛屿的数量。一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的。你可以假设网格的四个边均被水包围。
示例 1:
输入:
11110
11010
11000
00000
输出: 1
示例 2:
输入:
11000
11000
00100
00011
输出: 3
思路:循环遍历每个点,如果该点是0,则跳过;如果是1,加入队列并将该点改为0,避免重复访问。然后进行广搜,取出队首元素,搜索该点周围四个点,如果有1就加入队列,并将1改为0,否则就跳过,当队列空时,一块岛屿搜索完毕,岛屿数目加1。进入下一块搜索,如此下去。。。
搜索时注意数组是否越界
class Solution {
public:
int numIslands(vector<vector<char>>& grid) {
if(grid.empty() || grid[0].empty())
return 0;
int m = grid.size(), n = grid[0].size();
int res = 0;
queue<pair<int,int>> island;
pair<int, int> pos;
for(int i = 0; i < m;i++)
for(int j = 0; j < n; j++)
{
if(grid[i][j] == '0')
continue;
else
{
pos.first = i;
pos.second = j;
island.push(pos);
grid[i][j] = '0';
while(!island.empty())
{
pos = island.front();
island.pop();
int x = pos.first;
int y = pos.second;
if(x-1 >= 0 && grid[x-1][y] == '1')
{
pos.first = x-1;
pos.second = y;
island.push(pos);
grid[x-1][y] = '0';
}
if(x+1 < m && grid[x+1][y] == '1')
{
pos.first = x+1;
pos.second = y;
island.push(pos);
grid[x+1][y] = '0';
}
if(y-1 >= 0 && grid[x][y-1] == '1')
{
pos.first = x;
pos.second = y-1;
island.push(pos);
grid[x][y-1] = '0';
}
if(y+1 < n && grid[x][y+1] == '1')
{
pos.first = x;
pos.second = y+1;
island.push(pos);
grid[x][y+1] = '0';
}
}
res++;
}
}
return res;
}
};</