编程之美 3.10 分层遍历二叉树 扩展问题

扩展问题

如果要求按深度从下到上访问图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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值