1. 程式人生 > >二叉樹C++實現

二叉樹C++實現

最近整理原來的一些程式碼,腦子有點不好使,還是記下來吧。

//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,重複@1
	stack<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是root
	BiNode<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;

}