1.问题定义
给定一棵二叉树,要求按分层遍历该二叉树,即从上到下按层次访问该二叉树(每一层将单独输出一行),每一层要求访问的顺序为从左到右,并将节点依次编号。下面是一个例子:
正确输出为:
1
2 3
4 5 6
7 8
节点定义:
struct Node { Node *pLeft; //节点数据 Node *pRight; //左指针 int data; //右指针 };
2.编程之美解法
书上举出两个解法。第一个解法是用递归方式,搜寻并打印某一层的节点,再打印下一层的节点。这方法简单但时间效率不高(但不需要额外空间),因此书中亦提供了第二个解法。 书中第二个解法,使用vector容器来储存n个节点信息,并用一个游标变量last记录前一层的访问结束条件,实现如下:
void PrintNodeByLevel(Node* root) { vector<Node*> vec; // 这里我们使用STL 中的vector来代替数组,可利用到其动态扩展的属性 vec.push_back(root); int cur = 0; int last = 1; while(cur < vec.size()) { Last = vec.size(); // 新的一行访问开始,重新定位last于当前行最后一个节点的下一个位置 while(cur < last) { cout << vec[cur] -> data << " "; // 访问节点 if(vec[cur] -> lChild) // 当前访问节点的左节点不为空则压入 vec.push_back(vec[cur] -> lChild); if(vec[cur] -> rChild) // 当前访问节点的右节点不为空则压入,注意左右节点的访问顺序不能颠倒 vec.push_back(vec[cur] -> rChild); cur++; } cout << endl; // 当cur == last时,说明该层访问结束,输出换行符 } }
3.别人的解法
详见:http://www.cnblogs.com/miloyip/archive/2010/05/12/binary_tree_traversal.html
4.我的想法
与书上的想法类似,同样设置两个标量,i,j,分别用来记录当前层的节点个数和下一层的节点个数(我想能记录二叉树每层的节点个数,或许多其它算法有用吧)
void PrintNodeByLevel(Node *root) { queue<Node*> Q; if (root != NULL) { Q.push(root); } else return; int i = 1;//用来记录每一层有多少个结点 int j = 0;//用来记录下一层有多少个节点 do{ i--;//i减少一次 说明当前层出去了一个,当i=0时,表示当前层都出队了 Node *node = Q.front(); Q.pop(); cout<<node->data<<" ";//当然这里每层结尾都多输出一个空格" ",你也可以在这里做个判断:if (i != 0),否则就把输出放到i == 0的地方输出 if (node->pLeft != NULL) { j++; Q.push(node->pLeft); } if (node->pRight != NULL) { j++; Q.push(node->pRight); } if (i == 0)//表示当前层都出队了,输出换行 { i = j;//把下一层的个数给i j = 0; cout<<endl; } }while(!Q.empty()); }
空间复杂度为O(m),m为所有层中的最大数量。比书上的vector,O(n),一般情况下少一点。