扩展问题
如果要求按深度从下到上访问图3-23中的二叉树,每层的访问顺序仍然是从左到右:
比较容易想到的方法是先按照层序弄好一个待遍历数组,层与层之间考虑用一个标识NULL作为分割,这样只需要反向遍历这个数组就行了,不过要注意的是弄这个遍历数组一定要先压入右节点,再压入左节点。
代码
void printNodeByLevel(Node *root)
{
vector<Node*> vec;
int cur , last;//设定该层的起始点和结束点
vec.push_back(root);
cur = 0;last = vec.size();
while(cur<vec.size()){//循环截止条件:没有更多层了
last = vec.size();
vec.push_back(NULL);//作为层间分割标识
while(cur<last){//遍历一层
if(vec[cur]->pRChild)//有右孩子
vec.push_back(vec[cur]->pRChild);
if(vec[cur]->pLChild)//有左孩子
vec.push_back(vec[cur]->pLChild);
cur++;
}
cur++;//跳过NULL标志位
}
vec.pop_back();//去掉最后一个NULL
//---逆序遍历数组
for(int i=vec.size()-1 ; i>=0 ; i--){
if(vec[i] == NULL){//碰到层间分割
cout<<endl;
continue;
}
cout<<vec[i]->data<<" ";
}
cout<<endl;
}
扩展问题 2
如果按深度从下到上访问,每层的访问顺序变成从右到左:
把上题中的先压右孩子改为先压左孩子
分析:只要层与层之间加入哑元素(NULL),然后逆序输出队列Q即可
第一步:给每一层之间添加哑元素NULL
void PrintNodeByLevel(Node *root)
{
int last;
Node *p;
if(!root) return ;
InitQueue();
EnQueue(root);
EnQueue(NULL);
while(front < rear - 1)
{
last = rear - 1;
while(front < last)
{
p = DeQueue();
if(p->lChild) EnQueue(p->lChild);
if(p->rChild) EnQueue(p->rChild);
}
EnQueue(NULL);
front = last + 1;
}
}
第二步:逆序输出队列Q
for(int i = rear - 2 ; i >= 0 ; i--)
{
if(Q[i] == NULL) //加入哑元素方便换行
printf("\n");
else
printf("%c", Q[i]->chValue);
}
百度面试题 要求输出二叉树第m层第k个节点值(m,k均从0开始计数)
考虑第m层节点相当于考虑从根孩子节点出发的第m-1层节点,然后进行引用计数或使用全局变量。
Code
//寻找从根节点开始第m层的第k个节点也就是寻找从根节点的孩子节点开始的第m-1层第k个节点
int findKNode(Node *root , int m , int k , int &count)//找到root为根的子树第m层第k个节点值
{
if(m<0 || !root)
return 0;
if(m==0){//找到第m层
if(k == count){//找到第k个数
cout<<root->data<<endl;
return 1;
}
count++;//如果count是指针传入,注意*count++是count指针++后再解引用,正确做法是(*count)++
return 0;//未找到第k个数
}
if(findKNode(root->pLChild,m-1,k,count) || findKNode(root->pRChild,m-1,k,count))
return 1;
return 0;
}