天天看点

二叉树的创建与相关操作

二叉树的创建与相关操作

1、二叉树:是每个节点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。

如图:

二叉树的创建与相关操作

2、二叉树的每个结点至多只有二棵子树(不存在度大于2的结点),二叉树的子树有左右之分,次序不能颠倒。

3、二叉树的第i层至多有2^(i-1)个结点;深度为k的二叉树至多有2^k-1个结点;对任何一棵二叉树T,如果其终端结点数为n0,度为2的结点数为n2,则n0=n2+1。

4、一棵深度为k,且有2^k-1个节点称之为​​满二叉树​​​(如上图);深度为k,有n个节点的二叉树,当且仅当其每一个节点都与深度为k的满二叉树中,序号为1至n的节点对应时,称之为​​完全二叉树​​。

如下图:

二叉树的创建与相关操作

一、创建二叉树

假设我们要创建一个二叉树:

二叉树的创建与相关操作

对应数组为:char array[] = "abc##d##ef##g";

这是因为以下程序中设置无效值为‘#’,在递归的过程中,遇到无效值则置为NULL。

代码如下:

// 根+左子树+右子树 
  PNode _CreateBinTree(const T* array, size_t size, size_t& index, const T& invalid)
  {
    if (NULL == array)
      return 0;
    PNode root = NULL;
    if (index < size && array[index] != invalid)
    {
      root = new Node(array[index]);
      root->_left = _CreateBinTree( array, size, ++index, invalid);
      root->_right = _CreateBinTree( array, size, ++index, invalid);
    }
    return root;
  }      

在判断语句中,最好将index<size放在前面,因为当越界后根本不需要判断是否为有效值。

二、前中后遍历二叉树

前序遍历:首先访问根,再遍历左子树,最后遍历右子树

// 根--->根的左子树---->根的右子树
  void _PreOrder(PNode& pRoot)
  {
    if (pRoot == NULL)
      return;
    cout << pRoot->_data << " ";
    _PreOrder(pRoot->_left);
    _PreOrder(pRoot->_right);
  }      

中序遍历:首先遍历左子树,再访问根,最后遍历右子树。

// 左子树--->根节点--->右子树 
  void _InOrder(PNode pRoot)
  {
    //pNode pCur = pRoot;
    if (pRoot == NULL)
      return;
    _InOrder(pRoot->_left);
    cout << pRoot->_data << " ";
    _InOrder(pRoot->_right);
  }      

后序遍历:首先遍历左子树,再遍历右子树,最后访问根。

// 左子树--->右子树--->根节点 
  void _PostOrder(PNode pRoot)
  {
    if (pRoot == NULL)
      return;
    _PostOrder(pRoot->_left);
    _PostOrder(pRoot->_right);
    cout << pRoot->_data << " "; 
  }      

三、层序遍历二叉树

按照层次访问,访问根,访问子女,再访问子女的子女。

这里递归很难实现,我们利用了队列的特性,创建一个队列,先将根节点入队,将队头的数据打印并出队,再看左右节点,如果左节点不为空,将左节点入队,如果右节点不为空,将右节点入队。

代码如下:

void _LeverOrder(PNode pRoot)
  {
    if (NULL == pRoot)
      return;
    queue<PNode> q;
    q.push(pRoot);
    while (!q.empty())
    {
      PNode front = q.front();
      cout << front->_data << " ";
      q.pop();

      if (front->_left)
        q.push(front->_left);
      if (front->_right)
        q.push(front->_right);
    }
  }      

四、求二叉树的高度

先求出左子树的高度,和右子树比较。

size_t _Height(PNode pRoot)
  {
    if (NULL == pRoot)
      return 0;
    return 1+(_Height(pRoot->_left) > _Height(pRoot->_right)?_Height(pRoot->_left): _Height(pRoot->_right));
  }      

五、求二叉树中节点的个数

size_t _Size(PNode pRoot)
  {
    if (NULL == pRoot)
      return 0;
    return _Size(pRoot->_left) + _Size(pRoot->_right) + 1;
  }      

六、求叶子节点的个数

size_t _GetLeafCount(PNode pRoot)
  {
    if (NULL == pRoot)
      return 0;
    if (pRoot->_left == NULL&&pRoot->_right == NULL)
      return 1;
    return _GetLeafCount(pRoot->_left) + _GetLeafCount(pRoot->_right);
  }      

