问题描述:输入一颗二元树,从上往下按层打印树的每个结点,同一层中按照从左往右的顺序打印。
例如输入
8
/ /
6 10
/ / / /
5 7 9 11
输出8 6 10 5 7 9 11。
定义二元树(其实是二元搜索树,但并不遍历算法)的结点为:
- struct BSTreeNode
- {
- int value;
- BSTreeNode *left;
- BSTreeNode *right;
- };
思路:利用队列的先进先出,很容易实现。每次取出队列的首元素,然后将其左右子女放入队列中。直至队列为空即可。按这种方式进出队列,正好是按层遍历二元树。
参考代码:
- //函数功能 : 按层次遍历二元树
- //函数参数 : 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