这里写自定义目录标题
搜索(DFS,BFS)
BFS
较为典型的有求最短步数,最少次数,最短时间等等。
洛谷 P1135\2895…
void bfs(para1, .....) {
q.push(para1);
vis[] = 1;
while (!q.empty()) {
struct_type tmp = q.front();
q.pop();
for (相邻节点) {
if (满足终止条件) {
记录;
return;
}
if(满足入队条件){
q.push();
vis[]
}
}
}
}
DFS
常见的有回溯法,染色法,以及遍历。
以回溯法为例。染色的时候就不用取消标记了。
常见的:求连通块数量,求小岛面积,求路径数量等。
void dfs(para1, .....){
if(满足终止条件){
记录;
return;
}
vis[]=1 //标记
for(对所有相邻节点遍历dfs){
dfs()
}
vis[]=0 //撤销标记
}
树的遍历
前序遍历对应dfs。层次遍历对应bfs。
已知前序和中序,求出后序遍历。
(或已知中序和后序,求前序)
前序的第一个节点是整棵树的根节点。
根节点又把中序分为左子树的中序,和右子树的中序。
前序也可以分为左子树的前序和右子树的前序。
而后序的最后一个节点也是整棵树的根节点。
所以递归就可以解决。
void backToPreorder(string s1, string s2) {//s1为中序,s2为后序
if (s1.size() == 0) {
return;
}
if (s1.size() == 1) {
cout << s1;
return;
}
int l = s2.size();
int index = s1.find(s2[l - 1]);
cout << s2[l - 1];
string ls1 = s1.substr(0, index);
string rs1 = s1.substr(index + 1);
string ls2 = s2.substr(0, ls1.size());
string rs2 = s2.substr(ls1.size(),rs1.size());
backToPreorder(ls1, ls2);
backToPreorder(rs1, rs2);
}
void backToPostorder(string s1, string s2) {//s1为前序,s2为中序
if (s1.size() == 0) {
return;
}
if (s1.size() == 1) {
cout << s1;
return;
}
int index = s2.find(s1[0]);
string ls2 = s2.substr(0, index);
string rs2 = s2.substr(index + 1);
string ls1 = s1.substr(1, ls2.size());
string rs1 = s1.substr(ls2.size()+1, rs2.size());
backToPostorder(ls1, ls2);//求左子树的后序遍历
backToPostorder(rs1, rs2);//求右子树的后序遍历
cout << s1[0];//根节点
}