您的位置:首页 > 职场人生

【2013微软面试题】输出节点数为n的二叉树的所有形态

2013-10-28 01:33 274 查看
转自:http://blog.csdn.net/monsterxd/article/details/8449005

/*
* 题意,求节点数为n的二叉树的所有形态,先要想个方式来唯一标示一棵二叉树
*
* 方法一:一个前序+一个中序,可以还原一棵唯一的二叉树,故使用【前序输出的字符串+中序输出的字符串】
* 来唯一标示一棵二叉树。
*
* 方法二:【将一颗二叉树逐层遍历,若节点不为空,则记为X,为空记为O,最终得到的序列可以唯一标示一颗二叉树。】
*
* 建树过程采用递归,对已经建成的树的部分,每次节点逐一判断其左右儿子是否可以插入,可以的话,则插入,然后递归。
* 直到数的大小达到n,则记录这棵树的唯一标示,然后返回!
*
* output: 例如输入3,
* 则输出结果,对应的二叉树如下所示:
* X X X X X
* X O X O O X O X X X
* X O O X X O O X O O O O
* O O O O O O O O
*/

代码如下所示:

#include <iostream>
#include <string>
#include <map>
#include <vector>
using namespace std;

int n;   //二叉树有n个节点
map<string, int> m;

struct Node{
Node * left;
Node * right;
};

void PreOut(Node * head, string &s)  //先序输出,根左右
{
s += "X";       //根
if(head->left != NULL)   //左
PreOut(head->left, s);
else
s += "O";
if(head->right != NULL)  //右
PreOut(head->right, s);
else
s += "O";
}

void MidOut(Node * head, string &s)  //中序输出,左根右
{
if(head->left != NULL)   //左
MidOut(head->left, s);
else
s += "O";
s += "X";
if(head->right != NULL)  //右
MidOut(head->right, s);
else
s += "O";

}

//逐层遍历二叉树
void Bfs(Node * head, string &s)
{
vector<Node *> vec;
vec.push_back(head);
for(int i=0; i<vec.size(); i++)
{
if(vec[i] != NULL)
{
s += "X";
vec.push_back(vec[i]->left);  //左儿子入队,为NULL的时候也入队
vec.push_back(vec[i]->right); //右儿子入队
}
else
s += "O";
}
}

/*
* head: 为整棵树的根节点
* arr:  为二叉树节点的数组
* now:  为当前已经建立的树的节点数
* total:为输入n,总共的节点数
* 建树时间复杂度: 卡特兰数复杂度  C(2*n,n)/(n+1)
*/
void BuildAllKindsTree(Node * head, Node * arr, int now, int total)
{
if(now == total)  //成功建立一棵树
{
string s = "";
//PreOut(head, s);
//MidOut(head, s);
Bfs(head, s);
m[s]++;
return;
}

for(int i=0; i<now; ++i) //当前建立的树已经有 now 个节点
{
if( arr[total - 1 - i].left == NULL ) //该节点左儿子位置可以链接个节点
{
arr[total - 1 - i].left = &arr[total - 1 - now];
BuildAllKindsTree(head, arr, now+1, total);
arr[total - 1 - i].left = NULL;  //递归回溯
}
if( arr[total - 1 - i].right == NULL)  //该节点右儿子位置可以链接个节点
{
arr[total - 1 - i].right = &arr[total - 1 - now];
BuildAllKindsTree(head, arr, now+1, total);
arr[total - 1 - i].right = NULL;
}
}
}

void output()
{
cout<<"*****************************************************************"<<endl;
map<string, int>::iterator iter = m.begin();
for(; iter != m.end(); iter++)
cout<<iter->first<<endl;
cout<<n<<"个节点的时候,二叉树总共有"<<m.size()<<"种情况。"<<endl;
cout<<"*****************************************************************"<<endl;
}

int main()
{
while(cin>>n)
{
m.clear();
Node * a = new Node
;  //new出n个节点
for(int i=0; i<n; i++)
{
a[i].left = NULL;
a[i].right = NULL;
}

BuildAllKindsTree(&a[n-1], a, 1, n);

output();
delete []a;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