解题笔记(33)——按层次遍历二元树

        问题描述:输入一颗二元树,从上往下按层打印树的每个结点,同一层中按照从左往右的顺序打印。  

        例如输入

   8

  / /

 6 10

/ / / /

5 7 9 11

输出8 6 10 5 7 9 11。

          定义二元树(其实是二元搜索树,但并不遍历算法)的结点为:

  1. struct BSTreeNode    
  2. {    
  3.     int value;    
  4.     BSTreeNode *left;    
  5.     BSTreeNode *right;    
  6. };    

      思路:利用队列的先进先出,很容易实现。每次取出队列的首元素,然后将其左右子女放入队列中。直至队列为空即可。按这种方式进出队列,正好是按层遍历二元树。

      参考代码:

//函数功能 : 按层次遍历二元树
//函数参数 : pRoot指向根结点
//返回值 :   无
void LevelReverse(BSTreeNode *pRoot)
{
	if(pRoot == NULL)
		return;

	queue<BSTreeNode *> nodeQueue;
	nodeQueue.push(pRoot);
	while(nodeQueue.size())
	{
		BSTreeNode * pNode = nodeQueue.front(); //取队首元素
		nodeQueue.pop(); //必须出队列
		if(pNode->left)  //左子女
			nodeQueue.push(pNode->left);
		if(pNode->right) //右子女
			nodeQueue.push(pNode->right);

		cout<<pNode->value<<' ';
	}
}

       扩展一:上文给出的代码,所有结点都输出在同一行。如果希望仅仅同层结点输出在同一行,该如何修改代码呢?

       思路:如果我们能知道每层的最后一个结点,那么就方便多了,输出每层最后一个结点的同时,输出一个换行符。因此,关键在于如何标记每层的结束。可以考虑在每层的最后一个点之后,插入一个空结点。比如队列中先放入根结点,由于第0层只有一个结点,因此放入一个空结点。然后依次取出队列中的结点,将其子女放入队列中,如果遇到空结点,表明当前层的结点已遍历完了,而队列中放的恰恰是下一层的所有结点。如果当前队列为空,表明下一层无结点,也就说是所有结点已遍历好了。如果不为空,那么插入一个空结点,用于标记下一层的结束。

      参考代码:

void LevelReverse(BSTreeNode *pRoot)
{
	if(pRoot == NULL)
		return;
	queue<BSTreeNode *> nodeQueue;  
	nodeQueue.push(pRoot);  
	nodeQueue.push(NULL);   //放入空结点,作为层的结束符
	while(nodeQueue.size())
	{
		BSTreeNode * pNode = nodeQueue.front(); //取队首元素  
        nodeQueue.pop(); //必须出队列 
		if(pNode)
		{
			if(pNode->left)  //左子女  
				nodeQueue.push(pNode->left);  
			if(pNode->right) //右子女  
				nodeQueue.push(pNode->right);
			cout<<pNode->value<<' ';  
		}
		else if(nodeQueue.size()) //如果结点为空并且队列也为空,那么所有结点都已访问
		{
			nodeQueue.push(NULL);
			cout<<endl;
		}
	}
}

       扩展二:之前讨论的都是从上往下、从左往右遍历二叉树,那么如果希望自下往上、从左右往右遍历二叉树,该如何修改代码呢?

       思路:比较简单的方法,首先遍历二叉树,将所有结点保存在一个数组中,遍历的同时记录每一层在数组中的起止位置。然后根据起止位置,就可以自下往上的打印二叉树的结点。

//每层的起止位置
struct Pos
{
	int begin;
	int end;
	Pos(int b, int e): begin(b),end(e) {}
};
void LevelReverse(BSTreeNode *pRoot)
{
	if(pRoot == NULL)
		return;

	vector<BSTreeNode*> vec;   //用以存放所有结点
	vector<Pos> pos;           //用以记录每层的起止位置
	vec.push_back(pRoot);

	int level = 0;    //树的层数
	int cur = 0;
	int last = 1;

	while(cur < vec.size())
	{
		last = vec.size();
		pos.push_back(Pos(cur, last)); //记录当前层的起止位置

		while(cur < last) //遍历当前层的结点,将子女放入数组中
		{
			if(vec[cur]->left) //先是左然后是右。如果希望自由向左,交换一下顺序即可
				vec.push_back(vec[cur]->left);
			if(vec[cur]->right)
				vec.push_back(vec[cur]->right);
			cur++;
		}
		level++; //层数加1
	}

	for(int i = level - 1; i >= 0; i--) //自下往上遍历
	{
		for(int j = pos[i].begin; j < pos[i].end; j++)
			cout<<vec[j]->value<<' ';
		cout<<endl;
	}
}

        本人享有博客文章的版权,转载请标明出处 http://blog.csdn.net/wuzhekai1985

猜你喜欢

转载自blog.csdn.net/wuzhekai1985/article/details/6730352
今日推荐