【2013微軟校招面試題】輸出節點數為n的二叉樹的所有形態
阿新 • • 發佈:2019-01-04
/*
* 題意,求節點數為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[n]; //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; } }