二叉树的层序遍历(要求区分层,比如每层遍历完输出换行)



单单层序遍历很easy,一个队列就搞定了,可是区分层则要麻烦些。总的思路无非就是在每次print的时候,要能通过某个东西

区分出当前节点是否是一层最后一个节点,或者下一层的最后一个节点,感觉有点类似于机器学习中找个区分度明显的特征:



1.自己的解法,在单队列基础上,输入队列的数据加入一个标志 ,LevelHeaded,同一时候,在后面插入两个孩子的时候,推断是否这次输出的是队头,假设是的话,先插

个队头标志,再插入孩子,并且插入一次之后,后面不能插入,用LevelFirst布尔变量来控制。



代码例如以下

void LevelOrder(node* p)
{
Queue<node *> Q;
Bool LevelFirst=false;
Q.Enqueue(root);
while(quene is not empyty)
{
Q.Dequeue(p);
if(q==LevelHead)
{
p=Q.Dequeue(p);
LevelFirst=true;
cout<<endl;
cout<<q->data;
}
else
{
cout<<q->data;
}

if(p->left)
{
if(LevelFirst=true)
{
Q.Enqueue(LevelHead);LevelFirst=False;
}
Q.Enqueue(p->left);
}
if(p->right)
{
if(LevelFirst=true)
{
Q.Enqueue(LevelHead);LevelFirst=False;
}
Q.Enqueue(p->right);
}
}
}





2.编程之美解法:



解法1:指示当前层的结束位置,判读当前index是否等于结束位置,使用vector来实现。而且里面两重循环,里层表示一层结点的处理,外层表示整个的处理

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时,说明该层訪问结束,输出换行符
}
}





解法2:先解决訪问每层结点,然后遍历层,前提还要知道树高,只是后面发现能够通过前面函数返回状态值免除求树高的过程

再次不赘述,树高也能够用递归来求解




解法1:用两个队列,将取出队列和插入两个儿子到队列分开到两个队列里的操作。



然后一层结束标志是取元素队列为空,然后与下一个队列交换内容,实质是交换指针,Mileho是这么解释的.



解法2:记录当前层在队列中的节点数NodesInCurrentLevel,以及下一层在队列的节点数NodesInNextLevel,推断Current变量是否为0来区分层结束




这个链接还上了编程之美书:



解法1:同上面某人博客解法1,事实上应该是这个时间早

解法2:和我的思路一致,增加一个层结束标志,可是程序的逻辑设计的比我的beautiful,少一个bool变量,并且看起来程序短。



void PrintNodeByLevel(Node* root) {
queue<Node*> Q;
Q.push(root);
Q.push(0);
do {
Node* node = Q.front();
Q.pop();
if (node) {
cout << node->data << " ";
if (node->pLeft)
Q.push(node->pLeft);
if (node->pRight)
Q.push(node->pRight);
}
else if (!Q.empty()) {
Q.push(0);
cout << endl;
}
} while (!Q.empty());
}





总结:1 实现queue的时候,都不是node类型,而是node* 类型,这样插入LevelHead标志都会比較方便,并且当swap两个队列空间复杂度为O(1),之前老师教的时候

好像都没太注意这个地方

 2.单队列实现,空间复杂度O(n) 详细为最大长度为结点数最多的一层的结点数,n个节点最大值为(n+1)/2

 3.遇到问题,首先是大致思路,确定下来后,设计须要的变量,小心设计逻辑,这里的思路里面  区分层有点类似于ML中的找特征

 4.思路正确,代码逻辑不一定正确,20 80原理


另外看到另一个求十进制表示的二进制数的1的位数,Hamming_weight,也才知道还有个名词