二叉树结构——BTree、BTreeNode

二叉树引言

  通用树的结构过于复杂,工程中很少会用到这么复杂的树,该如何简化呢?→减少孩子结点数量→二叉树

  通用树结构回顾
    双亲孩子表示法:
      每个结点都有一个指向其双亲的指针
      每个结点都有若干个指向其孩子的指针


  二叉树树结构引进
    孩子兄弟表示法:
      每个结点都有一个指向其第一个孩子的指针
      每个结点都有一个指向其第一个右兄弟的指针


  孩子兄弟表示法的特点
    能够表示任意的树形结构
    每个结点包含一个数据成员和两个指针成员
    孩子结点指针和兄弟结点指针构成了“树杈”
    
  二叉树的定义
    二叉树由n(n >= 0)个结点组成的有限集合,该集合或者为空
    或者由一个根结点加上两颗分别称为左子树和右子树的、互不相交的二叉树组成

  特殊的二叉树
    满二叉树:
      如果二叉树所有分支结点的度数都为2
      且叶节点都在同一层次上
      则称这类二叉树为满二叉树
    
    完全二叉树:
      如果一棵具有n个结点的高度为k的二叉树
      它的每一个结点都与高度为k的满二叉树中编号为1——n的结点一一对应
      则这棵二叉树称为完全二叉树(从上到下,从左到右编号)
      特点:
        *同样结点数的二叉树,完全二叉树的高度最小
        *完全二叉树的叶结点仅出现在最下面两层
          -最底层的叶结点一定出现在左边
          -倒数第二层的叶结点一定出现在右边
          -完全二叉树中度为1的结点只有左孩子


二叉树的性质

  性质1
    二叉树的第 i 层最多有2^(i - 1)个结点(根结点为第一层)
  性质2
    高度为 k 的二叉树最多有2^(i - 1)个结点
  性质3
    对任何一棵二叉树,如果其叶结点有 n0 个,度为2的非叶结点有 n2 个,则有 n0 = n2 + 1
    证明:
      假设二叉树中度为1的结点有 n1 个且总结点为 n 个
      则: n = n0 + n1 + n2
      假设二叉树中父节点与子结点间的边为 e 条
      则: e = n1 + 2 * n2 = n - 1
      所以: n0 = n2 + 1
      
  性质4
    具有 n 个结点的完全二叉树的高度为 k =(不大于log2 n的最大整数)+ 1
    证明:
      假设这 n 个结点组成的完全二叉树高度为 k
      则: 2^(k - 1) < n <= 2^(k - 1)
      因为 n 为整数,所以:
       k - 1 <= log2 n< k
      所以: k =(不大于log2 n的最大整数)+ 1
  性质5
    一棵具有 n 个结点的完全二叉树的高度为 k ,则按层次对结点进行编号(从上到下,从左到右)
    对任意结点 i 有:

二叉树的存储结构设计

  二叉树的继承结构:

  设计要点:
    BTree为二叉树结构,每个结点最多只有两个后继结点
    BTreeNode只包含四个固定的公有成员(左孩子、右孩子、双亲结点、数据)
    实现树形结构中的接口(增,删,查,等)

树是递归定义的,所以树中的函数也大都用递归实现!

  BTreeNode的设计与实现:
    继承自TreeNode(继承关系),添加两个结点指针(左孩子与右孩子)

  BTree的设计与实现:
    继承自Tree(继承关系),组合使用BTreeNode(组合关系)

  BTree的实现架构图:


二叉树的结点查找操作

 1、通过树中的元素的值查找
   定义功能:find(node,value)
   在node为根节点的树中查找value所在的结点

 2、通过树中的结点的值查找
   定义功能:find(node,obj)
   在node为根节点的树中查找是否存在obj结点

二叉树中的插入操作

  如何指定树中的结点插入在什么位置?
    二叉树是非线性的,无法使用下标来定位数据元素
    每一个结点都有唯一的前驱结点(父节点)
    因此,必须找到(指明)前驱结点,才可以插入新结点
    又:二叉树每一个结点都只有两个孩子结点
    所以可以定义新的数据类型,指明插入的位置

