简单二叉树的层次遍历
题目:
例:输入一棵二叉树,你的任务是按从上到下,从左到右的顺序输出每一个节点的值。
每个节点都按照从根节点到它的移动序列给出(L表示左,R表示右)。
在输入中,每个节点的左括号和右括号之间没有空格,相邻节点之间用一个空格隔开。
每课树的输入用一对空括号“()”结束(这对括号本身不代表任何节点)。
注意,如果从根到某个节点的路径上有的节点没有在输入的中给出,或者给出超过一次,输出“Error”。节点个数不超过256个。
样例输入:
(1) (11,LL) (7,LLL) (8,R) (5,) (4,L) (13,RL) (2,LLR) (1,RRR) (4,RR) ()
(2) (3,L) (4,R) ()
样例输出:
(1) 5 4 8 11 13 4 7 2 1
(2) Error
实现代码:
#include<cstdio>
#include<iostream>
#include<stdlib.h>
#include<string>
#include<string.h>
#include<sstream>
#include<queue>
#include<vector>
using namespace std;
struct Node
{
bool have_value; //是否已经赋值
int num; //储存值
Node* left; //左节点
Node* right; //右节点
Node():have_value(false),left(NULL),right(NULL){} //构造函数
};
Node* root; //根节点
bool failed; //判断是否出错
Node* newnode() //创建新节点
{
return new Node();
}
void addnode(int value,string direc) //添加节点
{
Node* u=root;
int len=direc.length();
for(int i=0;i<len;i++)
{
if(direc[i]=='L')
{
if(u->left==NULL)u->left=newnode();//如果左边还没有建立
u=u->left;//u往左走
}
else if(direc[i]=='R')
{
if(u->right==NULL)u->right=newnode();//如果右边还没有建立
u=u->right;//u往右走
}
}
if(u->have_value) failed=true;
u->num=value;
u->have_value=true; //做标记
}
bool read_input()
{
string s;
failed=false;
root=newnode(); //创建根节点
for(;;)
{
cin>>s;
if(s=="()")break; //结束
int num;
stringstream stream;
string input_num;
int i;
for(i=1;;i++)
{
if(s[i]==',')break;
input_num+=s[i]; //值
}
stream<<input_num;
stream>>num; //stream转为值
stream.clear();
string direstore; //存储方向
for(;i<s.length();i++)
{
direstore+=s[i];
}
addnode(num,direstore);
}
return true;
}
int ans[1005];
int k=1;
bool bfs() //入队函数
{
queue<Node*>q;
memset(ans,0,sizeof(ans));
q.push(root);
while(!q.empty())
{
Node*u=q.front();
q.pop();
if(!u->have_value) return false; //没有值 返回错误
ans[k++]=u->num;
//ans.push_back(u->num); //增加到输出数据尾部
if(u->left!=NULL)q.push(u->left); //左节点入列
if(u->right!=NULL)q.push(u->right); //右节点入列
}
return true;
}
//==============================================//
//程序结构:
//1.struct Node
//2.Node* newnode():创建新节点
//3.Node*root; :根节点
//4.bool failed; :判断是否出错
//5.void addnode(int value,string direc):找节点
//6.bool read_input():输入节点
//7.bool bfs() :按序输出
//==============================================//
int main()
{
bool read=read_input();
if(!read || failed)
{
printf("Error\n");
return 0;
}
if(bfs())
{
for(int i=1;i<k;i++)
printf("%d\n",ans[i]);
}
else
{
printf("Error\n");
}
return 0;
}
分块解释:
1.struct Node:节点
struct Node
{
bool have_value; //是否已经赋值
int num; //储存值
Node*left; //左节点
Node*right; //右节点
Node():have_value(false),left(NULL),right(NULL){} //构造函数
};
用Node结构体来定义节点,不管是链表还是树,均使用struct建立节点。
注意的是里面的构造函数使用了初始化列表的形式对节点内容进行初始化:
1.把用来表示是否已经赋值的bool类型变量have_value初始化为false。
2.把指向左右节点的指针置NULL。
2.Node* newnode():创建新节点
Node* newnode() //创建新节点
{
return new Node();
}
用使用new分配一个节点的内存。
3.Node*root :根节点
全局变量。
4.bool failed:判断是否出错
全局变量。
5.void addnode(int value,string direc):添加节点
void addnode(int value,string direc) //添加节点
{
Node* u=root;
int len=direc.length();
for(int i=0;i<len;i++)
{
if(direc[i]=='L')
{
if(u->left==NULL)u->left=newnode();//如果左边还没有建立
u=u->left;//u往左走
}
else if(direc[i]=='R')
{
if(u->right==NULL)u->right=newnode();//如果右边还没有建立
u=u->right;//u往右走
}
}
if(u->have_value) failed=true;
u->num=value;
u->have_value=true; //做标记
}
注意点:
1.不需要对特殊情况:比如根节点(5,)的后半部分,即direc=”)”,进行特判。
2.
u->have_value=true; //做标记
最后记得做上标记,代表该节点已经赋值完毕。3.
if(u->have_value) failed=true;
重复赋值,全局变量failed置true。
6.bool read_input():输入节点
bool read_input()
{
string s;
failed=false;
root=newnode(); //创建根节点
for(;;)
{
cin>>s;
if(s=="()")break; //结束
int num;
stringstream stream;
string input_num;
int i;
for(i=1;;i++)
{
if(s[i]==',')break;
input_num+=s[i]; //值
}
stream<<input_num;
stream>>num; //stream转为值
stream.clear();
string direstore; //存储方向
for(;i<s.length();i++)
{
direstore+=s[i];
}
addnode(num,direstore);
}
return true;
}
说明:
1.置判断错误的全局bool变量failed为false。
2.创建root节点。
3.输入字符串,利用sstream求得输入的节点值,调用addnode创建新节点。
7.bool bfs():取值
int ans[1005]; //按序存储节点的值
int k=1; //一共有几个节点
bool bfs() //入队函数
{
queue<Node*>q;
memset(ans,0,sizeof(ans));
q.push(root);
while(!q.empty())
{
Node*u=q.front();
q.pop();
if(!u->have_value) return false; //没有值 返回错误
ans[k++]=u->num; //增加到输出数据尾部
if(u->left!=NULL)q.push(u->left); //左节点入列
if(u->right!=NULL)q.push(u->right); //右节点入列
}
return true;
}
利用bfs算法按序取得各节点的值,存放在数组ans中,在主函数输出即可。