七、求二叉树中第k层节点的个数

size_t _GetKLevelCount(PNode pRoot, int K)
  {
    if (NULL == pRoot || K < 1)
      return 0;
    if (K == 1)
      return 1;
    int leftLevel = _GetKLevelCount(pRoot->_left, K - 1);
    int rightLevel = _GetKLevelCount(pRoot->_right, K - 1);
    return leftLevel + rightLevel;
  }      

八、求一个节点的双亲节点,及左、右孩子节点。

PNode _Parent(PNode pRoot, PNode pNode)
  {
    if (pNode == pRoot->_left || pNode == pRoot->_right)
      return pRoot;
    if (pRoot->_left)
    {
      _Parent(pRoot->_left, pNode);
    }
    if (pRoot->_right)
    {
      _Parent(pRoot->_right, pNode);
    }
    return pRoot;
  }      
PNode LeftChild(PNode pNode)
  {
    if (NULL == pNode)
      return NULL;
    return pNode->_left;
  }

  PNode RightChild(PNode pNode)
  {
    if (NULL == pNode)
      return NULL;
    return pNode->_right;
  }      

还有一些辅助函数,比如寻找某一元素所在节点。

整体代码如下:

#include<iostream>
using namespace std;
#include<queue>
#include<string.h>

template<class T>
struct TreeNode
{
  T _data;
  TreeNode *_left;
  TreeNode *_right;
  TreeNode(const T& data)
    :_data(data)
    , _left(NULL)
    , _right(NULL)
  {}
};

template<class T>
class BinTree
{
  typedef TreeNode<T> Node;
  typedef TreeNode<T> *PNode;
public:
  BinTree()
    : _pRoot(NULL)
  {}

  BinTree(const T* array, size_t size, const T& invalid)
  {
    size_t index = 0;
    _pRoot = _CreateBinTree(array, size, index, invalid);
  }

  BinTree(const BinTree& bt)
  {
    _pRoot = _CopyBinTree(bt._pRoot);
  }

  BinTree& operator=(const BinTree& bt)
  {
    if (this == bt)
      return;
    _DestroyBinTree(_pRoot);
    _pRoot = new Node(bt->_data);
    _pRoot->_left = bt->_left;
    _pRoot->_right = bt->_right;
  }

  ~BinTree()
  {
    _DestroyBinTree(_pRoot);
  }
  void PreOrder()
  {
    _PreOrder(_pRoot);
    cout << endl;
  }

  void InOrder()
  {
    _InOrder(_pRoot);
    cout << endl;
  }

  void PostOrder()
  {
    _PostOrder(_pRoot);
    cout << endl;
  }

  void LevelOrder()
  {
    _LeverOrder(_pRoot);
    cout << endl;
  }

  size_t Size()
  {
    return _Size(_pRoot);
  }

  size_t GetLeafCount()
  {
    return _GetLeafCount(_pRoot);
  }

  // 获取第K层结点的个数 
  size_t GetKLevelCount(size_t K)
  {
    return _GetKLevelCount(_pRoot, K);
  }

  size_t Height()
  {
    return _Height(_pRoot);
  }

  PNode Find(const T& data)
  {
    return _Find(_pRoot, data);
  }

  PNode Parent(PNode pNode)
  {
    return _Parent(_pRoot, pNode);
  }

  PNode LeftChild(PNode pNode)
  {
    if (NULL == pNode)
      return NULL;
    return pNode->_left;
  }

  PNode RightChild(PNode pNode)
  {
    if (NULL == pNode)
      return NULL;
    return pNode->_right;
  }
private:
  // 根+左子树+右子树 
  PNode _CreateBinTree(const T* array, size_t size, size_t& index, const T& invalid)
  {
    if (NULL == array)
      return 0;
    PNode root = NULL;
    if (index < size && array[index] != invalid)
    {
      root = new Node(array[index]);
      root->_left = _CreateBinTree( array, size, ++index, invalid);
      root->_right = _CreateBinTree( array, size, ++index, invalid);
    }
    return root;
  }

  PNode _CopyBinTree(PNode pRoot)
  {
    if (this == pRoot)
      return;
    if (pRoot)
    {
      _pRoot = new Node(pRoot->_data);
      _pRoot->_left = _CopyBinTree(pRoot->_left);
      _pRoot->_right = _CopyBinTree(pRoot->_right);
    }
    return *this;
  }