//  添加一种新的数据类型,用来指明二叉树插入的位置
enum BTNodePos
{
	ANY,
	LEFT,
	RIGHT
};
插入结点流程图

插入数据流程图

二叉树中的清除操作

  定义清除操作功能:free(node)
    清除node为根节点的树
    释放树中的每一个结点(内存中的释放)


  树中的结点可能来源与不同的存储空间,如何判断堆空间中的结点并释放?(PS:单凭内存地址很难判断是否为堆空间创建的)
    使用工厂模式
    在TreeNode中增加包含成员变量m_flag
    将TreeNode中的operator new重载为包含成员函数(无法外部new出新对象)
    提供工厂方法BTreeNode* NewNode()
    在工厂方法中,new出新结点时,将m_flag设置为true
    无参构造的时候,m_flag设置为false
    只有这两种方式可以产生结点,所以可以通过m_flag判断是否为堆对象。

二叉树中的删除操作

  删除操作成员函数的设计要点
    将删除结点所代表的子树一并删除
    如果删除中的结点所代表的子树中,有扔需要的数据怎么办?
      删除后,返回为一棵独立的堆空间中的树
    如果没有需要的数据呢?
      返回为指向该子树的智能指针对象
      不需要的话,因为生命周期原因,会直接析构
      需要的话,使用智能指针对象指向即可继续使用

删除流程图

二叉树中的属性操作

二叉树的属性计算示例

 1、二叉树中结点的数目
   定义功能:count(node)
   在node为根节点的二叉树中统计结点数目

 2、二叉树的高度
   定义功能:height(node)
   获取node为根结点的二叉树的高度

 3、二叉树的度数
   定义功能:degree(node)
   获取node为根结点的二叉树的度数

二叉树中的遍历方式

层次遍历

  与Gtree的设计方式相同,设计思路:
    使用游标的方式,利用LinkQueue实现
    提供一组遍历相关函数:begin() current() next() end()
    函数实现方式:
      begin() → 将根节点压入队列
      current() → 返回队头结点指向的数据元素
      next() → 将队头结点弹出,将队头结点的孩子压入队列中
      end() → 判断队列是否为空

层次遍历算法示例

递归遍历方式

1 先序遍历:
  二叉树为空:
    无操作,直接返回
  二叉树不为空:
    1 访问根结点中的数据元素
    2 先序遍历左子树
    3 先序遍历右子树

先序遍历结果

2 中序遍历:
  二叉树为空:
    无操作,直接返回
  二叉树不为空:
    1 中序遍历左子树
    2 访问根结点中的数据元素
    3 中序遍历右子树

中序遍历结果

3 后序遍历:
  二叉树为空:
    无操作,直接返回
  二叉树不为空:
    1 后序遍历左子树
    2 后序遍历右子树
    3 访问根结点中的数据元素

后序遍历结果

先序 中序 后序遍历函数

//先序遍历
void preOrderTraversal(BTreeNode<T>* node,LinkQueue<BTreeNode<T>*>& queue)
{
    if(node)
    {
        queue.add(node);
        preOrderTraversal(node->left,queue);
        preOrderTraversal(node->right,queue);
    }
}

//中序遍历
void inOrderTraversal(BTreeNode<T>* node,LinkQueue<BTreeNode<T>*>& queue)
{
    if(node)
    {
        inOrderTraversal(node->left,queue);
        queue.add(node);
        inOrderTraversal(node->right,queue);
    }
}

//后序遍历
void postOrderTraversal(BTreeNode<T>* node,LinkQueue<BTreeNode<T>*>& queue)
{
    if(node)
    {
        postOrderTraversal(node->left,queue);
        postOrderTraversal(node->right,queue);
        queue.add(node);
    }
}

遍历函数合并

  因为层次遍历函数是一组函数(begin() current() next() end() ),需要一直移动游标,来获取下一层次的数据,而先序、中序、后序遍历的方式,一次就获得了遍历树的结果。为了让层次遍历与先序、中序、后序遍历兼容,封装出一个新的层次遍历函数和一个总的遍历函数(通过变量确定使用哪种遍历方式)。

新的层次遍历函数,这样也可以一次调用,queue中即是层次遍历的结果

