二叉树的遍历
二叉树的遍历一般分为三种遍历方法,即先序遍历、中序遍历和后序遍历。
在中序遍历中,一个节点的前驱,是其左子树的最右下角结点,后继,是其右子树的最左下角结点。
在后序遍历中,
• 若结点是根结点,则其后继为空;
• 若结点是双亲的右子树,或是左子树但双亲无右子树,则其后继为双亲结点;
• 若结点是双亲的左子树且双亲有右子树,则其后继为右子树按后序遍历的第一个结点
二叉树的遍历实现如下:
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 }