二叉樹的遍歷 前序 中序 後序 分別實現遞歸和非遞歸遍歷方式

開始複習下數據結構,學習二叉樹將二叉樹的遍歷方式實現了一遍,非遞歸相對有點難度,通過收集資料最終完成了二叉樹的所有遍歷方式,做個記錄以備後用。廢話不說了,貼代碼!

1. BinaryTree.h

#ifndef _BINARY_TREE_H_
#define _BINARY_TREE_H_
#include <string>

typedef int POS;
typedef int METHOD;
typedef std::string String;

enum { LeftChild, RightChild };
enum { Preorder, Inorder, Postorder };

struct Node
{
	String elem;
	Node* left;
	Node* right;

	Node() { elem = ""; left = right = NULL; }
	Node(const String& str) { elem = str; left = right = NULL; }
};

class BinaryTree
{
public:
	BinaryTree(void);
	~BinaryTree(void);

public:
	//@ DESC:輸出樹
	//\params: 
	// method, 爲 中序後序前序三種遍歷方式,
	// recursive, 爲是否使用遞歸的方式
	void     DumpTree( METHOD method, bool recursive = false );
	//@ DESC:創建一棵樹,其實就是初始化了根節點
	//\params:  
	// rootContent, 參見Node的定義,其中elem的類型爲std::string, 其實就是爲了傳入根節點的內容
	void     CreateTree( const String& rootContent );
	//@ DESC:插入一個節點
	//\params:
	// root, 參數node的父節點
	// node, 要插入的節點
	// pos, 是左子樹還是右子樹
	//@RTRN:返回當前插入的節點,其實就是node
	Node*    InsertNode( Node* root, Node* node, POS pos );
	void     Destroy();
	Node*    Root();

private:
	void     PreorderDump();
	void     InorderDump();
	void     PostOrderDump();

	void     Dump( METHOD method, String info );
	void     Output( String info );

	void     PreorderR( Node* node );
	void     InorderR( Node* node );
	void     PostorderR( Node* node );

private:
	Node*    m_pRoot;
};

#endif

2. BianryTreeImp.cpp 二叉樹類的實現

#include "BinaryTree.h"
#include <vector>

// 使用vector實現了一個簡單的堆棧,這裏偷懶了,
// 使用鏈表會更快 
template <class T>
class Stack
{
public:
	void Push( const T& t ) { elements.insert( elements.begin(), t ); }
	T Pop() { T tmp = *(elements.begin());
			elements.erase( elements.begin() ); return tmp;  }
	bool IsEmpty() { return elements.empty(); }
	T Top() { return *(elements.begin()); }

private:
	std::vector<T> elements;
};

BinaryTree::BinaryTree(void)
{
	m_pRoot = NULL;
}


BinaryTree::~BinaryTree(void)
{
	Destroy();
}

void BinaryTree::CreateTree( const String& rootContent )
{
	if ( m_pRoot )
		Destroy();

	m_pRoot = new Node;
	m_pRoot->elem = rootContent;
}

// DESC: 這個函數是不完整的,缺少了對樹的所有子節點的內存釋放,
// 這裏沒寫 
void BinaryTree::Destroy()
{
	if ( m_pRoot )
	{
		delete m_pRoot;
		m_pRoot = NULL;
	}
}

void BinaryTree::DumpTree( METHOD method, bool recursive )
{
	switch( method )
	{
	case Preorder:
		{
			if ( recursive )
			{
				PreorderR( m_pRoot );
				Output( "\n" );
			}
			else
			{
				PreorderDump();
			}
			break;
		}
	case Inorder:
		{
			if ( recursive )
			{
				InorderR( m_pRoot );
				Output( "\n" );
			}
			else
			{
				InorderDump();
			}
			break;
		}
	case Postorder:
		{
			if ( recursive )
			{
				PostorderR( m_pRoot );
				Output( "\n" );
			}
			else
			{
				PostOrderDump();
			}
			break;
		}
	}
}

