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;
}
构建二叉树示意图为:


运行程序结果为:



展开阅读全文

没有更多推荐了,返回首页