1. 程式人生 > >c++學習筆記—二叉樹基本操作的實現

c++學習筆記—二叉樹基本操作的實現

用c++語言實現的二叉樹基本操作,包括二叉樹的建立、二叉樹的遍歷(包括前序、中序、後序遞迴和非遞迴演算法)、求二叉樹高度,計數葉子節點數、計數度為1的節點數等基本操作。

IDE:vs2013


具體實現程式碼如下:

#include "stdafx.h"
#include <malloc.h>
#include <stack>
#include <iostream>
#define MAXSIZE 100 
using namespace std;
typedef struct node   //二叉樹結構體
{
	int data;
	struct node *lchild;
	struct node *rchild;
}Bnode,*BTree;

BTree CreateBinaryTree(BTree &tree){            //建立二叉樹
	int inputdata;
	cin >> inputdata;
	if (-1 == inputdata)
	{
		tree = NULL;
	}
	else
	{
		if (!(tree = (Bnode*)malloc(sizeof(Bnode))))
		{
			cout<<"ERROR";
		}
		tree->data = inputdata;
		tree->lchild=CreateBinaryTree(tree->lchild);
		tree->rchild=CreateBinaryTree(tree->rchild);
	}
	return tree;
}
void preorderTraverse(BTree tree)    //遞迴前序遍歷
{
	if (tree != NULL)
	{
		cout<<tree->data;
	}
	if (tree->lchild != NULL)
	{
		preorderTraverse(tree->lchild);
	}
	if (tree->rchild)
	{
		preorderTraverse(tree->rchild);
	}
}

void preorderTraverse2(BTree tree)   
{

	//////////////////////////////////////////////////////////////////////////
	//			非遞迴前序                     	
	//    根據前序遍歷訪問的順序,優先訪問根結點,				
	//    然後再分別訪問左孩子和右孩子。						
	//    即對於任一結點,其可看做是根結點,因此可以直接訪問,訪問完之後,  
	//    若其左孩子不為空,按相同規則訪問它的左子樹;當訪問其左子樹時,    
	//    再訪問它的右子樹。因此其處理過程如下:				
	//									
	//////////////////////////////////////////////////////////////////////////
	stack<BTree> s;
	if (!tree)
	{
		cout << "空樹" << endl;
		return;
	}
	while (tree || !s.empty())
	{
		while (tree)
		{
			s.push(tree);
			cout << tree->data;
			tree = tree->lchild;
		}
		tree = s.top();
		s.pop();
		tree = tree->rchild;
	}
}

void inorderTraverse(BTree tree)      //遞迴中序遍歷
{
	if (tree->lchild)
	{
		inorderTraverse(tree->lchild);
	}
	cout << tree->data;
	if (tree->rchild)
	{
		inorderTraverse(tree->rchild);
	}
}
void inorderTraverse2(BTree tree)     
{
	 //////////////////////////////////////////////////////////////////////////
	 //		       非遞迴中序遍歷 		         	
         //      根據中序遍歷的順序,對於任一結點,優先訪問其左孩子,	        	
         //      而左孩子結點又可以看做一根結點,然後繼續訪問其左孩子結點,	
        //       直到遇到左孩子結點為空的結點才進行訪問,		         
        //       然後按相同的規則訪問其右子樹。					 
        //       因此其處理過程如下:				
        //									
	///////////////////////////////////////////////////////////////////////////
	stack<BTree> s;
	if (!tree)
	{
		cout << "空樹" << endl;
		return;
	}
	while (tree || !s.empty())
	{
		while (tree)
		{
			s.push(tree);
			tree = tree->lchild;
		}
		tree = s.top();
		s.pop();
		cout << tree->data;
		tree = tree->rchild;
	}
}
void postoderTraverse(BTree tree)     //遞迴後序遍歷
{
	if (tree->lchild)
	{
		postoderTraverse(tree->lchild);
	}
	if (tree->rchild)
	{
		postoderTraverse(tree->rchild);
	}
	cout << tree->data;
}

void postoderTraverse2(BTree tree)			
{
	//////////////////////////////////////////////////////////////////////////
	//			非遞迴後序遍歷		
	//      要保證根結點在左孩子和右孩子訪問之後才能訪問,			
	//	因此對於任一結點P,先將其入棧。如果P不存在左孩子和右孩子,
	//	則可以直接訪問它;或者P存在左孩子或者右孩子,			
	//	但是其左孩子和右孩子都已被訪問過了,則同樣可以直接訪問該結點。  
	//	若非上述兩種情況,則將P的右孩子和左孩子依次入棧,		
	//	這樣就保證了每次取棧頂元素的時候,左孩子在右孩子前面被訪問,	
	//	左孩子和右孩子都在根結點前面被訪問。				
	//////////////////////////////////////////////////////////////////////////

	stack<BTree> s;
	BTree cur;                        //當前結點 
	BTree pre = NULL;                 //前一次訪問的結點 
	s.push(tree);
	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 != NULL)
				s.push(cur->rchild);
			if (cur->lchild != NULL)
				s.push(cur->lchild);
		}
	}
}
int Depth(BTree T)   //求二叉樹的深度
{
	int dep = 0, depl, depr;
	if (!T) dep = 0;
	else
	{
		depl = Depth(T->lchild);
		depr = Depth(T->rchild);
		dep = 1 + (depl>depr ? depl : depr);
	}
	return dep;
}
int sumLeaf(BTree tree)   //求葉子節點的個數
{                         
	int sum = 0, m, n;
	if (tree)
	{
		if ((!tree->lchild) && (!tree->rchild))
			sum++;
		m = sumLeaf(tree->lchild);
		sum += m;
		n = sumLeaf(tree->rchild);
		sum += n;
	}
	return sum;
}
int numnSinglePoint(BTree tree )    //統計度為1的節點數目
{
	int sum = 0, m, n;
	if (tree)
	{
		if ((tree->lchild!=NULL) && (tree->rchild == NULL))
			sum++;
		if ((tree->lchild == NULL) && (tree->rchild != NULL))
			sum++;
		m = numnSinglePoint(tree->lchild);
			sum += m;
		n = m = numnSinglePoint(tree->rchild);
			sum += n;
	}
	return sum;
}

int _tmain(int argc, _TCHAR* argv[])
{
	BTree t;
	t= CreateBinaryTree(t);
	cout<<endl<<"非遞迴前序遍歷:";
	preorderTraverse2(t);
	cout << endl<<"----------------------"<<endl;
	cout << "遞迴前序遍歷:";
	preorderTraverse(t);
	cout << endl << "---------------------"<<endl;
	cout << "非遞迴中序遍歷:";
	inorderTraverse2(t);
	cout << endl << "---------------------"<<endl;
	cout << "遞迴中序遍歷:";
	inorderTraverse(t);
	cout << endl << "---------------------"<<endl;
	cout << "非遞迴後序遍歷:";
	postoderTraverse2(t);
	cout << endl << "---------------------"<<endl;
	cout << "遞迴後序遍歷:";
	postoderTraverse(t);
	cout << endl << "----------------------"<<endl;
	cout << "連結串列深度為:"<<Depth(t);
	cout << endl << "----------------------"<<endl;
	cout << "連結串列的葉子節點個數為:" << sumLeaf(t);
	cout << endl << "----------------------"<<endl;
	cout << "連結串列中度為1的節點數目為:" << numnSinglePoint(t) << endl;
	return 0;
}
構建二叉樹示意圖為:


執行程式結果為: