#include <iostream>
#include <ctime>
using namespace std;
/*********************************************************
* Description:参数传递:C++ 二叉树的实现以及指针使用注意事项
* Author:ADao12
* DateTime:2013-05-30 02:27
* Compile Environment:win8+vs2012
***********************************************************/
//*************************************************************************************
//二叉树结点类的定义
template<class T> //模版结构体
struct BTNode
{
T data; //节点的内容
BTNode<T> *Lchild,*Rchild; //节点的左子树和右子树
BTNode(T nodeValue = T(), BTNode<T>* leftNode = NULL, BTNode<T>* rightNode = NULL)
:data(nodeValue),Lchild(leftNode),Rchild(rightNode){} //可选择参数的默认构造函数
};
//**************************************************************************************
//二叉树的建立
template<class T> //模版方法
void createBinTree(BTNode<T> *&root ) //传递指针的引用
{
BTNode<T>* p;
BTNode<T>* k;
T nodeValue ;
cin>>nodeValue;
if(nodeValue==-1)
{
root=NULL;
}
else
{
p = new BTNode<T>(); //构造一个节点
root = p;
p->data = nodeValue;
createBinTree(p->Lchild); //递归构造左子树
createBinTree(p->Rchild); //递归构造右子树
}
}
//************************************************************************************
//二叉树的先序遍历
template<class T>
void preOrder( BTNode<T> * & p) //传递指针的引用
{
if (p)
{
cout<<p->data<<" ";
preOrder(p->Lchild);
preOrder(p->Rchild);
}
}
//**************************************************************************************
//二叉树的中序遍历
template<class T>
void inOrder(BTNode<T> * & p) //传递指针的引用
{
if (p)
{
preOrder(p->Lchild);
cout<<p->data<<" ";
preOrder(p->Rchild);
}
}
//**************************************************************************************
//二叉树的后序遍历
template<class T>
void postOrder(BTNode<T> *& p) //传递指针的引用
{
if (p)
{
preOrder(p->Lchild);
preOrder(p->Rchild);
cout<<p->data<<" ";
}
}
//*************************************************************************************
//统计二叉树中结点的个数
template<class T>
int countNode(BTNode<T> * & p) //传递指针的引用
{
if (p == NULL)
{
return 0;
}
else
{
return 1+countNode(p->Lchild)+countNode(p->Rchild);
}
}
//***********************************************************************************
//求二叉树的深度
template<class T>
int depth(BTNode<T> *& p) //传递指针的引用
{
if (p == NULL)
return -1;
int h1 = depth(p->Lchild);
int h2 = depth(p->Rchild);
if (h1 > h2) return h1 + 1;
return h2 + 1;
}
//***********************************************************************************
//二叉树的消毁操作
//容易混淆的错误声明:void destroy(BTNode<T>* p) 这种声明会创建一个局部的临时对象来保存传递的指针
//虽然2个指针都执行同一块堆空间,delete局部指针 也会删除二叉树结构所占用的堆内存
//但是全局传递的那个指针将会是垃圾指针,会产生不可预料的错误
//void destroy(BTNode<T> *& p) 此函数的参数为全局指针的一个别名,代表全局指针rootNode本身
// 这样p = NULL;能达到置空指针的左右
//可选的方案是在调用完destroy方法之后,在主函数中执行rootNode = NULL操作
template<class T>
void destroy(BTNode<T> *& p) //传递指针的引用,消毁函数,用来消毁二叉树中的各个结点
{
if (p)
{
//错误 return之后 没有执行delete p
//return destroy(p->Lchild);
//return destroy(p->Rchild)
destroy(p->Lchild);
destroy(p->Rchild);
//delete只能释放由用户通过new方式在堆中申请的内存,
//是通过变量声明的方式由系统所声明的栈内存不能使用delete删除
//delete和free函数一样,不修改它参数对应指针指向的内容,也不修改指针本身,
//只是在堆内存管理结构中将指针指向的内容标记为可被重新分配
delete p;
//堆上内存释放 栈上指针并不销毁
//此时p指向的地址未知,此时执行*p = ? 操作会导致不可预料的错误
//但是可以重新赋值p = &x;
//最好delete之后把P置空
p = NULL;
}
}
//主函数的设计
int main()
{
BTNode<int> *rootNode = NULL;
int choiced = 0;
while(true)
{
system("cls"); //清屏
cout<<"\n\n\n ---主界面---\n\n\n";
cout<<" 1、创建二叉树 2、先序遍历二叉树\n";
cout<<" 3、中序遍历二叉树 4、后序遍历二叉树\n";
cout<<" 5、统计结点总数 6、查看树深度 \n";
cout<<" 7、消毁二叉树 0、退出\n\n";
cout<<" 请选择操作:";
cin>>choiced;
if(choiced == 0)
return 0;
else if(choiced == 1)
{
system("cls");
cout<<"请输入每个结点,回车确认,并以-1结束:\n";
createBinTree(rootNode);
}
else if(choiced == 2)
{
system("cls");
cout<<"先序遍历二叉树结果:\n";
preOrder(rootNode);
cout<<endl;
system("pause"); //暂停屏幕
}
else if(choiced == 3)
{
system("cls");
cout<<"中序遍历二叉树结果:\n";
inOrder(rootNode);
cout<<endl;
system("pause");
}
else if(choiced == 4)
{
system("cls");
cout<<"后序遍历二叉树结果:\n";
postOrder(rootNode);
cout<<endl;
system("pause");
}
else if(choiced == 5)
{
system("cls");
int count = countNode(rootNode);
cout<<"二叉树中结点总数为"<<count<<endl;
system("pause");
}
else if(choiced == 6)
{
system("cls");
int dep = depth(rootNode);
cout<<"此二叉树的深度为"<<dep<<endl;
system("pause");
}
else if(choiced == 7)
{
system("cls");
cout<<"二叉树已被消毁!\n";
destroy(rootNode);
cout<<endl;
system("pause");
}
else
{
system("cls");
cout<<"\n\n\n\n\n\t错误选择!\n";
}
}
/*******************************************************************************
**除了-1节点之外的就是实际创建的二叉树
**-1不是实际的节点、输入-1仅表示子节点为空返回继续创建其他节点
********************************************************************************/
}