  void _DestroyBinTree(PNode pRoot)
  {
    if (NULL == pRoot)
      return;
    if (pRoot)
    {
      _Destroy(pRoot->_left);
      _Destroy(pRoot->_right);
      delete pRoot;
      pRoot = NULL;
    }
  }

  // 根--->根的左子树---->根的右子树
  void _PreOrder(PNode& pRoot)
  {
    if (pRoot == NULL)
      return;
    cout << pRoot->_data << " ";
    _PreOrder(pRoot->_left);
    _PreOrder(pRoot->_right);
  }

  // 左子树--->根节点--->右子树 
  void _InOrder(PNode pRoot)
  {
    //pNode pCur = pRoot;
    if (pRoot == NULL)
      return;
    _InOrder(pRoot->_left);
    cout << pRoot->_data << " ";
    _InOrder(pRoot->_right);
  }

  // 左子树--->右子树--->根节点 
  void _PostOrder(PNode pRoot)
  {
    if (pRoot == NULL)
      return;
    _PostOrder(pRoot->_left);
    _PostOrder(pRoot->_right);
    cout << pRoot->_data << " "; 
  }

  //层次遍历
  void _LeverOrder(PNode pRoot)
  {
    if (NULL == pRoot)
      return;
    queue<PNode> q;
    q.push(pRoot);
    while (!q.empty())
    {
      PNode front = q.front();
      cout << front->_data << " ";
      q.pop();

      if (front->_left)
        q.push(front->_left);
      if (front->_right)
        q.push(front->_right);
    }
  }

  size_t _Size(PNode pRoot)
  {
    if (NULL == pRoot)
      return 0;
    return _Size(pRoot->_left) + _Size(pRoot->_right) + 1;
  }

  size_t _GetLeafCount(PNode pRoot)
  {
    if (NULL == pRoot)
      return 0;
    if (pRoot->_left == NULL&&pRoot->_right == NULL)
      return 1;
    return _GetLeafCount(pRoot->_left) + _GetLeafCount(pRoot->_right);
  }

  size_t _Height(PNode pRoot)
  {
    if (NULL == pRoot)
      return 0;
    return 1+(_Height(pRoot->_left) > _Height(pRoot->_right)?_Height(pRoot->_left): _Height(pRoot->_right));
  }

  PNode _Find(PNode pRoot, const T& data)
  {
    if (data == pRoot->_data)
      return pRoot;
    if (pRoot->_left)
    {
      _Find(pRoot->_left, data);
    }
    if (pRoot->_right)
    {
      _Find(pRoot->_right, data);
    }
  }

  PNode _Parent(PNode pRoot, PNode pNode)
  {
    if (pNode == pRoot->_left || pNode == pRoot->_right)
      return pRoot;
    if (pRoot->_left)
    {
      _Parent(pRoot->_left, pNode);
    }
    if (pRoot->_right)
    {
      _Parent(pRoot->_right, pNode);
    }
    return pRoot;
  }

  size_t _GetKLevelCount(PNode pRoot, int K)
  {
    if (NULL == pRoot || K < 1)
      return 0;
    if (K == 1)
      return 1;
    int leftLevel = _GetKLevelCount(pRoot->_left, K - 1);
    int rightLevel = _GetKLevelCount(pRoot->_right, K - 1);
    return leftLevel + rightLevel;
  }

private:
  PNode _pRoot;
};      

测试,传文章开头所示的数组,如下:

int main()
{
    char array[] = "abc##d##ef##g";
    BinTree<char> bt(array,strlen(array),'#');

    cout << bt.GetKLevelCount(2) << endl;

    cout << bt.GetLeafCount() << endl;

    cout << bt.Height() << endl;

    bt.PreOrder();
    bt.InOrder();
    bt.PostOrder();
    bt.LevelOrder();

    cout << bt.LeftChild(bt.Find('a'))->_data << endl;
    cout << bt.RightChild(bt.Find('a'))->_data << endl;

    cout << bt.Parent(bt.Find('b'))->_data << endl;

    cout << bt.Size() << endl;

    system("pause");
    return 0;
}      

结果如下:

继续阅读