二叉树的属性操作
1.二叉树结点的数目
对于二叉树结点数目的计算需要用递归来解决,在node为根节点的二叉树中统计结点数目的递归公式如下所示
return 0; node == NULL
count(node)
count(node->left)+count(node->right)+1; node!=NULL;
代码如下:
int count(BTreeNode<T>* node)const
{
if(node == NULL)
{
return 0;
}
else
{
return count(node->l_pointer)+count(node->r_pointer)+1;
}
}
/*
可以简化为
return (node!=NULL)?(count(node->l_pointer)+count(node->r_pointer)+1):0;
*/
2.二叉树的高度
原理上是一样的,二叉树的高度也要用递归来求,获取node为根节点的二叉树的高度的递归公式如下所示,比较左子树和右子树高度的最大值加1就完成了
return 0; node==NULL;
height(node)
Max{height(node->left),height(node->right)}+1; node!=NULL;
代码实现
int height(BTreeNode<T>* node) const
{
if(node == NULL)
{
return 0;
}
else
{
int lh = height(node->l_pointer);
int rh = height(node->r_pointer);
return ((rh>lh)?rh:lh)+1;
}
}
3.树的度数
还是老套路使用递归来求解这个问题,递归公式如下所示
return 0; node == NULL
degree(node)
Max{
degree(node->left),
degree(node->right), node!=NULL
!!node->left + !!node->right
};
代码实现
int degree(BTreeNode<T>* node)const
{
int ld,rd,ret;
if(node == NULL)
{
return 0;
}
else
{
ld = degree(node->l_pointer);
rd = degree(node->r_pointer);
ret = !!node->l_pointer + !!node->r_pointer;
if(ret<ld)
{
ret = ld;
}
if(ret < rd)
{
ret = rd;
}
}
return ret;
}
二叉树的层次遍历
二叉树的遍历是指从根节点出发,按照某种次序依次访问二叉树中的所有结点,使得每个结点有且只有一次被访问,提供一组遍历相关的函数,按层次访问二叉树中的数据元素
算法设计
在二叉树中加入一个队列成员BQueue,该队列用来层次遍历使用
思想:
begin()->将根结点压入队列中
current()->访问队头元素指向的数据元素
next()->队头元素弹出,将队头元素的孩子压入队列中
end()->判断队列是都为空
bool begin()
{
bool ret = (root()!=NULL);
if(ret)
{
BQueue.clear();
BQueue.add(root());
}
return ret;
}
bool next()
{
bool ret = (BQueue.length()>0);
if(ret)
{
BTreeNode<T>* node = BQueue.front();
BQueue.remove();
if(node->l_pointer!=NULL)
{
BQueue.add(node->l_pointer);
}
if(node->r_pointer!=NULL)
{
BQueue.add(node->r_pointer);
}
}
return ret;
}
bool end()
{
return (BQueue.length()==0);
}
T current()
{
if(!end())
{
return BQueue.front()->value;
}
else
{
THROW_EXCEPTION(InvalidParamterException,"no value to read");
}
}
二叉树的其他遍历方式
先序遍历
1.访问根结点中的数据元素
2.先序遍历左子树
3.先序遍历右子树
中序遍历
1.中序遍历左子树
2.访问根结点中的数据元素
3.中序遍历右子树
后序遍历
1.中序遍历左子树
2.中序遍历右子树
3.访问根结点中的数据元素
接口设计
SharedPointer<Array<T>> traversal(BTTraversal order)
1.根据参数order选择执行遍历算法(先序,中序,后序)
2.返回值为堆中的数组对象(生命期由智能指针管理)
3.数组元素的次序反映遍历的先后次序
代码
BTree.h
template <typename T>
class BTree : public Tree<T>
{
private:
void PreOrderTraversal(BTreeNode<T>* node,LinkQueue<BTreeNode<T>*>& q)
{
if(node!=NULL)
{
q.add(node);
PreOrderTraversal(node->l_pointer,q);
PreOrderTraversal(node->r_pointer,q);
}
}
void InOrderTraversal(BTreeNode<T>* node,LinkQueue<BTreeNode<T>*>& q)
{
if(node!=NULL)
{
PreOrderTraversal(node->l_pointer,q);
q.add(node);
PreOrderTraversal(node->r_pointer,q);
}
}
void PostOrderTraversal(BTreeNode<T>* node,LinkQueue<BTreeNode<T>*>& q)
{
if(node!=NULL)
{
PreOrderTraversal(node->l_pointer,q);
PreOrderTraversal(node->r_pointer,q);
q.add(node);
}
}
public:
SharedPointer< Aarry <T> > traversal(BTTraversal order)
{
DynamicArray<T> *ret = NULL;
LinkQueue<BTreeNode<T>*> queue;
switch(order)
{
case PreOrder:
PreOrderTraversal(root(),queue);
break;
case InOrder:
InOrderTraversal(root(),queue);
break;
case PostOrder:
PostOrderTraversal(root(),queue);
break;
default:
THROW_EXCEPTION(InvalidParamterException,"Invaild para");
break;
}
cout<<"the queue's length is"<<queue.length()<<endl;
ret = new DynamicArray<T> (queue.length());
if(ret!=NULL)
{
for(int i =0;i<ret->length();i++,queue.remove())
{
ret->set(i,queue.front()->value);
;
}
}
else
{
THROW_EXCEPTION(NoEnougMemoryException,"no EnoungMemory......");
}
return ret;
}
}
main.c
#include <BTree.h>
int main()
{
BTree<int> bt;
BTreeNode<int>* n = NULL;
bt.insert(1,NULL);
n = bt.find(1);
bt.insert(2,n);
bt.insert(3,n);
n = bt.find(2);
bt.insert(4,n);
bt.insert(5,n);
n = bt.find(4);
bt.insert(8,n);
bt.insert(9,n);
n = bt.find(5);
bt.insert(10,n);
n=bt.find(3);
bt.insert(6,n);
bt.insert(7,n);
SharedPointer < Aarry <int> > sp = bt.traversal(PreOrder);
for(int i =0;i<(*sp).length();i++)
{
cout<<(*sp)[i]<<" ";
}
cout<<endl;
SharedPointer < Aarry <int> > sp1 = bt.traversal(InOrder);
for(int i =0;i<(*sp1).length();i++)
{
cout<<(*sp1)[i]<<" ";
}
cout<<endl;
SharedPointer < Aarry <int> > sp2 = bt.traversal(PostOrder);
for(int i =0;i<(*sp2).length();i++)
{
cout<<(*sp2)[i]<<" ";
}
return 0;
}
结果: