最近整理原來的一些代碼,腦子有點不好使,還是記下來吧。
//binary_tree.h,遍曆包含了遞迴和非遞迴兩種,層次遍曆
#ifndef _BINARY_TREE_H_#define _BINARY_TREE_H_template<class T> struct BiNode{T data;BiNode<T>* lchild, *rchild;};template<class T>class BiTree{public:BiTree();~BiTree();BiNode<T>* GetRoot();void PreOrder(BiNode<T>* node);void InOrder(BiNode<T>* node);void PostOrder(BiNode<T>* node);//非遞迴實現void PreOrderNonRec(BiNode<T>* node);void InOrderNonRec(BiNode<T>* node);void PostOrderNonRec(BiNode<T>* node);void LevelOrder(BiNode<T>* node);//層次遍曆protected:private:BiNode<T>* m_root;BiNode<T>* Create();void Release(BiNode<T>* root);};#endif
//bianry_tree.cpp
#include <iostream>#include <stack>#include <queue>using namespace std;template<class T>BiNode<T>* BiTree<T>::GetRoot(){return m_root;}template<class T>BiTree<T>::BiTree(){m_root = new BiNode<T>;m_root = Create();}template<class T>BiTree<T>::~BiTree(){Release(m_root);}template<class T>BiNode<T>* BiTree<T>::Create(){char ch;cin>>ch;BiNode<T>* pnode;if (ch == '#') pnode = NULL;else{pnode = new BiNode<T>;pnode->data = ch;pnode->lchild = Create();pnode->rchild = Create();}return pnode;}template<class T>void BiTree<T>::Release( BiNode<T>* root ){if(root != NULL){Release(root->lchild);Release(root->rchild);}}template<class T>void BiTree<T>::PreOrder(BiNode<T>* node){//TLR的第一個一定是樹根if(node == NULL)return;else{cout<<node->data<<" ";PreOrder(node->lchild);PreOrder(node->rchild);}}template<class T>void BiTree<T>::InOrder(BiNode<T>* node){//由前序走訪和中序遍曆可以確定唯一二叉樹//後序遍曆和中序遍曆也可以//但是前序和後序一起不可以//特點是 前後定根,中序定左右if(node == NULL)return;else{InOrder(node->lchild);cout<<node->data<<" ";InOrder(node->rchild);}}template<class T>void BiTree<T>::PostOrder(BiNode<T>* node){//LRT的最後一個一定是樹根if(node == NULL)return;else{PostOrder(node->lchild);PostOrder(node->rchild);cout<<node->data<<" ";}}template<class T>void BiTree<T>::PreOrderNonRec(BiNode<T>* node){stack<BiNode<T>*> s;BiNode<T>* p = node;while(p != NULL || !s.empty()){while(p != NULL){cout<<p->data<<" ";s.push(p);p = p->lchild;}if (!s.empty()){p = s.top();s.pop();p = p->rchild;}}}template<class T>void BiTree<T>::InOrderNonRec(BiNode<T>* node){//先序遍曆非遞迴需要藉助stack s來實現,類比遞迴調用//總的迴圈邊界是當前節點不為空白或者stack不空,//@1 在當前節點p非空時候,將p入棧s,p的左子樹賦給p,保證左子樹都能入棧//p為空白時候,也就是左子樹最左邊訪問到了,這時候在棧非空的時候//@2 取棧頂給p,輸入p,出棧,這時候最底層的最左邊節點訪問了,將p的右子樹賦給p,重複@1stack<BiNode<T>*> s;BiNode<T>* p = node;while(p != NULL || !s.empty()){while (p != NULL){s.push(p);p = p->lchild;}if (!s.empty()){p = s.top();cout<<p->data<<" ";s.pop();p = p->rchild;}}}template<class T>void BiTree<T>::PostOrderNonRec(BiNode<T>* node){//要保證根結點在左孩子和右孩子訪問之後才能訪問,//因此對於任一結點P,先將其入棧。如果P不存在左孩子和右孩子,則可以直接存取它;//或者P存在左孩子或者右孩子,但是其左孩子和右孩子都已被訪問過了,則同樣可以直接存取該結點。//若非上述兩種情況,則將P的右孩子和左孩子依次入棧,這樣就保證了每次取棧頂元素的時候,//左孩子在右孩子前面被訪問,左孩子和右孩子都在根結點前面被訪問。if(node == NULL)return;stack<BiNode<T>*> s;s.push(node);//node是rootBiNode<T>* pre = NULL;BiNode<T>* cur;while(!s.empty()){cur = s.top();if(cur->lchild == NULL && cur->rchild == NULL || (pre != NULL)&&(pre == cur->lchild || pre == cur->rchild) )//上一次訪問的是當前節點的左子樹{cout<<cur->data<<" ";s.pop();pre = cur;}else{if(cur->rchild)s.push(cur->rchild);if (cur->lchild)s.push(cur->lchild);}}}template<class T>void BiTree<T>::LevelOrder(BiNode<T>* node){//層次遍曆需要queue來實現,思路://@1初始化queue//if root為空白 返回//@2 push(root)//@3 while(queue不為空白)//s <-- queue.front()//queue.pop()//輸入s.data//if(s的左子樹不空)//s的左子樹入隊//if(s的右子樹不空)//s的右子樹入隊queue<BiNode<T>*> q;BiNode<T>* s = node;if(s == NULL)return;q.push(s);while(!q.empty()){s= q.front();q.pop();cout<<s->data<<" ";if (s->lchild)q.push(s->lchild);if(s->rchild)q.push(s->rchild);}}
【測試】
#include "list.h"#include "binary_tree.h"#include <iostream>using namespace std;int main(){BiTree<char> my_tree;my_tree.PreOrder(my_tree.GetRoot());cout<<endl;my_tree.PreOrderNonRec(my_tree.GetRoot());cout<<endl;my_tree.InOrder(my_tree.GetRoot());cout<<endl;my_tree.InOrderNonRec(my_tree.GetRoot());cout<<endl;my_tree.PostOrder(my_tree.GetRoot());cout<<endl;my_tree.LevelOrder(my_tree.GetRoot());cout<<endl;my_tree.PostOrderNonRec(my_tree.GetRoot());cout<<endl;}