//定義二叉樹結點 struct BiTreeNode { int data; BiTreeNode* left; BiTreeNode* right; };
1、遞歸實現post
//先序 void preOrder(BiTreeNode *root){ cout<<root->data; preOrder(root->left); preOder(root->right); } //中序 void inOrder(BiTreeNode *root){ preOrder(root->left); cout<<root->data; preOder(root->right); } //後序 void postOrder(BiTreeNode *root){ preOrder(root->left); preOder(root->right); cout<<root->data; }
以上的cout<<root->data;是對結點的一種操做,這裏能夠對結點作任意想作的操做。spa
2、非遞歸實現指針
//先序 void preOrderS(Node *root) { stack<Node*> s; Node *p=root; while(p!=NULL||!s.empty()) { //沿着左支走到底 //用棧記錄走過的路徑 while(p!=NULL) { cout<<p->data<<" "; s.push(p); p=p->left; } //當左支走到盡頭時,若棧裏邊還有結點 //則退棧,後退到跟結點,而且向右支前進 //此時p!=NULL,會進入以上while循環 if(!s.empty()) { p=s.top(); s.pop(); p=p->right; } } } //注:在 if(!s.empty())中,獲取根結點只是爲了獲得往右支的中轉, //當得到右支指針後,將根結點從棧中彈出,以便返回的時候直接 //回到爺爺結點 //中序 void inOrderS(Node *root){ stack<Node*> s; Node *p=root; while(p!=NULL||!s.empty()){ while(p!=NULL)){ s.push(p); p=p->left; } if(!s.empty()){ p=s.top(); s.pop(); cout<<p->data; p=p->right; } } } //中序遍歷和先序遍歷的代碼幾乎一致,除了訪問點的位置不同 //中序遍歷是在退棧的時候訪問根結點
//後序 void PostOrderS(Node *root) { Node *p = root, *r = NULL; stack<Node*> s; while (p!=NULL || !s.empty()) { if (p!=NULL) {//走到最左邊 s.push(p); p = p->left; } else { p = s.top(); if (p->right!=NULL && p->right != r)//右子樹存在,未被訪問 p = p->right; else { s.pop(); visit(p->val); r = p;//記錄最近訪問過的節點 p = NULL;//節點訪問完後,重置p指針 } }//else }//while } //由於後序非遞歸遍歷二叉樹的順序是先訪問左子樹,再訪問右子樹,最後訪問根節點。當用
//堆棧來存儲節點,必須分清返回根節點時,是從左子樹返回的,還從右子樹返回的。因此,
//使用輔助指針r,其指向最近訪問過的節點。也能夠在節點中增長一個標誌域,記錄是否已被
//訪問