思路
回溯
代码
版本一:
#include <iostream>
#include <vector>
using namespace std;
//const int INF = 1e7;
const int MAXN = 1005;
int in[MAXN];
vector<vector<int> > res;
void backtrace(int parent, int n, vector<int> &path){
int child = 2 * parent;
if(child > n){// 如果没有儿子节点,说明到底了,直接返回
vector<int> tmp = path;
res.push_back(tmp);
return;
}
// 这里的回溯数量较少,只有左右节点,所以可以直接写
// 其实如果使用 for 循环反而麻烦
if(child + 1 <= n){// 如果存在右儿子,就先去右儿子的路径
path.push_back(in[child + 1]);
backtrace(child + 1, n, path);
path.pop_back();
}
// 不管是否存在右儿子,下面的代码都应该被执行
path.push_back(in[child]);
backtrace(child, n, path);
path.pop_back();
}
int main(){
int n;
vector<int> path;
scanf("%d", &n);
for(int i=0; i<n; i++){
scanf("%d", &in[i+1]);
}
// 打印函数
path.push_back(in[1]);
backtrace(1, n, path);
for(int i=0; i<res.size(); i++){
for(int j=0; j<res[i].size(); j++){
// printf("%d", res[i][j]);
// if(j < res[i].size() - 1) printf(" ")
printf("%d%s", res[i][j], j < (res[i].size() - 1) ? " " : "\n");
}
//printf("\n");
}
int isMin = 1, isMax = 1;
// 判断,如果满足堆的条件,直接标记
for(int i=2; i<=n; i++){
if(in[i/2] > in[i]){
// 根节点大于儿子,不是最小堆
isMin = 0;
}
if(in[i/2] < in[i]){
// 根节点小于儿子,不是最大堆
isMax = 0;
}
}
if(isMin == 1) printf("Min Heap\n");
else printf("%s", isMax ? "Max Heap\n" : "Not Heap\n");
return 0;
}
版本二:
可以在到底之后直接就打印,不要记录了
#include <iostream>
#include <vector>
using namespace std;
//const int INF = 1e7;
const int MAXN = 1005;
int in[MAXN];
//vector<vector<int> > res;
void backtrace(int parent, int n, vector<int> &path){
int child = 2 * parent;
if(child > n){// 如果没有儿子节点,说明到底了,直接返回
// vector<int> tmp = path;
// res.push_back(tmp);
for(int i=0; i<path.size(); i++){
printf("%d%s", path[i], i < (path.size() - 1) ? " " : "\n");
}
return;
}
// 这里的回溯数量较少,只有左右节点,所以可以直接写
// 其实如果使用 for 循环反而麻烦
if(child + 1 <= n){// 如果存在右儿子,就先去右儿子的路径
path.push_back(in[child + 1]);
backtrace(child + 1, n, path);
path.pop_back();
}
// 不管是否存在右儿子,下面的代码都应该被执行
path.push_back(in[child]);
backtrace(child, n, path);
path.pop_back();
}
int main(){
int n;
vector<int> path;
scanf("%d", &n);
for(int i=0; i<n; i++){
scanf("%d", &in[i+1]);
}
// 打印函数
path.push_back(in[1]);
backtrace(1, n, path);
// for(int i=0; i<res.size(); i++){
// for(int j=0; j<res[i].size(); j++){
printf("%d", res[i][j]);
if(j < res[i].size() - 1) printf(" ")
// printf("%d%s", res[i][j], j < (res[i].size() - 1) ? " " : "\n");
// }
// //printf("\n");
// }
int isMin = 1, isMax = 1;
// 判断,如果满足堆的条件,直接标记
for(int i=2; i<=n; i++){
if(in[i/2] > in[i]){
// 根节点大于儿子,不是最小堆
isMin = 0;
}
if(in[i/2] < in[i]){
// 根节点小于儿子,不是最大堆
isMax = 0;
}
}
if(isMin == 1) printf("Min Heap\n");
else printf("%s", isMax ? "Max Heap\n" : "Not Heap\n");
return 0;
}
参考文献
- [1] 柳神打印例程、判断大小堆例程的代码
- [2] labaladong 回溯算法的讲解