题目描述:
实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。
分析:
对于一个n层的二叉树,可以使用一个数组将二叉树按层序记录下来,特别的为了明确的分割每一层,要将二叉树的前n-1层填满。方法是,对于一个NULL节点,若在它之后还有不为NULL的结点那么就用NULL填充它的子节点位置,直到遍历完所有位置为止;然后按层序打印二叉树,每一层结束元素的下标为2^n - 2 (前n层的元素个数是2^n - 1 个,所以其下标就是2^n - 2).
vector<vec<int>> PrintTree(Node *tree){
vector<vector<Node*>> ret;
vector<int> num;
vector<vector<int>> result;
if(tree == NULL)
return result;
ret.push_back(tree);
int len = 0;
int lastLocal = 0;
while(len < ret.size()){
if(ret[len] != NULL){
ret.push_back(ret[len]->left);
// if(ret[len]->left != NULL)
// lastLocal = len*2+1;
ret.push_back(ret[len]->right);
// if(ret[len]->right != NULL)
// lastLocal = len*2+2;
}else{//将二叉树的前n-1层填满
if(!AllIsNull(ret, len)){//使用函数判断次结点之后害有没有不为NULL的结点
//每次调用函数来判断会有重复遍历的情况,
//解决方法是维护一个lastLocal值来记录当前最后一个不为NULL的结点的下标
//每次只需要判断len是否小于lastLocal .
// if(len < lastLocaol)
ret.push_back(NULL);
ret.push_back(NULL);
}
}
len++;
}
int i = 0; n = 1;
bool flage = true;
while(i < ret.size()){
if(flage){//正序打印
num.clear();
int tmp = pow(2, n) - 2;
for(int j = i; j <= MinNum(tmp, ret.size()-1); j++){
if(ret[j] != NULL)
num.push_back(ret[j]->val);
}
i = MinNum(tmp, ret.size()-1) + 1;
if(num.size() > 0)
result.push_back(num);
flage = false;
n += 1;
}else{//反序打印
num.clear();
for(int j = MinNum(pow(2, n)-2, ret.size()-1); j >= i; j--){
if(ret[j] != NULL)
num.push_back(ret[j]->val);
}
if(num.size() > 0)
result.push_back(num);
i = MinNum(pow(2, n)-2, ret.size()-1);
flage = true;
n += 1;
}
}
return result;
}
int MinNum(int a, int b){
return (a < b) ? a : b;
}
bool AllIsNull(vector<Node*>& ret, int len){//判断在此之后还有没有不为NULL的结点
for(int i = len + 1; i < ret.size(); i++){
if(ret[i] != NULL)
return false;
}
return true;
}