void levelOrderTraversal(BTreeNode<T>* node,LinkQueue<BTreeNode<T>*>& queue)
{
    if(node)
    {
        LinkQueue<BTreeNode<T>*> tmp;

        tmp.add(root());
        while(tmp.length() > 0)
        {
            BTreeNode<T>* n = tmp.front();

            if(n->left != NULL)
            {
                tmp.add(n->left);
            }
            if(n->right != NULL)
            {
                tmp.add(n->right);
            }

            tmp.remove();
            queue.add(n);
        }
    }
}

  定义新数据类型,来选择遍历的方式

/*顺序遍历方式*/
enum BTTraversal
{
    LevelOrder,//层次遍历
    PreOrder,//先序遍历
    InOrder,//中序遍历
    PostOrder//后序遍历
};

总的遍历函数:因为二叉树是可以有编号的(通常从上到下,从左向右编号),所以返回值为数组类型,可以根据编号直接访问对应的数据元素,为了防止内存泄漏,采用了智能指针类型

void traversal(BTTraversal order,LinkQueue<BTreeNode<T>*>& queue)
{
    switch(order)
    {
    case PreOrder:
        preOrderTraversal(root(),queue);
        break;
    case InOrder:
        inOrderTraversal(root(),queue);
        break;
    case PostOrder:
        postOrderTraversal(root(),queue);
        break;
    case LevelOrder:
        levelOrderTraversal(root(),queue);
        break;
    default:
        THROW_EXCEPTION(InvalidParameterException,"Parameter order is invalid ...");
        break;
    }
}

SharedPointer<Array<T>> traversal(BTTraversal order)
{
    DynamicArray<T>* ret = NULL;
    LinkQueue<BTreeNode<T>*>  queue;

    traversal(order,queue);//根据选择的遍历方式进行遍历,遍历结果放入queue中

    ret = new DynamicArray<T>(queue.length());

    if(ret)
    {
        for(int i=0;i<ret->length();i++,queue.remove())
        {
            ret->set(i,queue.front()->value);
        }
    }
    else
    {
        THROW_EXCEPTION(NoEnoughMemoryException,"No memory to create Array ...");
    }

    return ret;
}

二叉树的克隆操作

  返回一棵堆空间上的新二叉树(与当前树相等)

  定义功能:clone(node)
   拷贝node为根结点的二叉树(数据对应位置相同)

二叉树的比较操作

  对应位置的对应数据元素进行比较。容器里的数据类型需要支持比较操作。

  定义功能:equal(node)
   判断 lh 为根结点的二叉树与 rh 为根结点的二叉树是否相等

二叉树的相加操作

  对应位置的对应数据元素相加,并返回一棵堆空间上的新二叉树。容器里的数据类型需要支持相加操作。

二叉树的相加操作示例

  定义功能:add(node)
   判断 lh 为根结点的二叉树与 rh 为根结点的二叉树相加

二叉树的线索化操作

  将原本的树转换为双向链表的线索(原本的树没了)
  根据二叉树的遍历次序进行线索化(结点有先后顺序)
    利用左孩子结点指针(left)指向遍历中的前驱结点
    利用右孩子结点指针(right)指向遍历中的后继结点

BTreeNode<T>* connect(LinkQueue<BTreeNode<T>*>& queue)
{
    BTreeNode<T>* ret = NULL;

    if(queue.length() > 0)
    {
        ret = queue.front();//初始首结点
        BTreeNode<T>* slider = ret;

        ret->left = NULL;//首结点无直接前驱
        queue.remove();

        while(queue.length() > 0)
        {

            slider->right = queue.front();//前后连接操作
            queue.front()->left = slider;

            slider = queue.front();//跳转下一个结点
            queue.remove();
        }
    }

    return ret;
}

//线索化操作,将原本的树转换为双向链表的线索(原本的树没了)
BTreeNode<T>* thread(BTTraversal order)
{
    BTreeNode<T>* ret = NULL;

    LinkQueue<BTreeNode<T>*> queue;

    traversal(order,queue);//根据选择的遍历方式进行遍历,遍历结果放入queue中

    ret = connect(queue);//将queue中的结点线索化为双向链表

    this->m_root = NULL;//置为空树
    m_queue.clear();

    return ret;
}

