二元樹的走訪

二元樹的走訪

在這篇文章中我們建立一個二元樹

然後用遞回的方式來走訪他

除了常見的傳統走訪方式 (前序 中序 後序)

另外還有一種橫向的走訪方式

 

 

以下程式碼為一個二元樹的物件

		#define LEFT 0
		#define RIGHT 1
		#define NAME_LEN 128
		 
		 
		// Note:
		// If you delete the node.
		// Its child nodes will be deleted in same time.
		// Detail can be found in destruct.
		class CTreeNode
		{
		public:
		CTreeNode(const char* acName_);
		~CTreeNode();
		 
		BOOL Add(int iSide_, char* acName_);
		BOOL Add(int iSide_, CTreeNode* pChildNode_);
		 
		CTreeNode* GetNode(int iSide_) const;
		
		void GetName(char* acName_);
		 
		private:
		char _acName[NAME_LEN]; 
		CTreeNode* _pTreeNode[2];
		
		};
		 
		CTreeNode::CTreeNode(const char* acName_)
		{
		this->_pTreeNode[LEFT] = NULL;
		 
		this->_pTreeNode[RIGHT] = NULL;
		
		::memset(this->_acName, 0, sizeof(this->_acName));
		 
		::memcpy(this->_acName, acName_, sizeof(this->_acName));
		 
		//std::cout << this->_acName << "  constructed" << std::endl;
		}
		 
		 
		CTreeNode::~CTreeNode()
		{
		if(this->_pTreeNode[LEFT] != NULL)
		delete this->_pTreeNode[LEFT];
		 
		if(this->_pTreeNode[RIGHT] != NULL)
		delete this->_pTreeNode[RIGHT];
		 
		//std::cout << this->_acName << "  destructed" << std::endl;
		
		}
		 
		 
		void CTreeNode::GetName(char* acName_)
		{
		::memcpy(acName_, this->_acName, sizeof(this->_acName));
		}
		 
		 
		BOOL CTreeNode::Add(int iSide_, CTreeNode* pChildNode_)
		{
		if(this->_pTreeNode[iSide_] != NULL)
		{
		assert(0);
		return FALSE;
		}
		
		this->_pTreeNode[iSide_] = pChildNode_;
		 
		return TRUE;
		}
		 
		 
		BOOL CTreeNode::Add(int iSide_, char* acName_)
		{
		return this->Add(iSide_, new CTreeNode(acName_));
		}
		 
		 
		CTreeNode* CTreeNode::GetNode(int iSide_) const
		{
		return this->_pTreeNode[iSide_];
		}

 

 

 

我們使用手動的方式來建立我們需要的二元樹

		void Program()
		{
		CTreeNode* pRootNode = new CTreeNode("Root");
		 
		 
		pRootNode->Add(0, "0");
		
		pRootNode->GetNode(0)->Add(0, "0-0");
		pRootNode->GetNode(0)->GetNode(0)->Add(0, "0-0-0");
		pRootNode->GetNode(0)->GetNode(0)->Add(1, "0-0-1");
		 
		pRootNode->GetNode(0)->Add(1, "0-1");
		pRootNode->GetNode(0)->GetNode(1)->Add(0, "0-1-0");
		pRootNode->GetNode(0)->GetNode(1)->Add(1, "0-1-1");
		 
		 
		pRootNode->Add(1, "1");
		pRootNode->GetNode(1)->Add(0, "1-0");
		pRootNode->GetNode(1)->Add(1, "1-1");
		pRootNode->GetNode(1)->GetNode(1)->Add(1, "1-1-1");
		 
		 
		TraditionRecurrence(pRootNode);
		
		std::cout << std::endl;
		 
		int i=0;
		while(RecurrenceByLevel(pRootNode, i++)){}
		
		 
		delete pRootNode;
		}
		 
		void Visit(CTreeNode* pNode_)
		{
		char acBuff[128];
		::memset(acBuff, 0, sizeof(acBuff));
		pNode_->GetName(acBuff);
		std::cout << acBuff << std::endl;
		}

 

 

 

這是傳統的二元樹走訪方式

		void TraditionRecurrence(CTreeNode* pNode_)
		{
		if(pNode_==NULL)
		return;
		 
		// You can swap their sequence.
		// The result will be different (pre order, mid order, post order)
		Visit(pNode_);
		 
		TraditionRecurrence(pNode_->GetNode(0));
		 
		TraditionRecurrence(pNode_->GetNode(1));
		}

 

 

 

這是橫向的走訪方式

		int RecurrenceByLevel(CTreeNode* pNode_, int iLevel_)
		{
		if(!pNode_ || iLevel_<0)
		return 0;
		 
		if(iLevel_==0)
		{
		Visit(pNode_);
		return 1;
		}
		 
		return RecurrenceByLevel(pNode_->GetNode(0),iLevel_-1) + RecurrenceByLevel(pNode_->GetNode(1),iLevel_-1);
		}