二叉树的创建和释放

转自:<a target=_blank href="http://www.cnblogs.com/charley_yang/archive/2010/12/08/1900256.html">http://www.cnblogs.com/charley_yang/archive/2010/12/08/1900256.html</a>
/*********************************************************
* Description:参数传递:C++ 二叉树的实现以及指针使用注意事项
* Author:charley
* DateTime:2010-12-8 11:00
* Compile Environment:win7+vs2008
***********************************************************/
 
#include <iostream>
using namespace std;
 
//*************************************************************************************
//二叉树结点类的定义
template<class T>                  //模版结构体
struct TreeNode
{
    T data;                       //节点的内容
    TreeNode <T> *Lchild,*Rchild; //节点的左子树和右子树
 
    //可选择参数的默认构造函数
    /*TreeNode(T nodeValue = T(),TreeNode<T> *leftNode = NULL,TreeNode<T> *rightNode = NULL )
        :data(nodeValue),Lchild(leftNode),Rchild(rightNode){} */      
};
 
//**************************************************************************************
//二叉树的建立
template <class T> //模版方法
void createBinaryTree(TreeNode<T> *&root )  //传递指针的引用
{
    TreeNode<T>* p = root;
    T nodeValue ;
    cin>>nodeValue;
    if(nodeValue==-1)
    {
        root=NULL;
    }
    else
    {
        root=new TreeNode<T>();            //构造一个节点
        root->data = nodeValue;
        createBinaryTree(root->Lchild);    //递归构造左子树
        createBinaryTree(root->Rchild);    //递归构造右子树
    }
}
 
//************************************************************************************
//二叉树的先序遍历
template <class T>
void preOrder( TreeNode<T> * & p) //传递指针的引用
{
    if(p)
    {
        cout<<p->data<<" ";
        preOrder(p->Lchild);
        preOrder(p->Rchild);
    }
}
 
//**************************************************************************************
//二叉树的中序遍历
template <class T>
void inOrder(TreeNode<T> * & p) //传递指针的引用
{
     
    if(p)
    {
        inOrder(p->Lchild);
        cout<<p->data<<" ";
        inOrder(p->Rchild);
    }
}
 
//**************************************************************************************
//二叉树的后序遍历
template <class T>
void postOrder(TreeNode<T> *& p) //传递指针的引用
{
    if(p)
    {
        postOrder(p->Lchild);
        postOrder(p->Rchild);
        cout<<p->data<<" ";
    }
}
 
//*************************************************************************************
//统计二叉树中结点的个数
template<class T>
int countNode(TreeNode<T> * & p) //传递指针的引用
{
    if(p == NULL) return 0;
    return 1+countNode(p->Lchild)+countNode(p->Rchild);
}
 
//***********************************************************************************
//求二叉树的深度
template<class T>
int depth(TreeNode<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(TreeNode<T>* p) 这种声明会创建一个局部的临时对象来保存传递的指针
//虽然2个指针都执行同一块堆空间,delete局部指针 也会删除二叉树结构所占用的堆内存
//但是全局传递的那个指针将会是垃圾指针,会产生不可预料的错误
//void destroy(TreeNode<T> *& p) 此函数的参数为全局指针的一个别名,代表全局指针rootNode本身
//  这样p = NULL;能达到置空指针的左右
//可选的方案是在调用完destroy方法之后,在主函数中执行rootNode = NULL操作
template<class T>
void destroy(TreeNode<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 ()
{
    TreeNode<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";
            createBinaryTree(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";
        }
         
    }
}
<img src="http://images.cnblogs.com/cnblogs_com/charley_yang/Windows-Live-Writer/C-_D38C/%E6%9C%AA%E6%A0%87%E9%A2%98-1_thumb_4.png" alt="未标题-1" />
<p style="margin: 10px auto; font-family: Verdana, 'Lucida Grande', Arial, Helvetica, sans-serif; line-height: 18px;"><span style="font-family:宋体;font-size:14px;color:#0000ff;">则创建二叉树输入的顺序为:8 7 5 1 –1 –1 –1 4 –1 –1 6 3 –1 –1 2 –1 -1</span></p><p style="margin: 10px auto; font-family: Verdana, 'Lucida Grande', Arial, Helvetica, sans-serif; line-height: 18px;"><span style="font-family:宋体;font-size:14px;color:#ff0000;">除了-1节点之外的就是实际创建的二叉树</span></p><p style="margin: 10px auto; font-family: Verdana, 'Lucida Grande', Arial, Helvetica, sans-serif; line-height: 18px;"><span style="font-family:宋体;font-size:14px;color:#ff0000;">-1不是实际的节点、输入-1仅表示子节点为空返回继续创建其他节点</span></p>

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值