BTree

BTree.h

#ifndef __BTree_H_
#define __BTree_H_


#include "include/GTree.h"
#include "include/BTreeNode.h"
#include "include/Exception.h"
#include "include/LinkQueue.h"
#include "include/Array.h"
#include "include/DynamicArray.h"

#include <iostream>

namespace JYlib
{

/*顺序遍历方式*/
enum BTTraversal
{
    LevelOrder,//层次遍历
    PreOrder,//先序遍历
    InOrder,//中序遍历
    PostOrder//后序遍历
};

/*                  二叉树结构
 *    二叉树类插入的对象的生命周期必须要比树的生命周期长
 * 不然在调用或者析构时都会有问题(尽量不用局部变量)
 *    层次遍历:begin next current end 调用时,需要
 * 先begin,让队列里有元素,才可以使用current
*/
template < typename T >
class BTree : public Tree<T>
{
protected:

    LinkQueue<BTreeNode<T>*> m_queue;//队列

	virtual BTreeNode<T>* find(BTreeNode<T>* node,const T& value)const
	{
		BTreeNode<T>* ret = NULL;

		if(node != NULL)
		{
			if(node->value == value)
			{
				ret = node;
			}
			else
			{
				if(ret == NULL)
				{
					ret = find(node->left,value);
				}
				
				if(ret == NULL)
				{
					ret = find(node->right,value);
				}
			}
		}
		
		return ret;
	}

	virtual BTreeNode<T>* find(BTreeNode<T>* node,BTreeNode<T>* obj)const
	{
		BTreeNode<T>* ret = NULL;

		if(node != NULL)
		{
			if(node == obj)
			{
				ret = node;
			}
			else
			{
				if(ret == NULL)
				{
					ret = find(node->left,obj);
				}

				if(ret == NULL)
				{
					ret = find(node->right,obj);
				}
			}
		}
		
		return ret;
	}

	virtual bool insert(BTreeNode<T>* node,BTreeNode<T>* n_parent,BTNodePos pos)
	{
		bool ret = true;

		if(ANY == pos)
		{
			if(n_parent->left == NULL)
			{
				n_parent->left = node;
			}
			else if(n_parent->right == NULL)
			{
				n_parent->right = node;
			}
			else
			{
				ret = false;
			}
		}
		else if(LEFT == pos)
		{
			if(n_parent->left == NULL)
			{
				n_parent->left = node;
			}
			else
			{
				ret = false;
			}
		}
		else if(RIGHT == pos)
		{
			if(n_parent->right == NULL)
			{
				n_parent->right = node;
			}
			else
			{
				ret = false;
			}
		}
		else
		{
			ret = false;
		}

		return ret;
	}

    virtual void remove(BTreeNode<T>* node,BTree<T>*& ret)
    {
        ret = new BTree<T>();

        if(ret)
        {
            if(root() == node)
            {
                this->m_root = NULL;
            }
            else
            {
                BTreeNode<T>* parent = dynamic_cast<BTreeNode<T>*>(node->parent);
                if(parent->left == node)
                {
                    parent->left = NULL;
                }
                else if(parent->right == node)
                {
                    parent->right = NULL;
                }

                node->parent = NULL;
            }

            ret->m_root = node;//作为新的一棵树返回
        }
        else
        {
            THROW_EXCEPTION(NoEnoughMemoryException,"No memory to create new tree ...");
        }
    }

    virtual void free(BTreeNode<T>* node)
    {
        if(node)
        {
            free(node->left);
            free(node->right);

            if(node->flag() == true)
            {
                //std::cout << "delete  " << node->value << std::endl;
                delete node;
            }
        }
    }

    int count(BTreeNode<T>* node)const
    {
        //左子树与右子树的子结点数量和,再加上当前的(1)
        return (node != NULL) ? (count(node->left) + count(node->right)+1) : 0;
    }

    int height(BTreeNode<T>* node)const
    {
        int ret = 0;

        if(node)
        {
            int l = height(node->left);
            int r = height(node->right);
            //左子树与右子树高度取最大高度,再加上当前的(1)
            ret = (l>r ? l : r) + 1;
        }

        return ret;
    }

