天天看點

二叉樹的前序、中序、後序周遊與建立

#include <iostream>

#include <string>

#include <stack>

using namespace std;

struct node;

typedef node *pNode;

struct node {

     char data;

     pNode left, right;

};

string line;

string::iterator it;

// 前序擴充序列建立二叉樹  

void plant(pNode &root)

{

     if (it == line.end())

         return;

     char data = *it++;

     if (data == '/')

         root = NULL;

     else {

         root = new node();

         root->data = data;

         plant(root->left);

         plant(root->right);

     }

}

// 先序周遊  

void pre_order(pNode root)

     stack<pNode> s;

     while (root != NULL || !s.empty())

     {

         if (root != NULL) {

             cout << root->data << " ";

             s.push(root);

             root = root->left;

         } else {

             root = s.top();

             s.pop();

             root = root->right;

         }

// 中序周遊  

void in_order(pNode root)

// 壓棧的參數類型,包括局部變量和行号  

struct stack_arg {

     stack_arg(pNode _root, int _line)

     : root(_root), line(_line) { }

     pNode root;

     int line;

// 後序周遊  

void post_order(pNode root)

     stack<stack_arg> s;

     s.push(stack_arg(root, 1));

     while (!s.empty())

         switch (s.top().line) {

         case 1:

             if (s.top().root == NULL)

                 s.pop();

             else

                 s.top().line = 2;

             break;

         case 2:

             s.top().line = 3;  

             s.push(stack_arg(s.top().root->left, 1));

         case 3:

             s.top().line = 4;

             s.push(stack_arg(s.top().root->right, 1));

         case 4:

             cout << s.top().root->data << " ";

int main()

     cin >> line;

     it = line.begin();

     pNode root = NULL;

     plant(root);

     cout << "先序周遊" << endl;  

     pre_order(root);

     cout << endl;

     cout << "中序周遊" << endl;  

     in_order(root);

     cout << "後序周遊" << endl;  

     post_order(root);

     system("pause");

     return 0;

/*

input

     ABDI//J//EK//LQ///CFM//N//GO//P//

output

     先序周遊:

     A B D I J E K L Q C F M N G O P

     中序周遊

     I D J B K E Q L A M F N C O G P

     後序周遊  

     I J D K Q L E B M N F O P G C A

//////////////////////////////////////////////////////////////////////

知樹的前序周遊,後序周遊,怎麼求中序周遊?

通過對同一棵二叉樹三種周遊方式的分析,概括出由前序、中序或由中序、後序周遊結果快速還原二叉樹的方法。 

二叉樹是最為常用的資料結構,它的實際應用非常廣泛。二叉樹的周遊方式有三種,前序周遊、中序周遊、後序周遊。先序周遊的順序為:NLR,即先根結點,然後左子樹、右子樹;中序周遊順序為:LNR先左子樹,然後根結點、右子樹;後序周遊順序為:LRN先左子樹、然後右子樹、根結點。由前序和中序周遊、由中序和後序周遊序列可以唯一确定一棵二叉樹,而由前序和後序周遊序列不能唯一确定一棵二叉樹。 

  二叉排序樹對二叉樹作了進一步的限定:根結點的權值大于(或小于)左子樹中所有結點的權值;根結點的權值小于(或大于)其右子樹中所有結點的權值。 

  那麼如何根據三種周遊序列之間的關系及二叉排序樹來快速還原一棵二叉樹?下面以二叉樹的前序和中序周遊序列為基礎,利用二叉排序樹的性質,給出快速還原二叉樹的方法。 

  1由給定前序和中序序列或中序和後序序列還原二叉樹的方法 

  例:前序序列:ABDECFGH 中序序列:DEBACGFH (後序序列:EDBGHFCA) 

  (1)給中序序列中的每個結點從小到大、從左到右賦以權值,如下: 

  D(1)E(2)B(3)A(4)C(5)G(6)F(7)H(8) 

  (2)還原時讀入的序列為前序序列,從左到右依次讀入序列中的各個結點值和相應的權值;  

  (3)由讀入的序列,根據第1)步中給定的權值按照二叉排序樹的構造規則構造二叉排序樹。第一個讀入的結點為根結點,其他結點分别為左右子樹中的結點。設根結點為TT,權值為NN,目前讀入結點為SS,權值為MM,若MM

  (4)将SS插入到TT的左子樹或右子樹的過程中,仍然遵循3)中的規則,直至左子樹或右子樹為空時止。 

  (5)讀入序列結束時,二叉樹還原成功。 

6)對于由中序序列和後序序列還原二叉樹是,讀入的序列為後序序列,從右向左讀入,構造規則同上。還原結果與上述結果完全一緻。

2還原方法的确定依據 

  二叉樹周遊過程中,在中序序列中,根結點的左子樹中的所有結點都在根結點的左側,根結點的右子樹中的所有結點都在根結點的右側,這個特點恰好與二叉排序樹具有相同的性質;在讀入序列時,前序序列則從左向右讀,這恰好與周遊二叉樹的順序相同;後序序列從右向左讀,則按照根結點、右子樹、左子樹的順序還原。 

  (1)設二叉樹共有N個結點(N為大于1的正整數),我們按照還原方法給中序序列中的這N個結點分别賦予權值1,2…N,設根結點的權值為M(1

  (2)由二叉樹的周遊規則可知,權值為1,2…M-1的結點為根結點的左子樹中的結點,而權值為M+1,…N的結點為根結點的右子樹中的結點。 

  (3)将這N個結點劃分成3個子集AA=(1,2…M-1)BB=(M)CC=(M+1,…N),由于前序序列第一個讀入的結點必定為二叉根的根結點,是以BB為根結點,AA集為左子樹,CC集為右子樹。 

  (4)同理不斷讀入前序序列中的結點,依次遞歸還原BB對應的左子樹和CC對應的右子樹,最後将三棵子樹合并成以BB為根結點、AA的根結點為BB的左子樹、CC的根結點為BB的右子樹的一棵二叉排序樹。 

  (5)同理可以得出,由中序序列和後序序還原二叉樹的規則也成立。 

  (6)在還原過程中,讀入序列的順序也遵循也先根結點,後子樹的規律。 

  3總結 

  在二叉樹的一些應用中,如平衡二叉樹、紅黑樹等,常常要觀察二叉樹的形态,對其進行判斷并調整。根據周遊序列和二叉排序樹的性質快速還原出二叉樹對于研究相關的問題有很大的幫助。

上面可以得出前序擴充序列 ABD/E///C//FG//H

<a href="http://images.cnblogs.com/cnblogs_com/tuzhiye/WindowsLiveWriter/9c37fd6f138f_1A29/image_5.png"></a>

後序為 ED##B###G##HFCA

void PreCreate(Node* p)

if(line == end)    return;

  if(line == “/”)

      p = NULL;

else{

   p = new NOde();

   p-&gt;data = line;

   PreCreate(p-&gt;Left);

    PreCreate(p-&gt;Right);