二叉树的遍历 (递归和非递归实现)
二叉樹的遍歷 (遞歸實現)
用C++實現二叉樹的“先根遍歷”存儲。
用C++實現二叉樹的“先根遍歷”、“中根遍歷”、“后根遍歷”分別輸出二叉樹中結點的數據。
#include <iostream> using namespace std ;struct BiNode {char data ;BiNode *lchild , *rchild ; } ; BiNode *BiTree ;int NodeID ;BiNode *CreateBiTree (char *c , int n) {BiNode *T ;NodeID ++ ;if (NodeID > n){return (NULL) ;}if (c[NodeID] == '0'){return (NULL) ;}T = new BiNode ;T -> data = c[NodeID] ;T -> lchild = CreateBiTree (c , n) ;T -> rchild = CreateBiTree (c , n) ;return (T) ; }void PreOrderTraverse (BiNode *T) {if (T){cout << T -> data << " ";PreOrderTraverse (T -> lchild) ;PreOrderTraverse (T -> rchild) ;} }void InOrderTraverse (BiNode *T) {if (T){InOrderTraverse (T -> lchild) ;cout << T -> data << " ";InOrderTraverse (T -> rchild) ;} }void PostOrderTraverse (BiNode *T) {if (T){PostOrderTraverse (T -> lchild) ;PostOrderTraverse (T -> rchild) ;cout << T -> data << " ";} }int main () {int i , SampleNum ;char c[100] ;cin >> SampleNum ;for (i = 1 ; i <= SampleNum ; i ++){cin >> c[i] ;}NodeID = 0 ;BiTree = CreateBiTree (c , SampleNum) ;PreOrderTraverse (BiTree) ;cout << endl ;InOrderTraverse (BiTree) ;cout << endl ;PostOrderTraverse (BiTree) ;return 0 ; }C++實現的非遞歸版本代碼
struct BinaryTreeNode {int val;BinaryTreeNode* leftchild;BinaryTreeNode* rightchild;BinaryTreeNode(int const& _val, BinaryTreeNode* _leftchild=NULL, BinaryTreeNode* _rightchild=NULL) :val(_val), leftchild(_leftchild), rightchild(_rightchild) {}};??三種遍歷方式? 訪問節點的順序是一致的,不同之處在于,有的遍歷流程把訪問到的節點暫存起來,達成某種條件后再將節點輸出。約定, 根節點V, 其左孩子為L, 右孩子為R, 那么遍歷順序可以記為:
Pre-Order Traversal : 到達一個節點后,即刻輸出該節點的值,并繼續遍歷其左右子樹。? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??VLR
In-Order Traversal? :? ?到達一個節點后,將其暫存,遍歷完左子樹后,再輸出該節點的值,然后遍歷右子樹。LVR
Post-Order Traversal:? ?到達一個節點后,將其暫存,遍歷完左右子樹后,再輸出該節點的值。? ? ? ? ? ? ? ? ? ? ? ? ??LRV
?
? ? ? ? ? ? ? ? ? ? ??? ? ? ? ? ? ? ? ? ??
? ? ? ? ? Pre-Order Traversal? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? In-Order Traversal? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Post-Order Traversal
?
先序遍歷
? ? ? ?
? ? ? ? ? ? ? ? ? ? ? ? ???? ? ?
?先序遍歷與中序、后序遍歷都使用了棧結構來暫存節點
void pre_traversal(BinaryTreeNode* root) {std::stack<BinaryTreeNode*> node_stack; //用來暫存節點的棧while (root != nullptr || !node_stack.empty()) {if (root != nullptr) { //若當前的節點非空std::cout << root->val << " "; //則輸出該節點的值node_stack.push(root); //該節點壓入棧中root = root->leftchild; //繼續向左子樹前進}else {root = node_stack.top(); //取棧頂節點root = root->rightchild; //繼續向右子樹前進node_stack.pop(); //刪除棧頂節點}}}中序遍歷
與先序遍歷類似,唯一區別是到達當前節點時? 并不直接輸出該節點。
void in_traversal(BinaryTreeNode* root) {std::stack<BinaryTreeNode*> stack_node;while (root != nullptr || !stack_node.empty()) {if (root != nullptr) {stack_node.push(root); //節點入棧root = root->leftchild; //繼續訪問左子樹直到底}else {root = stack_node.top(); //取棧頂節點std::cout << root->val << " "; //訪問節點數據root = root->rightchild; //繼續向右子樹前進stack_node.pop(); //刪除棧頂}} }后序遍歷
? ? ?與先序、中序遍歷有所不同,后序遍歷在決定是否可以輸出當前節點的值的時候,需要考慮其左右子樹是否都已經遍歷完成。
? ? ?因此我們需要設置一個lastvisit游標。若lastvisit等于當前考查節點的右子樹,表示該節點的左右子樹都已經遍歷完成,則可以輸出當前節點(否則,繼續向右子樹進發)。并把lastvisit節點設置成當前節點,將當前游標節點root設置為空,下一輪就可以訪問棧頂元素。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
void post_traversal(BinaryTreeNode* root) {std::stack<BinaryTreeNode*> stack_node;BinaryTreeNode* lastvisit = root;while (root != nullptr || !stack_node.empty()) {if (root != nullptr) {stack_node.push(root);root = root->leftchild;}else {root = stack_node.top();if (root->rightchild == nullptr || root->rightchild == lastvisit) {std::cout << root->val << " ";stack_node.pop();lastvisit = root;root = nullptr;}else {root = root->rightchild;}}}}下面是測試用的代碼:
int main(int argc, char* argv[]) {BinaryTreeNode* A = new BinaryTreeNode(1);BinaryTreeNode* B = new BinaryTreeNode(2);BinaryTreeNode* C = new BinaryTreeNode(4);BinaryTreeNode* D = new BinaryTreeNode(7);BinaryTreeNode* E = new BinaryTreeNode(3);BinaryTreeNode* F = new BinaryTreeNode(5);BinaryTreeNode* G = new BinaryTreeNode(6);BinaryTreeNode* H = new BinaryTreeNode(8);A->leftchild = B;A->rightchild = E;B->leftchild = C;C->rightchild = D;E->leftchild = F;E->rightchild = G;G->leftchild = H;std::cout << "Pre order traversal:" << std::endl;pre_traversal(A);std::cout << std::endl<< "In order traversal:" << std::endl;in_traversal(A);std::cout << std::endl << "Post order traversal:" << std::endl;post_traversal(A);return 0; }?
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的二叉树的遍历 (递归和非递归实现)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 圆环回原点问题
- 下一篇: 二叉树的最长的路径长度最大路径和