二叉树的构造及常用方法

来源:互联网 发布:宜宾市行知中学周圣川 编辑:程序博客网 时间:2024/06/06 02:11

二叉树

  定义:二叉树是每个节点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。二叉树常被用于实现二叉查找树和二叉堆。


        特点:二叉树的每个结点至多只有二棵子树(不存在度大于2的结点),二叉树的子树有左右之分,次序不能颠倒。二叉树的第i层至多有2^(i-1)个结点;深度为k的二叉树至多有2^k-1个结点;对任何一棵二叉树,如果其终端结点(即叶子节点)数为n0,度为2的结点数为n2,则n0=n2+1。


满二叉树:一个二叉树,如果每一个层的结点数都达到最大值,即节点总数为2^k-1
完全二叉树:若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边


template<class T> //创建节点
struct BinaryTreeNode
{
public:
   BinaryTreeNode(const T& value)
  :_value(value)
  ,_pLeft(NULL)
  ,_pRight(NULL)
   {}
T _value;
BinaryTreeNode<T>* _pLeft;
BinaryTreeNode<T>* _pRight;
};


template<class T> // 创建二叉树、二叉树的基本函数
class BinaryTree
{
public:
typedef BinaryTreeNode<T> Node;
BinaryTree() //构造函数
:_pRoot(NULL)
{}
BinaryTree(const T array[],size_t size,const T& invalid)
{
  size_t index=0;
  _CreateBinaryTree(_pRoot,array,size,index,invalid);
}
BinaryTree(const BinaryTree<T>& bt) //拷贝构造函数
{
cout<<endl<<"CopyBinaryTree"<<endl;
  _pRoot=_CopyBinaryTree(bt._pRoot);
}
BinaryTree& operator=(const BinaryTree<T>& bt) //赋值运算符重载
{
  if(this!=&bt)
  {
     _DestroyBinaryTree(_pRoot);
 _pRoot=_CopyBinaryTree(bt._pRoot);
  }
  return *this;
}
~BinaryTree() //析构函数
{
   _DestroyBinaryTree(_pRoot);
}

void _CreateBinaryTree(Node* &pRoot,const T array[],size_t size,size_t & index,const T& invalid) //构造二叉树
{
if(index<size && array[index]!=invalid) // 得到的字符为无效值时,不处理
{
  pRoot=new Node(array[index]);
  _CreateBinaryTree(pRoot->_pLeft,array,size,++index,invalid);
  _CreateBinaryTree(pRoot->_pRight,array,size,++index,invalid);
}
}
Node* _CopyBinaryTree(Node* pRoot) //拷贝二叉树
{
  Node* pNewNode=NULL; 
  if(pRoot)
  {
         pNewNode=new Node(pRoot->_value); 
 pNewNode->_pLeft=_CopyBinaryTree(pRoot->_pLeft);
 pNewNode->_pRight=_CopyBinaryTree(pRoot->_pRight);
  }
  return pNewNode; //返回根节点
}
    void _DestroyBinaryTree(Node*& pRoot) //销毁二叉树
{
  if(pRoot)
  {
  _DestroyBinaryTree(pRoot->_pLeft);
  _DestroyBinaryTree(pRoot->_pRight); //先销毁左右子树
  delete pRoot; //再销毁根节点
  pRoot=NULL;  //根节点置空 
  }
}

//二叉树的基本构造就完成了

——二叉树的常见操作
//前序遍历
public:
void PerOrder() 
{
 cout<<"PerOrder:";
  _PerOrder(_pRoot);
  cout<<endl;
}
private:
void _PerOrder(Node* pRoot) 
{
  if(pRoot)
  {
  cout<<pRoot->_value<<" ";  //访问根节点
          _PerOrder(pRoot->_pLeft);  //再左子树
 _PerOrder(pRoot->_pRight); //再右子树
  }
}
//中序遍历

void _InOrder(Node* pRoot)
{
  if(pRoot)
  {
     _InOrder(pRoot->_pLeft);
 cout<<pRoot->_value<<" ";
 _InOrder(pRoot->_pRight);
  }
}

//后序遍历

void _PostOrder(Node* pRoot)
{
  if(pRoot)
  {
     _PostOrder(pRoot->_pLeft);
 _PostOrder(pRoot->_pRight);
 cout<<pRoot->_value<<" ";
  }
}

—三种遍历的基本方法都相同,只访问的顺序不一样—  
——这三种遍历方式均为递归遍历

//找特定值的节点
public:
Node* Find(const T& value) //包装Find方法
{
  return _Find(_pRoot,value);
}
private:
Node* _Find(Node* pRoot,const T& value) 
{
  if(NULL==pRoot)  //树空---NULL
  return NULL;
  if(pRoot->_value == value)   //根节点就是要找的节点
     return pRoot;
  Node* pCur=NULL;
  if(pCur=_Find(pRoot->_pLeft,value))  //左子树中找
  return pCur;
  if(_Find(pRoot->_pRight,value))  //右子树中找
    return pCur;  //返回pCur
}
//找某个节点的父节点
public:
Node* Find(const T& value)
{
  return _Find(_pRoot,value);
}
private:
Node* _Find(Node* pRoot,const T& value)
{
  if(NULL==pRoot)  //树空
  return NULL;
  if(pRoot->_value == value)  
  return pRoot;
  Node* pCur=NULL;
  if(pCur=_Find(pRoot->_pLeft,value))
  return pCur;
  if(_Find(pRoot->_pRight,value))
  return pCur;
}
//树的高度
 size_t _Height(Node* pRoot)// NULL -> 0     一个节点->1     多个节点->左、右子树
{
   if(NULL==pRoot)
return 0;
if(NULL==pRoot->_pLeft && NULL==pRoot->_pRight)
return 1;
size_t LeftHeight=_Height(pRoot->_pLeft);
size_t RightHeight=_Height(pRoot->_pRight);
return (LeftHeight>RightHeight)? LeftHeight+1:RightHeight+1;
}
//叶子节点的个数
size_t _GetLeefCount(Node* pRoot)
{
   if(NULL==pRoot)
return 0;
if(NULL==pRoot->_pLeft && NULL==pRoot->_pRight)
return 1;
size_t LeftLeefCount=_GetLeefCount(pRoot->_pLeft);
size_t RightLeefCount=_GetLeefCount(pRoot->_pRight);
return LeftLeefCount+RightLeefCount;
}

//第K层叶子节点的个数
size_t _GetKLevelCount(Node* pRoot,size_t k)
{
  if(NULL==pRoot || k<1)
  return 0;
  if(1==k)
  return 1;
  return _GetKLevelCount(pRoot->_pLeft,k-1)+_GetKLevelCount(pRoot->_pRight,k-1); 
                                                              //左子树上K-1层叶子节点的个数+右子树上K-1层叶子节点的个数
}

//二叉树的镜像树-------左右子树颠倒
void _BinaryMirror(Node* pRoot)
{
  if(pRoot)
  {
  std::swap(pRoot->_pLeft,pRoot->_pRight);  //交换左右子树
  _BinaryMirror(pRoot->_pLeft);   //对左子树进行镜像处理
  _BinaryMirror(pRoot->_pRight);  //对右子树进行镜像处理
  }
}
——非递归的三种遍历方式

//前序遍历
  void PerOrder_Nor()
{
cout<<"PerOrder_Nor:"<<" ";
  if(NULL==_pRoot)
  return;
  stack<Node*> s;
  s.push(_pRoot);
  while(!s.empty())
  {
     Node* pTop=s.top();
 cout<<pTop->_value<<" ";
 s.pop();
 if(pTop->_pRight)
 s.push(pTop->_pRight);
 if(pTop->_pLeft)
 s.push(pTop->_pLeft);
  }
  cout<<endl;
}

//中序遍历
void InOrder_Nor()
{
cout<<"InOrder_Nor:"<<" ";
 if(NULL == _pRoot)
 return;
 stack<Node*> s;
 Node* pCur=_pRoot;
 while(pCur || !s.empty())
 {
    while(pCur)
{
   s.push(pCur);
pCur=pCur->_pLeft;
}
pCur=s.top();
cout<<pCur->_value<<" ";
s.pop();
pCur=pCur->_pRight;
 }
 cout<<endl;
}

//后序遍历
void PostOrder_Nor()
{
cout<<"PostOrder_Nor:"<<" ";
  if(NULL == _pRoot)
  return;
  stack<Node*> s;
  Node* pCur=_pRoot;
  Node* prev=NULL;


  while(pCur || !s.empty())
  {
     while(pCur)
 {
    s.push(pCur);
pCur=pCur->_pLeft;
 }
 Node* pTop=s.top();
 if(NULL == pTop->_pRight || pTop->_pRight==prev)
 {
 cout<<pTop->_value<<" ";
 prev=pTop;
 s.pop();
 }
 else
 pCur=pTop->_pRight;
  }
}

ok,就这样,完成了










void _InOrder(Node* pRoot)
{
  if(pRoot)


  {
     _InOrder(pRoot->_pLeft);
 cout<<pRoot->_value<<" ";
 _InOrder(pRoot->_pRight);
  }
}


0 0
原创粉丝点击