//定義二叉樹結點 struct BiTreeNode { int data; BiTreeNode* left; BiTreeNode* right; };
一、遞歸實現
//先序 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;是對結點的一種操作,這里可以對結點做任意想做的操作。
二、非遞歸實現
//先序 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,其指向最近訪問過的節點。也可以在節點中增加一個標志域,記錄是否已被
//訪問
