zoukankan      html  css  js  c++  java
  • 二叉树的链式实现

    二叉树的定义见:二叉树实现:公式化描述

    二叉树最常用的描述方法是用链表或指针。每个元素都用一个有两个指针域的节点表示,这两个域为 L e f t C h i l d和R i g h t C h i d。除此两个指针域外,每个节点还有一个 d a t a域。
    二叉树的边可用一个从父节点到子节点的指针来描述。指针放在父节点的指针域中。因为包括个元素的二叉树恰有 n- 1 条边,因此将有2n- (n- 1 ) =n+ 1 个指针域没有值,这些域被置为0。

    节点类:

     1 template<class T>
     2 class BinaryTreeNode
     3 {
     4     friend class BinaryTree<T>;
     5 public:
     6     //构造函数
     7     BinaryTreeNode(){ LeftChild = RightChild = 0; }
     8     BinaryTreeNode(const T& e){ data = e; LeftChild = RightChild = 0; }
     9     BinaryTreeNode(const T& e, BinaryTreeNode *l, BinaryTreeNode *r)
    10     {
    11         data = e;
    12         LeftChild = l;
    13         RightChild = r;
    14     }
    15 private:
    16     T data;
    17     BinaryTreeNode<T> *LeftChild;//左子树
    18     BinaryTreeNode<T> *RightChild;//右子树
    19 };

    二叉树:

     1 template<class T>
     2 class BinaryTree
     3 {
     4 public:
     5     BinaryTree(){ root = NULL;
     6     }
     7 
     8     //复制构造函数
     9     BinaryTree(const BinaryTree<T> &t);
    10     ~BinaryTree(){};
    11     bool IsEmpty() const{ return root == NULL };
    12     bool Root(T& x)const;//获取根节点值
    13     void MakeTree(const T& element, BinaryTree<T>& left, BinaryTree<T>& right);//创建二叉树
    14     void BreakTree(T& element, BinaryTree<T> &left, BinaryTree<T> &right);//分拆二叉树
    15     void PreOrder(void (*Visit)(BinaryTreeNode<T> *u))//前序遍历
    16     {
    17         PreOrder(Visit, root);
    18     }
    19     void InOrder(void(*Visit)(BinaryTreeNode<T> *u))const//中序遍历
    20     {
    21         InOrder(Visit, root);
    22     }
    23     void PostOrder(void(*Visit)(BinaryTreeNode<T> *u))const//后序遍历
    24     {
    25         PostOrder(Visit, root);
    26     }
    27 
    28     BinaryTreeNode<T>* CopyTree(const BinaryTreeNode<T>* t);//复制树
    29 
    30     void LevelOrder(void(*Visit)(BinaryTreeNode<T> *u))const;//层序遍历
        //各种遍历输出
    31 void PreOutput()const; 32 void InOutput()const; 33 void PostOutput()const; 34 void LevelOutput()const; 35 void Delete(); 36 int Height()const//获取树的高度 37 { 38 return Height(root); 39 } 40 41 int Size();//树的节点数 42 private: 43 BinaryTreeNode<T> *root;//根节点 44 void PreOrder(void (*Visit)(BinaryTreeNode<T> *u), BinaryTreeNode<T> *t); 45 void InOrder(void(*Visit)(BinaryTreeNode<T> *u), BinaryTreeNode<T> *t)const; 46 void PostOrder(void(*Visit)(BinaryTreeNode<T> *u), BinaryTreeNode<T> *t)const; 47 int Height(BinaryTreeNode<T> *t)const; 48 49 50 static void output(BinaryTreeNode<T> *t) 51 { 52 std::cout << t->data << ' '; 53 } 54 55 static void freeNode(BinaryTreeNode<T> *t) 56 { 57 delete t; 58 t = NULL; 59 } 60 61 static void ctsize(BinaryTreeNode<T> *t) 62 { 63 ++count; 64 } 65 66 };
      1 template<class T>
      2 BinaryTreeNode<T>* BinaryTree<T>::CopyTree(const BinaryTreeNode<T>* t)
      3 {
      4     if (t)
      5     {
      6         BinaryTreeNode<T>* lchild = CopyTree(t->LeftChild);
      7         BinaryTreeNode<T>* rchild = CopyTree(t->RightChild);
      8         root = new BinaryTreeNode<T>(t->data, lchild, rchild);
      9     }
     10 
     11     return root;
     12 }
     13 
     14 template<class T>
     15 BinaryTree<T>::BinaryTree(const BinaryTree<T> &t)
     16 {
     17     root = CopyTree(t.root);
     18 }
     19 
     20 
     21 
     22 template<class T>
     23 int BinaryTree<T>::Size()
     24 {
     25     count = 0;
     26     PreOrder(ctsize);
     27     return count;
     28 }
     29 
    30 template<class T> 31 int BinaryTree<T>::Height(BinaryTreeNode<T> *t)const 32 { 33 if (!t) 34 { 35 return 0; 36 } 37 38 int ll = Height(t->LeftChild); 39 int lr = Height(t->RightChild); 40 41 if (ll > lr) 42 { 43 return ++ll; 44 } 45 else 46 return ++lr; 47 } 48 49 template<class T> 50 bool BinaryTree<T>::Root(T& x) const 51 { 52 if (root) 53 { 54 x = root->data; 55 return true; 56 } 57 return false; 58 } 59
    //当left和right以及this二叉树有重复时,利用拷贝构造函数复制一部分,以免左右子树指向同一个而引发错误 60 template<class T> 61 void BinaryTree<T>::MakeTree(const T& element, BinaryTree<T>& left, BinaryTree<T>& right) 62 { 63 if (&left==&right&&this==&left) 64 { 65 BinaryTree<T> newTree = right; 66 BinaryTree<T> newTree2 = left; 67 root = new BinaryTreeNode<T>(element, newTree2.root, newTree.root); 68 } 69 else if (&left==&right) 70 { 71 BinaryTree<T> newTree = right; 72 root = new BinaryTreeNode<T>(element, left.root, newTree.root); 73 } 74 else if (this==&left||this==&right) 75 { 76 BinaryTree<T> newTree = *this; 77 root = new BinaryTreeNode<T>(element, left.root, newTree.root); 78 } 79 else 80 root = new BinaryTreeNode<T>(element, left.root, right.root); 81 82 left.root = right.root = NULL; 83 } 84 85 template<class T> 86 void BinaryTree<T>::BreakTree(T& element, BinaryTree<T> &left, BinaryTree<T> &right) 87 { 88 if (root==NULL) 89 { 90 std::cerr << "树为空,不能拆分" << std::endl; 91 return; 92 } 93 94 BinaryTree<T> newTree = *this; 95 element = newTree.root->data; 96 left.root = newTree.root->LeftChild; 97 right.root = newTree.root->RightChild; 98 99 delete root; 100 root = NULL; 101 } 102 103 template<class T> 104 void BinaryTree<T>::PreOrder(void(*Visit)(BinaryTreeNode<T> *u), BinaryTreeNode<T> *t) 105 { 106 if (t) 107 { 108 Visit(t); 109 PreOrder(Visit, t->LeftChild); 110 PreOrder(Visit, t->RightChild); 111 } 112 } 113 114 template<class T> 115 void BinaryTree<T>::InOrder(void(*Visit)(BinaryTreeNode<T> *u), BinaryTreeNode<T> *t)const 116 { 117 if (t) 118 { 119 InOrder(Visit, t->LeftChild); 120 Visit(t); 121 InOrder(Visit, t->RightChild); 122 } 123 } 124 125 template<class T> 126 void BinaryTree<T>::PostOrder(void(*Visit)(BinaryTreeNode<T> *u), BinaryTreeNode<T> *t)const 127 { 128 if (t) 129 { 130 PostOrder(Visit, t->LeftChild); 131 PostOrder(Visit, t->RightChild); 132 Visit(t); 133 } 134 } 135 136 template<class T> 137 void BinaryTree<T>::LevelOrder(void(*Visit)(BinaryTreeNode<T> *u))const 138 { 139 LinkedQueue<T> Q; 140 BinaryTreeNode<T> *t = root; 141 while (t) 142 { 143 Visit(t); 144 if (t->LeftChild) 145 { 146 Q.Add(t->LeftChild); 147 } 148 if (t->RightChild) 149 { 150 Q.Add(t->RightChild); 151 } 152 153 if (Q.IsEmpty()) 154 { 155 return; 156 } 157 Q.Delete(t); 158 } 159 } 160 161 template<class T> 162 void BinaryTree<T>::PreOutput()const 163 { 164 PreOrder(output, root); 165 } 166 167 template<class T> 168 void BinaryTree<T>::InOutput()const 169 { 170 InOrder(output, root); 171 } 172 173 template<class T> 174 void BinaryTree<T>::PostOutput()const 175 { 176 PostOrder(output, root); 177 } 178 179 template<class T> 180 void BinaryTree<T>::LevelOutput()const 181 { 182 LevelOutput(output, root); 183 } 184 185 template<class T> 186 void BinaryTree<T>::Delete() 187 { 188 PostOrder(freeNode, root); 189 root = NULL; 190 }

     几个操作的解释:

    前三种遍历可以用递归完成,层次调用则利用队列

    删除:

    要删除一棵二叉树,需要删除其所有节点。可以通过后序遍历在访问一个节点时,把其删除。也就是说先删除左子树,然后右子树,最后删除根。

    计算高度:

    通过进行后序遍历,可以得到二叉树的高度。首先得到左子树的高度 h l,然后得到右子树的高度h r。此时,树的高度为:m a x { h l, hr} + 1


    简单测试:

     1 #include<iostream>
     2 #include "binaryTree.h"
     3 
     4 int countx = 0;
     5 BinaryTree<int> a, x, y, z;
     6 
     7 template<class T>
     8 void ct(BinaryTreeNode<T> *t)
     9 {
    10     ++countx;
    11 }
    12 
    13 void main(void)
    14 {
    15     y.MakeTree(1, a, a);
    16     z.MakeTree(2, y, y);
    17     x.MakeTree(3, y, z);
    18     y.MakeTree(4, x, a);
    19     y.PreOrder(ct);
    20     
    21     std::cout << countx << std::endl;
    22     std::cout << y.Height() << std::endl;
    23     std::cout << y.Size() << std::endl;
    24     y.Delete();
    25     std::cout << y.Height() << std::endl;
    26     std::cout << y.Size() << std::endl;    
    27 }

  • 相关阅读:
    Quartus 自定义一个IP核,通过AXI总线被HPS系统控制(未完待续)
    IR 发送数据的上升沿和下降沿的判断(边沿检测)
    机器学习特征工程和优化方法
    最大期望算法(EM)
    主题模型(Topic Model)
    马尔科夫(Markov)
    【mysql-02-2】使用文档-建表约束
    【mysql-02-3】使用文档-范式
    【mysql-02-1】使用文档-基本语法
    Linux身份鉴别机制原理
  • 原文地址:https://www.cnblogs.com/haoliuhust/p/4321755.html
Copyright © 2011-2022 走看看