<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    tbwshc

    二叉樹三種非遞歸遍歷的區別

    1 #include <iostream>
      2
      3 #define MAXN  100
      4 using namespace stbd;
      5
      6
      7 struct BTNode
      8 {
      9     char tag;
    10     BTNode *left;
    11     BTNode *right;
    12 };
    13
    14 class BTree
    15 {
    16 private:
    17     BTNode **root;
    18     void BuildBTree(BTNode **root);
    19
    20 public:
    21     /*遞歸版本*/
    22     void PreVisit(BTNode *root);
    23     void InVisit(BTNode *root);
    24     void PostVisit(BTNode *root);
    25
    26     /*非遞歸版本*/
    27     void NR_PreVisit(BTNode *root);
    28     void NR_InVisit(BTNode *root);
    29     void NR_PostVisit(BTNode *root);
    30
    31     BTree(BTNode **r);
    32     BTree();
    33 };
    34
    35 BTree::BTree()
    36 {
    37
    38 }
    39
    40 BTree::BTree(BTNode **r)
    41 {
    42     root = r;
    43     /*
    44 *root = new BTNode; 45     (*root)->left = NULL;
    46 (*root)->right = NULL; 47     */
    48     BuildBTree(root);
    49 }
    50
    51 /*先序方式插入結點*/
    52 void BTree::BuildBTree(BTNode **root)
    53 {
    54     char c;
    55    
    56     c = getchar();
    57     if(c == '#')
    58         *root=NULL;
    59     else{
    60         *root = new BTNode;
    61         (*root)->tag = c;
    62         BuildBTree(&(*root)->left);
    63         BuildBTree(&(*root)->right);
    64     }
    65 }
    66
    67 void BTree::PreVisit(BTNode *root)
    68 {
    69     if(root!=NULL)
    70     {
    71         printf("%c ", root->tag );
    72         PreVisit(root->left);
    73         PreVisit(root->right);
    74     }
    75 }
    76
    77 void BTree::InVisit(BTNode *root)
    78 {
    79     if(root!=NULL)
    80     {
    81         InVisit(root->left);
    82         printf("%c ", root->tag );
    83         InVisit(root->right);
    84     }
    85 }
    86
    87 void BTree::PostVisit(BTNode *root)
    88 {
    89     if(root!=NULL)
    90     {
    91         PostVisit(root->left);
    92         PostVisit(root->right);
    93         printf("%c ", root->tag );
    94     }
    95 }
    96
    97 void BTree::NR_PreVisit(BTNode *root)
    98 {
    99     BTNode *s[MAXN];
    100     int top=0;
    101
    102     while(top!=0 || root!=NULL)
    103     {
    104         while(root!=NULL)
    105         {
    106             s[top] = root;
    107             printf("%c ", s[top++]->tag);
    108             root = root->left;
    109         }
    110         if(top>0)
    111         {
    112             root = s[--top];
    113             root = root->right;
    114         }
    115     }
    116 }
    117
    118 void BTree::NR_InVisit(BTNode *root)
    119 {
    120     BTNode *s[MAXN];
    121     int top=0;
    122    
    123     while(top!=0 || root!=NULL)
    124     {
    125         while(root!=NULL)
    126         {
    127             s[top++]=root;
    128             root = root->left;
    129         }
    130         if(top>0)
    131         {
    132             root = s[--top];
    133             printf("%c ", root->tag);
    134             root = root->right;
    135         }
    136     }
    137 }
    138
    139 void BTree::NR_PostVisit(BTNode *root)
    140 {
    141     BTNode *s[MAXN], *tmp=NULL;
    142     int top=0;
    143
    144     while(top!=0 || root!=NULL)
    145     {
    146         while(root!=NULL)
    147         {
    148             s[top++]=root;
    149             root=root->left;
    150         }
    151         if(top>0)
    152         {
    153             root = s[--top];
    154
    155             /*右孩子不存在或者已經訪問過,root出棧并訪問*/
    156             if( (root->right == NULL) || (root->right == tmp) ) 
    157             {
    158                 printf("%c ", root->tag);
    159                 tmp = root;        //保存root指針
    160                 root=NULL;         //當前指針置空,防止再次入棧
    161             }
    162
    163             /*不出棧,繼續訪問右孩子*/
    164             else
    165             {
    166                 top++;             //與root=s[--top]保持平衡
    167                 root = root->right;
    168             }
    169         }
    170     }
    171 }
    172
    173 int main()
    174 {
    175     BTNode *root=NULL;
    176     BTree bt(&root);  //頭指針的地址
    177    
    178     bt.NR_PreVisit(root);
    179     printf("\n");
    180     bt.NR_InVisit(root);
    181     printf("\n");
    182     bt.NR_PostVisit(root);
    183     printf("\n");
    184     return 0;
    185 }
    復制代碼

    先上代碼,tb帶NR(Non-recursive)的表示非遞歸遍歷。

     

    測試數據:

    124#8##5##369###7##

     

    表示的二叉樹:

    用windows自帶的畫圖畫的,的確是粗糙了點。。。

     

    測試結果:

    1 2 4 8 5 3 6 9 7
    4 8 2 5 1 9 6 3 7
    8 4 5 2 9 6 7 3 1

     

     

    一、關于二叉樹的建立

     

      首先要注意二叉樹的創建過程,這里用的是先序方式遞歸插入結點,所以輸入數據的時候,必須按照先序方式輸入,

    左結點或右結點為空的,用#表示。否則,輸入不會有響應,因為遞歸過程還未結束,按CTRL+Z也沒用。當然可以用其

    他方式插入(如中序遞歸插入,后序遞歸插入等)。

     

    二、三種非遞歸遍歷的區別

     

      前序、中序和后序的遞歸遍歷方式比較簡單,這里就不講了。而非遞歸的遍歷方式,只需要用數組存儲結點指針,模擬系統棧的工作機制就可以了。

    先說先序非遞歸遍歷,按照根-左-右的方式訪問的話,需要將當前結點壓棧(同時打印當前結點信息),直到左子樹為空(內層while);然后出棧,訪問

    右結點;后面的操作就跟前面的一樣了(外層while)。

      對于中序非遞歸遍歷,可以看到代碼結構幾乎一模一樣,只是打印結點信息的位置不同而已。這是因為中序遍歷是左-根-右,這樣前序和中序非

    遞歸遍歷(根-左和左-根都是壓棧動作,且出棧動作的對象都是父節點)是一致的。

     

      對于后序非遞歸遍歷,因為后序遍歷是左-右-根,根的訪問是在右孩子之后,而這意味著兩種情況:

      1、右孩子不為空(繼續訪問右孩子);

      2、右孩子為空,從左孩子返回,則需要訪問根結點。

      為了區分這兩種情況(物理形式上從左孩子返回,還是從右孩子返回來訪問根節點),對于右孩子的訪問又需要判斷根結點的右孩子是否為空或者已

    訪問過(右子樹已遍歷過)。除這兩種情況外,都不應該訪問根節點,而是要繼續進入右子樹。

      

    三、補充說明

     

      在后序非遞歸遍歷的else語句中top++純粹是為了使棧保持平衡,因為對于2)繼續訪問右孩子這種情況,不需要出棧,而前面的root[--top]包含

    出棧操作,以此保證棧的正確性(當然可以有其他的處理,這里也是考慮到三種非遞歸遍歷方式的統一性)。

      兩個while不會提高程序的時間復雜度,因為二叉樹的結點個數是固定的,內層while是為了提高算法的邏輯性。

     

    四、遞歸->非遞歸

     

      另外,今天實習看到一個老師寫的非遞歸代碼,非常棒,贊一個!他僅僅是將程序的返回地址和函數的形參、局部變量都保存起來,然后在退出時

    還原現場;同樣是非遞歸,但是這種方式更接近編譯器的處理方式,同操作系統的任務切換也比較一致;所以這種處理方法為遞歸自動轉換為非遞歸奠

    定了基礎。

      分享一下他當場編寫的非遞歸的漢諾塔:

     

    復制代碼
      1 #include <stdio.h>
      2 #include <iostream>
      3 
      4 using namespace std ;
      5 
      6 #define  MAXSIZE  1000 
      7 
      8 struct SNode
      9 {
     10     int  n;
     11     char from ;
     12     char to;
     13     char aux ;
     14     int  label ;
     15 } ;
     16 
     17 struct STK
     18 {
     19     
     20     SNode  stack[MAXSIZE] ;
     21     int sp  ;
     22     STK()
     23     {
     24         sp = 0 ;
     25     };
     26     void push (int n,char from,char to,char aux, int label )
     27     {
     28         if ( sp>= MAXSIZE )
     29         {
     30             printf ( "STK is full!\n" ) ;
     31         }
     32         stack[sp].n = n ;
     33         stack[sp].from = from ;
     34         stack[sp].to = to ;
     35         stack[sp].aux = aux ;
     36         stack[sp++].label = label ;
     37     };
     38     SNode POP()
     39     {
     40         if ( sp <=0 )
     41         {
     42             printf ( "STK is empty!\n" ) ;
     43         }
     44         return stack[--sp] ;
     45     };
     46 } ;
     47 
     48 void move(int n,char from,char to,char aux)
     49 {
     50     if(n==1)
     51     {
     52         cout<<"將#1盤從"<<from<<"移到"<<to<<endl;
     53 }
     54     else
     55     {
     56          move(n-1,from,aux,to);
     57          cout<<"將#"<<n<<"盤從"<<from<<"移到"<<to<<endl;
     58          move(n-1,aux,to,from);
     59 }
     60 }
     61 
     62 
     63 void move_stk(int n,char from,char to,char aux)
     64 {
     65     STK stk ;
     66     char tmp;
     67 S1:
     68     if(n==1)
     69     {
     70         cout<<"將#1盤從"<<from<<"移到"<<to<<endl;
     71     }
     72     else
     73    {
     74     stk.push (n,from,to,aux,2 ) ;
     75     n = n-1 ;
     76     tmp = to ;
     77     to = aux ;  
     78     aux = tmp ;
     79     goto S1;
     80          // move(n-1,from,aux,to);
     81 S2:
     82          cout<<"將#"<<n<<"盤從"<<from<<"移到"<<to<<endl;
     83 
     84     stk.push (n,from,to,aux,3 ) ;
     85     n = n-1 ;
     86     tmp = from ;
     87     from = aux ;  
     88     aux = tmp ;
     89     goto S1;
     90          // move(n-1,aux,to,from);
     91 }
     92 S3:
     93     if ( stk.sp > 0 )
     94     {
     95         SNode sn = stk.POP() ;
     96         n = sn.n ;
     97         from = sn.from;
     98         to = sn.to ;
     99         aux = sn.aux ;
    100         if  ( 1 == sn.label  )
    101             goto S1;
    102         else if ( 2 == sn.label )
    103             goto S2;
    104         else 
    105             goto S3;        
    106     }
    107 }
    108 
    109 
    110 
    111 int main(int argc, char * argv[])
    112 {
    113     move ( 3,'A','B', 'C' );
    114     printf ( "================================\n" ) ;
    115     move_stk ( 3,'A','B', 'C' );
    116 
    117     return 0;
    118 }

    posted on 2012-07-06 15:45 chen11-1 閱讀(2097) 評論(0)  編輯  收藏


    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 中文字幕不卡高清免费| 久久精品国产亚洲av品善| 免费播放在线日本感人片| 精品国产香蕉伊思人在线在线亚洲一区二区 | 亚洲AV无码1区2区久久| 成全视频免费观看在线看| 国产亚洲免费的视频看| 全免费a级毛片免费看| 亚洲AV无码乱码在线观看富二代| 亚洲精品无码少妇30P| 日韩精品免费电影| 丰满亚洲大尺度无码无码专线 | 成年女人午夜毛片免费看| 最新亚洲精品国偷自产在线| 永久免费av无码入口国语片| 精品亚洲综合在线第一区| 久久国产精品免费看| 亚洲一区二区三区在线| 午夜毛片不卡免费观看视频| 免费人成视频在线播放| 国产成人亚洲综合无码精品| 在线免费观看亚洲| 亚洲天堂男人影院| 亚洲国产精品国产自在在线| 美女视频黄免费亚洲| 免费看国产一级特黄aa大片| 国产一级高青免费| 亚洲精品国产福利在线观看| 免费黄色一级毛片| 国产午夜亚洲精品| 免费少妇a级毛片| 免费在线看黄网站| 亚洲日韩精品无码AV海量| 伊人久久精品亚洲午夜| 曰批视频免费40分钟试看天天| 亚洲一日韩欧美中文字幕在线| 亚洲高清无码综合性爱视频| 男人的天堂网免费网站| 亚洲色大成网站www永久网站| 亚洲真人日本在线| 国内精品乱码卡1卡2卡3免费|