zoukankan      html  css  js  c++  java
  • 二叉树的建立与功能实现

    树结点

    template<class T>
    struct BinTreeNode  //结点
    {
    	T data;
    	BinTreeNode<T>* leftChild, * rightChild;
    	BinTreeNode() :leftChild(NULL), rightChild(NULL) {}                //默认构造函数
    	BinTreeNode(T x) :data(x), leftChild(NULL), rightChild(NULL) {}  //有参构造函数(赋予结点值)
    };
    

    定义树

    template<class T>
    class BinaryTree
    {
    public:
    	BinaryTree() :root(NULL) {}
    	BinaryTree(T value) :RefValue(value), root(NULL) {}
    	BinTreeNode<T>* &getRoot() { return root; }                     //取根//注意这一个代码
    	~BinaryTree() { Destory(root); }
    	void Destory(BinTreeNode<T>*& subTree);                             
    	void CreatBinTree(BinTreeNode<T>*& subTree);
    	void PreOrder(BinTreeNode<T>* subTree);                            //先序
    	void InOrder(BinTreeNode<T>* subTree);                             //中序
    	void Leaf(BinTreeNode<T>* subTree);
    	int  Height(BinTreeNode<T>* subTree);
    	int Size(BinTreeNode<T>*subTree);
    	
    protected:
    	T RefValue;                                                       //识别叶节点
    	BinTreeNode<T>* root;                                                                                                
    };
    
    • 传入的subTree一定要是一个引用的形式,不然内部我们用形参指针接收时,对形参的改变不会影响到实参。
    • 一定注意取根的那一个函数,getRoot,书上的代码没有前面的&,结果我在main函数里传都传不进去。取根是非常关键的一步,我们的指向根结点的指针*root是放在protected成员里面的,如果取不到根是无法进行后面操作。而我们取根返回的是一个指向根结点的指针,大家知道函数的返回值是一个右值,但是我们上一步传入是用一个引用接收的,引用只能接收左值,这就产生了矛盾。(对右值左值如果不太清楚可以看我上一篇文章)解决的办法就是在函数前面加上&,用引用去接收,这样返回的引用就是左值啦。

    创建树

    template<class T>
    void BinaryTree<T>::CreatBinTree(BinTreeNode<T>*&subTree)               //注意用引用接收指针  如果只传入指针 形参的指针指向改变 实参不会变
    {
    	T ch;
    	cin >> ch;
    		if (ch == RefValue) subTree = NULL;
    		else
    		{
    			subTree = new BinTreeNode<T>(ch);                      //有参构造函数 建立结点
    			CreatBinTree(subTree->leftChild);                      //递归
    			CreatBinTree(subTree->rightChild);
    	}
    }
    

    删除树

    template<class T>
    void BinaryTree<T>::Destory(BinTreeNode<T>*& subTree)
    {
    	if (subTree != NULL)
    	{
    		Destory(subTree->leftChild);
    		Destory(subTree->rightChild);
    		delete subTree;
    	}
    
    }
    

    前序遍历和中序遍历

    template<class T>
    void BinaryTree<T>::PreOrder(BinTreeNode<T>* subTree)
    {
    	if (subTree != NULL)
    	{
    		cout << subTree->data << ' ';
    		PreOrder(subTree->leftChild);
    		PreOrder(subTree->rightChild);
    	}
    }
    
    template<class T>
    void BinaryTree<T>::InOrder(BinTreeNode<T>* subTree)
    {
    	if (subTree != NULL)
    	{
    		InOrder(subTree->leftChild);
    		cout << subTree->data << ' ';
    		InOrder(subTree->rightChild);
    	}
    }
    

    求树叶结点个数

    template<class T>
    void BinaryTree<T>::Leaf(BinTreeNode<T>* subTree)
    {
    	if (subTree != NULL)
    	{
    		if (subTree->leftChild == NULL && subTree->rightChild == NULL)
    			cnt2++;
    		Leaf(subTree->leftChild);
    		Leaf(subTree->rightChild);
    	}
    }
    //只能用先序来写,感觉用递归return应该也行 不过暂时没想到..
    

    求树高度

    template <class T>
    int  BinaryTree<T>::Height(BinTreeNode<T>* subTree)
    {
    	if (subTree == NULL) return 0;	//空树高度为0
    	else
    	{
    		int i = Height(subTree->leftChild);
    		int j = Height(subTree->rightChild);
    		return (i < j) ? j + 1 : i + 1;
    	}
    }
    //可能不太好理解 画一个图比划几下可能好一些
    

    求树结点个数

    template <class T>
    int BinaryTree<T>::Size(BinTreeNode<T>* subTree)
    {
    	if (subTree == NULL) return 0;
    	else return 1 + (Size(subTree->leftChild) + Size(subTree->rightChild));
    }
    
    • 补充几点

    • subTree是任意一个结点,建立了树以后传入随意的值了,为了方便我只是传了根结点,所以理解为求树~~~,应该是根为subTree的树的函数。

    • 我们不难发现,树的一些函数的实现也就是在先序or中序or后序上加了一些特有的功能,比如求叶节点的时候我们就先序了一遍,求树高度和树结点个数的过程其实也是后序的过程。

    main函数

    int main()
    {
    	BinaryTree<char>Tree1('@');
    	Tree1.CreatBinTree(Tree1.getRoot());
    	cout << "先序遍历:";
    	Tree1.PreOrder(Tree1.getRoot());
    	cout << endl;
    	cout << "中序遍历:";
    	Tree1.InOrder(Tree1.getRoot());
    	cout << endl;
    	Tree1.Leaf(Tree1.getRoot());
    	cout << "该树叶节点个数为:" << cnt2 << endl;
    	cout << "该树高" << Tree1.Height(Tree1.getRoot());
    	cout << "该树的结点个数为" << Tree1.Size(Tree1.getRoot());
    }
    

    截图

    后续补充 层序遍历

    template<class T>
    void BinaryTree<T>::LevelOrder(BinTreeNode<T>* subTree)
    {
    	queue<BinTreeNode<T>*>Q;
    	BinTreeNode<T>* p = root;
    	Q.push(p);
    	while (!Q.empty())
    	{
    			BinTreeNode<T> * t = Q.front();
    			Q.pop();
    			cout << t->data <<" ";
    			if (t->leftChild != NULL) Q.push(t->leftChild);
    			if (t->rightChild != NULL)Q.push(t->rightChild);
    	}
    }
    
    

    代码

    感兴趣的话可以调试一下,很多函数都可以自己添加,为了大家方便我把总代码放在下面:

    
    #include<iostream>
    using namespace std;
    
    int cnt2;//统计叶节点个数
    
    template<class T>
    struct BinTreeNode  //结点
    {
    	T data;
    	BinTreeNode<T>* leftChild, * rightChild;
    	BinTreeNode() :leftChild(NULL), rightChild(NULL) {}                //默认构造函数
    	BinTreeNode(T x) :data(x), leftChild(NULL), rightChild(NULL) {}  //有参构造函数(赋予结点值)
    };
    
    
    template<class T>
    class BinaryTree
    {
    public:
    	BinaryTree() :root(NULL) {}
    	BinaryTree(T value) :RefValue(value), root(NULL) {}
    	BinTreeNode<T>* &getRoot() { return root; }                         //取根
    	~BinaryTree() { Destory(root); }
    	void Destory(BinTreeNode<T>*& subTree);
    	void CreatBinTree(BinTreeNode<T>*& subTree);
    	void PreOrder(BinTreeNode<T>* subTree);                            //先序
    	void InOrder(BinTreeNode<T>* subTree);                             //中序
    	void Leaf(BinTreeNode<T>* subTree);
    	int  Height(BinTreeNode<T>* subTree);
    	int Size(BinTreeNode<T>*subTree);
    	
    protected:
    	T RefValue;                                                       //识别叶节点
    	BinTreeNode<T>* root;                                             //本来应该在protected里面                                                      
    };
    
    
    
    template<class T>
    void BinaryTree<T>::CreatBinTree(BinTreeNode<T>*&subTree)               //注意!!!!传入的是指针的引用 如果只传入指针 形参的指针指向改变 实参不会变
    {
    	T ch;
    	cin >> ch;
    		if (ch == RefValue) subTree = NULL;
    		else
    		{
    			subTree = new BinTreeNode<T>(ch);
    			CreatBinTree(subTree->leftChild);
    			CreatBinTree(subTree->rightChild);
    	}
    }
    
    template<class T>
    void BinaryTree<T>::Destory(BinTreeNode<T>*& subTree)
    {
    	if (subTree != NULL)
    	{
    		Destory(subTree->leftChild);
    		Destory(subTree->rightChild);
    		delete subTree;
    	}
    
    }
    
    
    template<class T>
    void BinaryTree<T>::PreOrder(BinTreeNode<T>* subTree)
    {
    	if (subTree != NULL)
    	{
    		cout << subTree->data << ' ';
    		PreOrder(subTree->leftChild);
    		PreOrder(subTree->rightChild);
    	}
    }
    
    template<class T>
    void BinaryTree<T>::InOrder(BinTreeNode<T>* subTree)
    {
    	if (subTree != NULL)
    	{
    		InOrder(subTree->leftChild);
    		cout << subTree->data << ' ';
    		InOrder(subTree->rightChild);
    	}
    }
    
    template<class T>
    void BinaryTree<T>::Leaf(BinTreeNode<T>* subTree)
    {
    	if (subTree != NULL)
    	{
    		if (subTree->leftChild == NULL && subTree->rightChild == NULL)
    			cnt2++;
    		Leaf(subTree->leftChild);
    		Leaf(subTree->rightChild);
    	}
    }
    
    template <class T>
    int  BinaryTree<T>::Height(BinTreeNode<T>* subTree)
    {
    	if (subTree == NULL) return 0;	//空树高度为0
    	else
    	{
    		int i = Height(subTree->leftChild);
    		int j = Height(subTree->rightChild);
    		return (i < j) ? j + 1 : i + 1;
    	}
    }
    
    template <class T>
    int BinaryTree<T>::Size(BinTreeNode<T>* subTree)
    {
    	if (subTree == NULL) return 0;
    	else return 1 + (Size(subTree->leftChild) + Size(subTree->rightChild));
    }
    
    int main()
    {
    	BinaryTree<char>Tree1('@');
    	Tree1.CreatBinTree(Tree1.getRoot());
    	cout << "先序遍历:";
    	Tree1.PreOrder(Tree1.getRoot());
    	cout << endl;
    	cout << "中序遍历:";
    	Tree1.InOrder(Tree1.getRoot());
    	cout << endl;
    	Tree1.Leaf(Tree1.getRoot());
    	cout << "该树叶节点个数为:" << cnt2 << endl;
    	cout << "该树高" << Tree1.Height(Tree1.getRoot())<<endl; 
    	cout << "该树的结点个数为" << Tree1.Size(Tree1.getRoot());
    }
    
  • 相关阅读:
    VMware虚拟机下实现NAT方式上网的小方法
    文件附件上传
    [转] 深入了解 HTML 5
    用JS获取图片尺寸
    Stream与byte的转换
    递归算法
    搞懂java中的synchronized关键字
    初学UML之用例图
    浅析tomcat nio 配置
    面向对象:单一任务原则(SRP)
  • 原文地址:https://www.cnblogs.com/yuuuuu422/p/13185595.html
Copyright © 2011-2022 走看看