1. 程式人生 > >前序遍歷和中序遍歷唯一確定一顆二叉樹

前序遍歷和中序遍歷唯一確定一顆二叉樹

---恢復內容開始---

問題描述

如果給出了遍歷二叉樹的前序序列和中序序列,則可以構造出唯一的一顆二叉樹。

基本要求

已知一棵二叉樹的前序序列和中序序列,試設計完成下列任務的一個演算法:

(1).構造一顆二叉樹

(2).證明構造正確(即分撥兒以前序和中序遍歷該樹,將得到的結果

與給出的序列進行比較)

(3).對該二叉樹進行後序遍歷,輸出後序遍歷序列

(4).用凹入法輸出該二叉樹

測試資料

前序序列為ABDEGCFHIJ,中序序列為DBGEAHFIJC                                                                             

 

程式碼思路

1.確定樹的根節點,樹根是當前樹中所有元素在前序遍歷中最先出現的元素。

2.求解樹的子樹,找出根節點在中序遍歷中的位置,根左邊的所有元素就是左子樹,根右邊的所有元素就是右子樹。若根節點左邊或右邊為空,則該方向子樹為空;若根節點左邊和右邊都為空,則根節點已經為葉子節點。

3.遞迴求解樹,將左子樹和右子樹分別看成一棵二叉樹,重複1、2、3步,直到所有的節點完成定位。

 

原始碼

/*
1.確定樹的根節點,樹根是當前樹中所有元素在前序遍歷中最先出現的元素。
2.求解樹的子樹,找出根節點在中序遍歷中的位置,根左邊的所有元素就是左子樹,根右邊的所有元素就是右子樹。若根節點左邊或右邊為空,則該方向子樹為空;若根節點左邊和右邊都為空,則根節點已經為葉子節點。
3.遞迴求解樹,將左子樹和右子樹分別看成一棵二叉樹,重複1、2、3步,直到所有的節點完成定位。
*/ #include<iostream> #include<algorithm> #include<string> #include<cstring> using namespace std; const int maxint = 10000; char ch1[maxint], ch2[maxint]; //前序序列,中序序列 int length; //二叉樹結點的個數 struct tree { char name; struct tree *leftchild; struct tree *rightchild; }; //訪問函式
void vis(char name) { cout << name; } //初始化 void init(struct tree **root){ *root = (struct tree *)malloc(sizeof(struct tree)); (*root)->leftchild = NULL; (*root)->rightchild = NULL; } //建立左子樹 struct tree *build_ltree(struct tree *h,char name) { struct tree *p, *t; if (h == NULL) return NULL; t = h->leftchild; p= (struct tree*)malloc(sizeof(struct tree)); p->name = name; p->leftchild = t; p->rightchild = NULL; h->leftchild = p; return h->leftchild; } //建立右子樹 struct tree *build_rtree(struct tree *h, char name) { struct tree *p, *t; if (h == NULL) return NULL; t = h->rightchild; p = (struct tree*)malloc(sizeof(struct tree)); p->name = name; p->leftchild = NULL; p->rightchild = t; h->rightchild = p; return h->rightchild; } //凹入法列印二叉樹 void print_tree(struct tree *t, int n) { if (t == NULL) return; print_tree(t->rightchild, n + 1); for (int i = 0; i < n - 1; i++) cout << " "; if (n > 0) { cout<<"***"; cout << t->name << endl; } print_tree(t->leftchild, n + 1); } //前序遍歷 void preorder(struct tree *t, void vis(char name)) { if (t != NULL) { vis(t->name); preorder(t->leftchild, vis); preorder(t->rightchild, vis); } } //中序遍歷 void inorder(struct tree *t, void vis(char name)) { if (t != NULL) { inorder(t->leftchild, vis); vis(t->name); inorder(t->rightchild, vis); } } //後序遍歷 void postorder(struct tree *t, void vis(char name)) { if (t != NULL) { postorder(t->leftchild, vis); postorder(t->rightchild, vis); vis(t->name); } } //尋找對應中序序列中和前序序列相對應的結點的位置 int bfs(char ch[],char name) { int i(0); while (ch[i] != name) ++i; return i; } //找到左子樹的位置 int seek_left(int flag[], int t){ int temp; temp = t; while (flag[temp] != 1 && temp >= 0) temp--; if (flag[temp] == 1) return temp; else return -1; } //找到右子樹的位置 int seek_right(int flag[], int t) { int temp; temp = t; while (flag[temp] != 1 && temp <= 10000) temp++; if (flag[temp] == 1) return temp; else return -1; } int main() { while (1) { cout << " ***************唯一確定一顆二叉樹***************" << endl; cout << " * *" << endl; cout << " * 給定前序序列和中序序列唯一確定一顆二叉樹 *" << endl; cout << " * *" << endl; cout << " ************************************************" << endl; struct tree *root; //定義根節點 init(&root); //建立根節點 struct tree *node_tree[maxint]; //二叉樹中的結點 int flag[maxint]; //標記陣列 int left, right; memset(flag, 0, sizeof flag); //標記陣列全部賦值為0 cout << "請輸入前序序列:"; cin >> ch1; cout << "請輸入中序序列:"; cin >> ch2; length = strlen(ch1); char node; //前序序列中的結點 int num; //中序序列中對應前序序列結點的位置 for (int i = 0; i < length; ++i) { node = ch1[i]; num = bfs(ch2, node); left = seek_left(flag, num); //找到左子樹位置 right = seek_right(flag, num); //找到右子樹位置 if (left == -1 && right == -1) { //第一次的時候肯定會執行這個條件後面的語句 node_tree[num] = build_ltree(root, node); flag[num] = 1; } else if (left != -1 && node_tree[left]->rightchild == NULL) { node_tree[num] = build_rtree(node_tree[left], node); flag[num] = 1; } else if (right != -1 && node_tree[right]->leftchild == NULL) { node_tree[num] = build_ltree(node_tree[right], node); flag[num] = 1; } } cout << "此二叉樹的結構是:" << endl << endl; print_tree(root, 0); cout << "此二叉樹的前序序列為:"; preorder(root->leftchild, vis); cout << endl; cout << "此二叉樹的中序序列為:"; inorder(root->leftchild, vis); cout << endl; cout << "此二叉樹的後序序列為:"; postorder(root->leftchild, vis); cout << endl << endl << endl; } return 0; }

 

效果圖

 

總結

斷更一個月後,重新寫博。呃呃呃呃呃,最近狀態慢慢的調整過來了,加油吧!

下週去訓練!!!

---恢復內容結束---