zoukankan      html  css  js  c++  java
  • 【转】二叉树的实现及操作以及指针使用和删除注意事项

    #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仅表示子节点为空返回继续创建其他节点
    ********************************************************************************/
    }
    

      

  • 相关阅读:
    C语言中可变函数参数变量的实现
    Oracle电话面试
    JS和C#方法相互调用
    asp.net 页面从初始化到卸载事件顺序
    解决.NET CF 3.5 Bitmap(Stream)未处理异常问题
    sql2008新增时间类数据类型学习
    c#和Javascript操作同一json对象
    被研究生了
    分形
    跑钱
  • 原文地址:https://www.cnblogs.com/daocaowu/p/3107359.html
Copyright © 2011-2022 走看看