二叉树的构造及常用方法

xiaoxiao2021-02-28  86

二叉树

  定义:二叉树是每个节点最多有两个子树的树结构。通常子树被称作“左子树”(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);   } }
转载请注明原文地址: https://www.6miu.com/read-77226.html

最新回复(0)