    int degree(BTreeNode<T>* node)const
    {
        int ret = 0;

        if(node)
        {
            BTreeNode<T>* child[] = {node->left,node->right};

            ret = !!node->left + !!node->right;

            for(int i=0;(i<2)&&(ret<2);i++)
            {
                int d = degree(child[i]);

                if(ret < d)
                {
                    ret = d;
                }
            }
        }

        return ret;
    }

    //先序遍历
    void preOrderTraversal(BTreeNode<T>* node,LinkQueue<BTreeNode<T>*>& queue)
    {
        if(node)
        {
            queue.add(node);
            preOrderTraversal(node->left,queue);
            preOrderTraversal(node->right,queue);
        }
    }

    //中序遍历
    void inOrderTraversal(BTreeNode<T>* node,LinkQueue<BTreeNode<T>*>& queue)
    {
        if(node)
        {
            inOrderTraversal(node->left,queue);
            queue.add(node);
            inOrderTraversal(node->right,queue);
        }
    }

    //后序遍历
    void postOrderTraversal(BTreeNode<T>* node,LinkQueue<BTreeNode<T>*>& queue)
    {
        if(node)
        {
            postOrderTraversal(node->left,queue);
            postOrderTraversal(node->right,queue);
            queue.add(node);
        }
    }

    //层次遍历
    void levelOrderTraversal(BTreeNode<T>* node,LinkQueue<BTreeNode<T>*>& queue)
    {
        if(node)
        {
            LinkQueue<BTreeNode<T>*> tmp;

            tmp.add(root());
            while(tmp.length() > 0)
            {
                BTreeNode<T>* n = tmp.front();

                if(n->left != NULL)
                {
                    tmp.add(n->left);
                }
                if(n->right != NULL)
                {
                    tmp.add(n->right);
                }

                tmp.remove();
                queue.add(n);
            }
        }
    }

    BTreeNode<T>* clone(BTreeNode<T>* node)const
    {
        BTreeNode<T>* ret = NULL;

        if(node)
        {
            ret = BTreeNode<T>::NewNode();

            if(ret)
            {
                ret->value = node->value;

                ret->left = clone(node->left);
                ret->right = clone(node->right);

                if(ret->left != NULL)
                {
                    ret->left->parent = ret;
                }
                if(ret->right != NULL)
                {
                    ret->right->parent = ret;
                }
            }
            else
            {
                THROW_EXCEPTION(NoEnoughMemoryException,"No memory to create new node ...");
            }
        }

        return ret;
    }

    bool equal(BTreeNode<T>* lt,BTreeNode<T>* rt)
    {
        if(lt == rt)
        {
            return true;
        }
        else if((lt != NULL)&&(rt != NULL))
        {
            return (lt->value == rt->value) && equal(lt->left,rt->left) && equal(lt->right,rt->right);
        }
        else
        {
            return false;
        }
    }

    BTreeNode<T>* add(BTreeNode<T>* lt,BTreeNode<T>* rt)
    {
        BTreeNode<T>* ret = NULL;

        if((lt != NULL)&&(rt != NULL))
        {
            ret = BTreeNode<T>::NewNode();

            if(ret)
            {
                ret->value = lt->value + rt->value;

                ret->left = add(lt->left,rt->left);
                ret->right = add(lt->right,rt->right);

                if(ret->left != NULL)
                {
                    ret->left->parent = ret;
                }
                if(ret->right != NULL)
                {
                    ret->right->parent = ret;
                }
            }
            else
            {
                THROW_EXCEPTION(NoEnoughMemoryException,"No memory to create new node ...");
            }
        }
        else if((lt == NULL)&&(rt != NULL))
        {
            ret = clone(rt);
        }
        else if((lt != NULL)&&(rt == NULL))
        {
            ret = clone(lt);
        }

        return ret;
    }

