书中解法三用数组来对树进行BFS,比较适合在比赛中使用,如果使用队列的话,当数据规模比较大的时候,频繁的进队列,出队列还是很耗时的。 比较经典的“聪明的打字员”一题,就是BFS搜索,但是数据规模比较大,用队列的话很容易超时,参考PKU1184.
扩展问题一、二是按深度从下到上遍历二叉树,从左向右或者从右向左。
我们可以在开始根节点遍历的时候,每层遍历结束之后,存放一个 NULL 作为层与层之间的分割,当整棵树遍历完之后,再从后向前遍历数组,遇到 NULL 表示当前层结束,这样就可以实现按深度从下到上的遍历。
算法的时间复杂度与按深度从上到下时间复杂度相同,空间多用了4*H Bytes ( H 为树的高度 )
#include <vector>
#include <iostream>
using namespace std;
struct node
{
node* left;
node* right;
int value;
node( int v ): value( v ),left(NULL),right(NULL) {};
};
vector<const node*> vec;
void steps( const node* root, bool fromLeftToRight ) //true: 从左往右遍历 //false: 从右往左遍历
{
int cur = 0;
int last;
vec.clear();
vec.push_back( root );
while ( cur < vec.size() )
{
last = vec.size();
vec.push_back( NULL ); //层与层之间的分割
while( cur < last )
{
if ( fromLeftToRight )
{
if ( vec[cur]->right )
vec.push_back(vec[cur]->right);
if ( vec[cur]->left )
vec.push_back( vec[cur]->left);
}
else
{
if ( vec[cur]->left )
vec.push_back( vec[cur]->left );
if ( vec[cur]->right )
vec.push_back( vec[cur]->right );
}
cur++;
}
cur += 1 ; //跳过层与层之间的NULL节点
}
//反向遍历数组
vector<const node*>::const_reverse_iterator cri;
for( cri = vec.rbegin() + 1; cri != vec.rend(); cri++ )
{
if ( !*cri )
{
cout << endl;
}
else
{
cout << (*cri)->value << " " ;
}
}
cout << endl;
}
书中的 test case:
int main()
{
node* root = new node(1);
node* tmp = new node(2);
root->left = tmp;
tmp = new node(3);
root->right = tmp;
tmp = new node(4);
root->left->left = tmp;
tmp = new node(5);
root->left->right = tmp;
tmp = new node(6);
root->right->right = tmp;
tmp = new node(7);
root->left->right->left = tmp;
tmp = new node(8);
root->left->right->right = tmp;
cout << "From Left To the Right " << endl;
steps(root,true);
cout << "From Right To the Left " << endl;
steps(root,false);
return 0;
}
本文出自:http://hi.baidu.com/azuryy/item/d108414bbf982a0a6dc2f0d7