二叉樹的遍歷一般分為三種遍歷方法,即先序遍歷、中序遍歷和後序遍歷。
在中序遍歷中,一個節點的前驅,是其左子樹的最右下角結點,後繼,是其右子樹的最左下角結點。
在後序遍歷中,
• 若結點是根結點,則其後繼為空;
• 若結點是雙親的右子樹,或是左子樹但雙親無右子樹,則其後繼為雙親結點;
• 若結點是雙親的左子樹且雙親有右子樹,則其後繼為右子樹按後序遍歷的第一個結點
二叉樹的遍歷實現如下:
1 #include <stack> 2 #include <queue> 3 4 /* 5 *@struct 6 *@brief 二叉樹結點 7 */ 8 typedef struct binary_tree_node_t 9 { 10 binary_tree_node_t *lchild; /* 左孩子 */ 11 binary_tree_node_t *rchild; /* 右孩子 */ 12 void* data; /* 結點的數據 */ 13 }binary_tree_node_t; 14 15 /** 16 * @brief 先序遍歷,遞歸. 17 * @param[in] root 根結點 18 * @param[in] visit 訪問數據元素的函數指針 19 * @return 無 20 */ 21 void pre_order_r(const binary_tree_node_t *root, int (*visit)(void*)) 22 { 23 if(root != NULL) 24 { 25 (void)visit(root->data); 26 pre_order_r(root->lchild, visit); 27 pre_order_r(root->rchild, visit); 28 } 29 } 30 31 /** 32 * @brief 中序遍歷,遞歸. 33 */ 34 void in_order_r(const binary_tree_node_t *root, int (*visit)(void*)) 35 { 36 if(root != NULL) 37 { 38 pre_order_r(root->lchild, visit); 39 (void)visit(root->data); 40 pre_order_r(root->rchild, visit); 41 } 42 } 43 44 /** 45 * @brief 後序遍歷,遞歸. 46 */ 47 void post_order_r(const binary_tree_node_t *root, int (*visit)(void*)) 48 { 49 if(root != NULL) 50 { 51 pre_order_r(root->lchild, visit); 52 pre_order_r(root->rchild, visit); 53 (void)visit(root->data); 54 } 55 } 56 57 /** 58 * @brief 先序遍歷,非遞歸. 59 */ 60 void pre_order(const binary_tree_node_t *root, int (*visit)(void*)) 61 { 62 const binary_tree_node_t *p; 63 std::stack<const binary_tree_node_t *> s; 64 p = root; 65 if(p != NULL) 66 { 67 s.push(p); 68 } 69 70 while(!s.empty()) 71 { 72 p = s.top(); 73 s.pop(); 74 visit(p->data); 75 if(p->rchild != NULL) 76 { 77 s.push(p->rchild); 78 } 79 if(p->lchild != NULL) 80 { 81 s.push(p->lchild); 82 } 83 } 84 } 85 86 /** 87 * @brief 中序遍歷,非遞歸. 88 */ 89 void in_order(const binary_tree_node_t *root, int (*visit)(void*)) 90 { 91 const binary_tree_node_t *p; 92 std::stack<const binary_tree_node_t *> s; 93 p = root; 94 while(!s.empty() || p!=NULL) 95 { 96 if(p != NULL) 97 { 98 s.push(p); 99 p = p->lchild; 100 } 101 else 102 { 103 p = s.top(); 104 s.pop(); 105 visit(p->data); 106 p = p->rchild; 107 } 108 } 109 } 110 111 /** 112 * @brief 後序遍歷,非遞歸. 113 */ 114 void post_order(const binary_tree_node_t *root, int (*visit)(void*)) 115 { 116 /* p,正在訪問的結點,q,剛剛訪問過的結點 */ 117 const binary_tree_node_t *p, *q; 118 std::stack<const binary_tree_node_t *> s; 119 p = root; 120 do { 121 while(p != NULL) 122 { 123 /* 往左下走 */ 124 s.push(p); 125 p = p->lchild; 126 } 127 q = NULL; 128 while(!s.empty()) 129 { 130 p = s.top(); 131 s.pop(); 132 /* 右孩子不存在或已被訪問,訪問之 */ 133 if(p->rchild == q) 134 { 135 visit(p->data); 136 q = p; /* 保存剛訪問過的結點 */ 137 } 138 else 139 { 140 /* 當前結點不能訪問,需第二次進棧 */ 141 s.push(p); 142 /* 先處理右子樹 */ 143 p = p->rchild; 144 break; 145 } 146 } 147 }while(!s.empty()); 148 } 149 150 /** 151 * @brief 層次遍歷,也即 BFS. 152 * 153 * 跟先序遍歷一模一樣,唯一的不同是棧換成了隊列 154 */ 155 void level_order(const binary_tree_node_t *root, int (*visit)(void*)) 156 { 157 const binary_tree_node_t *p; 158 std::queue<const binary_tree_node_t *> q; 159 p = root; 160 if(p != NULL) 161 { 162 q.push(p); 163 } 164 while(!q.empty()) 165 { 166 p = q.front(); 167 q.pop(); 168 visit(p->data); 169 if(p->lchild != NULL) 170 { 171 /* 先左後右或先右後左無所謂 */ 172 q.push(p->lchild); 173 } 174 if(p->rchild != NULL) 175 { 176 q.push(p->rchild); 177 } 178 } 179 }