    void traversal(BTTraversal order,LinkQueue<BTreeNode<T>*>& queue)
    {
        switch(order)
        {
        case PreOrder:
            preOrderTraversal(root(),queue);
            break;
        case InOrder:
            inOrderTraversal(root(),queue);
            break;
        case PostOrder:
            postOrderTraversal(root(),queue);
            break;
        case LevelOrder:
            levelOrderTraversal(root(),queue);
            break;
        default:
            THROW_EXCEPTION(InvalidParameterException,"Parameter order is invalid ...");
            break;
        }
    }

    BTreeNode<T>* connect(LinkQueue<BTreeNode<T>*>& queue)
    {
        BTreeNode<T>* ret = NULL;

        if(queue.length() > 0)
        {
            ret = queue.front();
            BTreeNode<T>* slider = ret;

            ret->left = NULL;
            queue.remove();

            while(queue.length() > 0)
            {

                slider->right = queue.front();//前后连接操作
                queue.front()->left = slider;

                slider = queue.front();//跳转下一个结点
                queue.remove();
            }
        }

        return ret;
    }

public:

	bool insert(TreeNode<T>* node,BTNodePos pos)
	{
		bool ret = true;

		if(node != NULL)
		{
			if(this->m_root == NULL)
			{
				this->m_root = node;
				node->parent = NULL;
			}
			else
			{
				BTreeNode<T>* n_parent = find(node->parent);

				if(n_parent != NULL)
				{
					insert(dynamic_cast<BTreeNode<T>*>(node),n_parent,pos);
				}
				else
				{
					THROW_EXCEPTION(InvalidParameterException,"Invalid parent tree node ...");
				}
			}
		}
		else
		{
			THROW_EXCEPTION(InvalidParameterException,"Parameter node can not be NULL ...");
		}
	
		return ret;
	}

	bool insert(TreeNode<T>* node)
	{
		return insert(node,ANY);
	}

	bool insert(const T& value,TreeNode<T>* parent,BTNodePos pos)
	{
		bool ret = true;

		BTreeNode<T>* new_node = BTreeNode<T>::NewNode();

		if(new_node != NULL)
		{
			new_node->value = value;
			new_node->parent = parent;

			ret = insert(new_node,pos);

            if(ret == false)//插入失败时,删除新节点,防止内存泄漏
			{
				delete new_node;
			}
		}
		else
		{
			THROW_EXCEPTION(NoEnoughMemoryException,"No memory to create new_node ...");
		}
		return ret;
	}

	bool insert(const T& value,TreeNode<T>* parent)
	{
		return insert(value,parent,ANY);
	}

	//返回智能指针类型,函数返回值生命周期只有一条语句,如果没有智能指针接手,就会析构
	SharedPointer< Tree<T> > remove(const T& value)
	{
		BTree<T>* ret = NULL;
		BTreeNode<T>* del_node = find(value);

		if(del_node != NULL)
		{
            remove(del_node,ret);

            m_queue.clear();
		}
		else
		{
			THROW_EXCEPTION(InvalidParameterException,"Can not find the node via parameter value ...");
		}
		
		return ret;
	}

	SharedPointer< Tree<T> > remove(TreeNode<T>* node)
	{
		BTree<T>* ret = NULL;
        BTreeNode<T>* del_node = find(node);

		if(del_node != NULL)
		{
            remove(del_node,ret);

            m_queue.clear();
		}
		else
		{
			THROW_EXCEPTION(InvalidParameterException,"Parameter node is invalid ...");
		}

		return ret;
	}

	BTreeNode<T>* find(const T& value)const
	{
		return find(root(),value);
	}

	BTreeNode<T>* find(TreeNode<T>* node)const
	{
		return find(root(),dynamic_cast<BTreeNode<T>*>(node));
	}

	BTreeNode<T>* root()const
	{
		return dynamic_cast<BTreeNode<T>*>(this->m_root);
	}

	int degree()const 
	{
        return degree(root());
	}

	int count()const
	{
        return count(root());
	}

	int height()const
	{
        return height(root());
	}

    bool begin()
    {
        bool ret = (root() != NULL);

        if(ret)
        {
            m_queue.clear();
            m_queue.add(root());
        }

        return ret;
    }