void BinaryTree::PreorderDump()
{
	Node* p = m_pRoot;
	Stack<Node*> stack;
	while( p != NULL || !stack.IsEmpty() )
	{
		while ( p != NULL )
		{
			Output( p->elem );
			stack.Push( p );
			p = p->left;
		}

		if ( !stack.IsEmpty() )
		{
			p = stack.Pop();
			p = p->right;
		}
	}

	Output( "\n" );
}

void BinaryTree::InorderDump()
{
	Node* p = m_pRoot;
	Stack<Node*> stack;
	while( p != NULL || !stack.IsEmpty() )
	{
		if ( p != NULL )
		{
			stack.Push( p ); // if has left tree
			p = p->left;
		}
		else // left tree traversed
		{
			p = stack.Pop();
			Output( p->elem );
			p = p->right;
		}
	}

	Output( "\n" );
}

void BinaryTree::PostOrderDump()
{
	Node* p = m_pRoot;
	Stack<Node*> stack;
	Node* pPre = NULL;
	while( p != NULL || !stack.IsEmpty() )
	{
		if ( p != NULL )
		{
			stack.Push( p ); // if has left tree
			p = p->left;
		}
		else 
		{
			p = stack.Top();
			if ( p->right != NULL && pPre != p->right ) 
			{
				p = p->right;
			}
			else
			{
				p = pPre = stack.Top();
				Output( p->elem );
				stack.Pop();
				p = NULL;
			}
		}
	}

	Output( "\n" );
}

Node* BinaryTree::InsertNode( Node* root, Node* node, POS pos )
{
	switch ( pos )
	{
	case LeftChild:
		{
			root->left = node;
			break;
		}
	case RightChild:
		{
			root->right = node;
			break;
		}
	}

	return node;
}

Node* BinaryTree::Root()
{
	return m_pRoot;
}

void BinaryTree::Dump( METHOD method, String info )
{
	switch( method )
	{
	case Preorder:
		{
			printf( "Preorder: %s", info.data() );
			break;
		}
	case Inorder:
		{
			printf( "Inorder: %s", info.data() );
			break;
		}
	case Postorder:
		{
			printf( "Postorder: %s", info.data() );
			break;
		}
	}
}

void BinaryTree::Output( String info )
{
	printf( "%s", info.data() );
}

void BinaryTree::PreorderR( Node* node )
{
	if ( node )
	{
		// Visit
		Output( node->elem );

		PreorderR( node->left );
		PreorderR( node->right );
	}
}

void BinaryTree::InorderR( Node* node )
{
	if ( node )
	{
		InorderR( node->left );

		// Visit
		Output( node->elem );

		InorderR( node->right );
	}
}

void BinaryTree::PostorderR( Node* node )
{
	if ( node )
	{
		PostorderR( node->left );
		PostorderR( node->right );

		// Visit
		Output( node->elem );
	}
}


3. 測試代碼

樹結構如下圖



int _tmain(int argc, _TCHAR* argv[])
{
	BinaryTree* pTree = new BinaryTree;
	pTree->CreateTree( "+" );

	// Construct left child tree
	Node* pNow = pTree->InsertNode( pTree->Root(), new Node("+"), LeftChild );
	pTree->InsertNode( pNow, new Node("a"), LeftChild );
	pNow = pTree->InsertNode( pNow, new Node("*"), RightChild );
	pTree->InsertNode( pNow, new Node("b"), LeftChild );
	pTree->InsertNode( pNow, new Node("c"), RightChild );

	// Construct right child tree
	pNow = pTree->InsertNode( pTree->Root(), new Node("*"), RightChild );
	pTree->InsertNode( pNow, new Node("g"), RightChild );
	pNow = pTree->InsertNode( pNow, new Node("+"), LeftChild );
	pTree->InsertNode( pNow, new Node("f"), RightChild );
	pNow = pTree->InsertNode( pNow, new Node("*"), LeftChild );
	pTree->InsertNode( pNow, new Node("d"), LeftChild );
	pTree->InsertNode( pNow, new Node("e"), RightChild );

	printf( _T("前序:\n") );
	pTree->DumpTree( Preorder );
	printf( _T("中序:\n") );
	pTree->DumpTree( Inorder );
	printf( _T("後序:\n") );
	pTree->DumpTree( Postorder );

	delete pTree;
	pTree = NULL;
	return 0;
}


輸出



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章