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