    bool next()
    {
        bool ret = m_queue.length() > 0;

        if(ret)
        {
            if(m_queue.front()->left != NULL)
            {
                m_queue.add(m_queue.front()->left);
            }
            if(m_queue.front()->right != NULL)
            {
                m_queue.add(m_queue.front()->right);
            }
            m_queue.remove();
        }

        return ret;
    }

    T current()
    {
        if(!end())
        {
            return m_queue.front()->value;
        }
        else
        {
            THROW_EXCEPTION(InvalidOperationException,"No value at current queue ...");
        }
    }

    bool end()
    {
        return (m_queue.length() == 0);
    }

    //顺序遍历访问方式(先序、中序、后序、层次)
    SharedPointer<Array<T>> traversal(BTTraversal order)
    {
        DynamicArray<T>* ret = NULL;
        LinkQueue<BTreeNode<T>*>  queue;

        traversal(order,queue);//根据order选择遍历方式

        ret = new DynamicArray<T>(queue.length());

        if(ret)
        {
            for(int i=0;i<ret->length();i++,queue.remove())
            {
                ret->set(i,queue.front()->value);
            }
        }
        else
        {
            THROW_EXCEPTION(NoEnoughMemoryException,"No memory to create Array ...");
        }

        return ret;
    }

    //线索化操作,将原本的树转换为双向链表的线索(原本的树没了)
    BTreeNode<T>* thread(BTTraversal order)
    {
        BTreeNode<T>* ret = NULL;

        LinkQueue<BTreeNode<T>*> queue;

        traversal(order,queue);

        ret = connect(queue);

        this->m_root = NULL;//置为空树
        m_queue.clear();

        return ret;
    }

    //二叉树克隆
    SharedPointer<BTree<T>> clone()const
    {
        BTree<T>* ret = new BTree();

        if(ret)
        {
           ret->m_root = clone(root());
        }
        else
        {
            THROW_EXCEPTION(NoEnoughMemoryException,"No memory to create new tree ...");
        }

        return ret;
    }

    //二叉树相加
    SharedPointer<BTree<T>> add(const BTree<T>& btree)
    {
        BTree<T>* ret = new BTree<T>();

        if(ret)
        {
            ret->m_root = add(root(),btree.root());
        }
        else
        {
            THROW_EXCEPTION(NoEnoughMemoryException,"No memory to create new tree ...");
        }

        return ret;
    }

    bool operator ==(const BTree<T>& btree)
    {
        return equal(root(),btree.root());
    }

    bool operator !=(const BTree<T>& btree)
    {
        return !(*this == btree);
    }

	void clear() 
	{
        free(root());

        m_queue.clear();
	}

	~BTree()
	{
		clear();
	}

};
	





}



#endif

BTreeNode

BTreeNode.h

#ifndef __BTreeNode_H_
#define __BTreeNode_H_



#include "include/TreeNode.h"


namespace JYlib
{

/*              关于析构
 *    局部变量的生命周期只在局部有用,如果使用局部变量
 * 做了首结点,并且没有主动调用析构函数。等Tree的生命
 * 周期结束时,自动调用析构函数时,局部变量(头结点)生命
 * 已经结束,m_root的地址将为NULL,析构无法执行.
 *    不要使用局部变量作为头结点!
 *    如果非要使用,在确保头结点的生命周期结束前,调用
 * 树的析构函数.
*/

//  添加一种新的数据类型,用来指明二叉树插入的位置
enum BTNodePos
{
	ANY,
	LEFT,
	RIGHT
};

/*
					二叉树结点
孩子兄弟表示法:每个结点都有一个指向孩子一个指向兄弟的指针
通过这种表示法,可以描述任何的树形结构
二叉树由其抽象而来,抽象出每个结点都只有两个孩子,左孩子与右孩子
*/
template < typename T >
class BTreeNode : public TreeNode<T>
{
public:
	BTreeNode<T>* left;
	BTreeNode<T>* right;

	BTreeNode()
	{
		left = NULL;
		right = NULL;
	}

	static BTreeNode<T>* NewNode()
	{
        BTreeNode<T>* ret = new BTreeNode<T>();

		if(ret)
		{
			ret->m_flag = true;
		}

		return ret;
	}


};


}



#endif

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值