zoukankan      html  css  js  c++  java
  • 二叉查找树_前序遍历_中序_后序_递归与非递归写法_层次遍历_以及树形显示

      1 #include <iostream>
      2 #include <stack>
      3 using namespace std;
      4 
      5 template<typename T>
      6 struct BinaryNode
      7 {
      8     T element;
      9     BinaryNode<T> *left;
     10     BinaryNode<T> *right;
     11 
     12     BinaryNode(const T &theElement, BinaryNode *lt, BinaryNode *rt)
     13         : element(theElement), left(lt), right(rt) {}
     14 };
     15 
     16 
     17 template<typename T>
     18 class BinarySearchTree
     19 {
     20 public:
     21     BinarySearchTree() {
     22         root = nullptr;
     23     }
     24     BinarySearchTree(const BinarySearchTree& rhs) {  //复制构造函数
     25         root = clone(rhs.root);
     26     }
     27     ~BinarySearchTree();
     28 
     29     const T &findMin() const {
     30         return findMin(root)->element;
     31     }
     32     const T &findMax() const {
     33         return findMax(root)->element;
     34     }
     35     
     36     bool contains(const T& x) const;
     37     T& getNode(const T& e) {                        //得到元素为e的结点 
     38         return getNode(e, root)->element;
     39     }
     40     
     41     bool isEmpty() const {
     42         if (root == nullptr)
     43             return true;
     44         return false;
     45     }
     46     void PreprintTree() const {
     47         PreprintTree(root);
     48     }
     49     
     50     void InprintTree() const {
     51         InprintTree(root);
     52     }
     53     
     54     void PostprintTree() const {
     55         PostprintTree(root);
     56     }
     57     
     58     void LevelprintTree() const {
     59         LevelprintTree(root);
     60     }
     61     
     62     void PreprintTree_N() const {
     63         PreprintTree_N(root); 
     64     }
     65     
     66     void InprintTree_N() const {
     67         InprintTree_N(root);
     68     }
     69     
     70     void PostprintTree_N() const {
     71         PostprintTree_N(root);
     72     }
     73     
     74     void DisplayTreeShape(int level = 1) const {
     75         DisplayTreeShape(root, level);
     76     }
     77 
     78     void makeEmpty();
     79     void insert(const T &x);
     80     void remove(const T &x);
     81     int Depth(); 
     82     int CountLeaf() {
     83         BinaryNode<T> *p = root;
     84         int count = 0;
     85         CountLeaf(p, count);
     86         return count;
     87     }
     88     
     89     const BinarySearchTree& operator = (const BinarySearchTree& rhs);
     90 
     91 private:
     92 
     93     BinaryNode<T> *root;                      //指向树根结点的指针
     94 
     95     void insert(const T & x, BinaryNode<T> * & t);  
     96     void remove(const T & x, BinaryNode<T> * & t);
     97     BinaryNode<T> * findMin(BinaryNode<T> *t) const;
     98     BinaryNode<T> * findMax(BinaryNode<T> *t ) const;
     99     
    100     bool contains(const T & x, BinaryNode<T> *t) const;
    101     BinaryNode<T> * getNode(const T &x, BinaryNode<T> *t);
    102     
    103     void makeEmpty( BinaryNode<T> * & t );                  
    104     //利用 递归 算法 计算树的 深度 
    105     int Depth( BinaryNode<T> * t, int level, int &depth);
    106     //利用 递归 算法 计算树的 高度
    107     void CountLeaf(BinaryNode<T> * t, int &count);
    108     
    109         
    110     void PreprintTree( BinaryNode<T> * t ) const;           //先序遍历 
    111     void InprintTree( BinaryNode<T> *t ) const;             //中序遍历   
    112     void PostprintTree( BinaryNode<T> * t ) const;          //后序遍历
    113     void LevelprintTree( BinaryNode<T> * t) const;          //层次遍历 
    114     
    115     void PreprintTree_N( BinaryNode<T> * t) const;          //非递归先序遍历
    116     void InprintTree_N( BinaryNode<T> * t) const;           //非递归中序遍历二叉树 
    117     void PostprintTree_N( BinaryNode<T> * t) const;         //非递归后序遍历二叉树 
    118     void DisplayTreeShape(BinaryNode<T> *bt, int level) const;    //二叉树的树形显示算法 
    119     
    120       
    121     BinaryNode<T> * clone( BinaryNode<T> * t ) const;
    122 };
    123 
    124 template<typename T>
    125 bool BinarySearchTree<T>::contains(const T& x) const
    126 {
    127     return contains(x, root);
    128 }
    129 
    130 template<typename T>
    131 bool BinarySearchTree<T>::contains(const T & x, BinaryNode<T> *t) const
    132 {
    133     if (t == nullptr)
    134         return false;
    135     else if (x < t->element)          // x 小, 说明应该在左边找
    136         return contains(x, t->left);
    137     else if (t->element < x)          // x 大, 说明应该在右面找
    138         return contains(x, t->right);
    139     else 
    140         return true;
    141 }
    142 
    143 template<typename T>
    144 BinaryNode<T>* BinarySearchTree<T>::getNode(const T & x, BinaryNode<T> *t)
    145 {
    146     if (t == nullptr) 
    147         return nullptr;
    148     else if (x < t->element)
    149         return getNode(x, t->left);
    150     else if (t->element < x)
    151         return getNode(x, t->right);
    152     return t;
    153 }
    154 
    155 
    156 //findMin--返回指向树中包含最小元的结点的指针
    157 template<typename T>
    158 BinaryNode<T> * BinarySearchTree<T>::findMin(BinaryNode<T> *t) const
    159 {
    160     if (t == nullptr)
    161         return  nullptr;
    162     if (t->left == nullptr)
    163         return t;
    164     return findMin(t->left);
    165 }
    166 
    167 template<typename T>
    168 BinaryNode<T>* BinarySearchTree<T>::findMax(BinaryNode<T> *t) const
    169 {
    170     if (t != nullptr)
    171         while (t->right != nullptr) {
    172             t = t->right;
    173         }
    174     return t;
    175 }
    176 
    177 template<typename T>
    178 void BinarySearchTree<T>::insert(const T &x)
    179 {
    180     insert(x, root);
    181 }
    182 
    183 /************************************************************************/
    184 /* x is the item to insert        */
    185 /* t is the node that roots the subtree*/
    186 /* Set the new root of the subtree*/
    187 ///* 只有当一个新树叶生成时候,t才改变.
    188 ///* t 是到p->left或p->right的引用.==> 意味着p->left或p->right将会改变为指向新结点.
    189 /************************************************************************/
    190 template<typename T>
    191 void BinarySearchTree<T>::insert(const T & x, BinaryNode<T> * & t)
    192 {
    193     if (t == nullptr)         //没有结点,在该位置处添加新结点
    194         t = new BinaryNode<T>(x, nullptr, nullptr);
    195     else if (x < t->element)  //x 小, 在左子树查询
    196         insert(x, t->left);  
    197     else if (t->element < x)  //x 大, 在右子树查询
    198         insert(x, t->right);
    199     else;                     //Duplicate, do nothing;
    200 }
    201 
    202 template<typename T>
    203 void BinarySearchTree<T>::remove(const T &x)
    204 {
    205     remove(x, root);
    206 }
    207 
    208 /************************************************************************/
    209 /* x is item to remove                                                  */
    210 /* t is the node that roots the subtree                                 */
    211 /* Set the new root of the subtree                                      */
    212 /* 1.结点是一片树叶时 -- 可被立即删除*/
    213 /* 2.结点有一个儿子, 则该结点可以在其父节点调整他的链 以绕过该结点后被删除 */
    214 /* 3.结点有两个儿子, 则其右子树的最小数据代替该结点的数据,并递归删除那个结点 */
    215 /* 注: 右子树中的最小的结点不可能有左结点                               */
    216 /************************************************************************/
    217 template<typename T>
    218 void BinarySearchTree<T>::remove(const T &x, BinaryNode<T> * & t)
    219 {
    220     if (t == nullptr) return;     //Item not found; do nothing
    221     if (x < t->element)           //x 小,在左子树递归查找
    222         remove(x, t->left);
    223     else if (t->element < x)      //x 大,在右子树递归查找
    224         remove(x, t->right); 
    225     else if (t->left != nullptr && t->right != nullptr)  //two children
    226     {
    227         //在右子树中查找最小数据代替该结点数据.;
    228         t->element = findMin(t->right)->element;
    229         remove(t->element, t->right);                    //删除该结点
    230     }
    231     else                         //只有一个结点或是树叶. 调整它的链,以绕过该结点后被删除.
    232     {                          
    233         BinaryNode<T> *oldNode = t;
    234         t = (t->left != nullptr) ? t->left : t->right;
    235         delete oldNode;
    236     }
    237 }
    238 
    239 /************************************************************************/
    240 ///* Destructor for the tree
    241 /************************************************************************/
    242 template<typename T>
    243 BinarySearchTree<T>::~BinarySearchTree()
    244 {
    245     makeEmpty();
    246 }
    247 
    248 template<typename T>
    249 void BinarySearchTree<T>::makeEmpty()       //公有函数
    250 {
    251     makeEmpty(root);
    252 }
    253 
    254 /************************************************************************/
    255 ///* Internal method to make subtree empty -- 私有函数
    256 /************************************************************************/
    257 template<typename T>
    258 void BinarySearchTree<T>::makeEmpty(BinaryNode<T> * & t)   
    259 {
    260     if (t != nullptr)
    261     {
    262         makeEmpty(t->left);
    263         makeEmpty(t->right);
    264         delete t;
    265     }
    266     t = nullptr;
    267 }
    268 
    269 /************************************************************************/
    270 ///* Deep copy
    271 /************************************************************************/
    272 template<typename T>
    273 const BinarySearchTree<T>& BinarySearchTree<T>::operator = (const BinarySearchTree &rhs)
    274 {
    275     if (this != &rhs) {
    276         makeEmpty();
    277         root = clone(rhs.root);
    278     }
    279     return *this;
    280 }
    281 
    282 /************************************************************************/
    283 ///* Internal method to clone subtree.  --  递归复制结点
    284 /************************************************************************/
    285 template<typename T>
    286 BinaryNode<T>* BinarySearchTree<T>::clone(BinaryNode<T> * t) const
    287 {
    288     if (t == nullptr)
    289         return nullptr;
    290     return new BinaryNode<T>( t->element, clone(t->left), clone(t->right) );
    291 }
    292 
    293 //利用递归计算树的深度 
    294 template<typename T>
    295 int BinarySearchTree<T>::Depth()
    296 {
    297     BinaryNode<T> *t = root;
    298     int depth = 0;
    299     if (root == nullptr) 
    300         return 0;
    301     Depth(t, 1, depth);
    302     return depth;
    303 }
    304 
    305 //由public的函数Depth调用, 完成树的深度的计算,p是根结点,Level是层,depth用来返回树的深度 
    306 template<typename T>
    307 int BinarySearchTree<T>::Depth(BinaryNode<T> *t, int level, int &depth)
    308 {
    309     if (level > depth) depth = level;                  //层数
    310     if (t->left) Depth(t->left, level + 1, depth);     //递归遍历左子树,且层数加1 
    311     if (t->right) Depth(t->right, level + 1, depth);   //递归遍历右子树, 且层数加1 
    312     return 0; 
    313 }
    314 
    315 template<typename T>
    316 //利用 递归 算法 计算树的 高度
    317 void BinarySearchTree<T>::CountLeaf(BinaryNode<T> * t, int &count)
    318 {
    319     if (t == nullptr) return;               //为空时,退出
    320 
    321 //    CountLeaf(t->left, count);
    322 //    CountLeaf(t->right, count); 
    323     if (!(t->left) && !(t->right)) {        //儿子为空时 
    324         count++;
    325     }
    326     CountLeaf(t->left, count);
    327     CountLeaf(t->right, count); 
    328 }
    329 
    330 
    331 /************************************************************************/
    332 ///* printTree   ---    前序遍历 
    333 /************************************************************************/
    334 template<typename T>
    335 void BinarySearchTree<T>::PreprintTree(BinaryNode<T> * t) const
    336 {
    337     if (t != nullptr) {
    338         cout << t->element << ' ';     
    339         PreprintTree(t->left);
    340         PreprintTree(t->right);
    341     }
    342 }
    343 
    344 //中序遍历 
    345 template<typename T>
    346 void BinarySearchTree<T>::InprintTree(BinaryNode<T> * t ) const
    347 {
    348     if (t != nullptr) {
    349         InprintTree(t->left);
    350         cout << t->element << ' ';
    351         InprintTree(t->right);
    352     }    
    353 } 
    354 
    355 //后序遍历 
    356 template<typename T>
    357 void BinarySearchTree<T>::PostprintTree(BinaryNode<T> * t) const 
    358 {
    359     if (t != nullptr) {
    360         PostprintTree(t->left);
    361         PostprintTree(t->right);
    362         cout << t->element << ' ';
    363     }    
    364 }
    365 
    366 //利用队列Queue层次遍历二叉树 
    367 template<typename T>
    368 void BinarySearchTree<T>::LevelprintTree( BinaryNode<T> * t) const
    369 {
    370     const int maxn = 1024;
    371     BinaryNode<T> *Queue[maxn];                          //一维数组作为队列 
    372     BinaryNode<T> *tmp;                         
    373     int front = 0, rear = 0;                             //队列初始为空 
    374     if (root) {
    375         Queue[rear++] = root;                            //二叉树的根结点指针入队列 
    376         while (front != rear)
    377         {
    378             tmp = Queue[front++];                        //队首的元素出队列
    379             if (tmp) cout << tmp->element << ' ';        //输出结点值
    380             if (tmp->left) Queue[rear++] = tmp->left; 
    381             if (tmp->right) Queue[rear++] = tmp->right; 
    382         }
    383     }
    384 }
    385 
    386 //先序遍历 
    387 template<typename T>
    388 void BinarySearchTree<T>::PreprintTree_N( BinaryNode<T> * t) const          //非递归先序遍历
    389 {
    390     const int maxn = 1024;
    391     BinaryNode<T> *Stack[maxn];    
    392     int top = 0;
    393     BinaryNode<T> *tmp = root;            //将根结点的指针赋值给tmp 
    394     
    395 //    cout << "Debug :
    ";
    396     while (tmp || top != 0)
    397     {
    398 //        cout << "debug : 
    ";
    399         while (tmp) {
    400             cout << tmp->element << ' ';
    401             Stack[top++] = tmp;           //右孩子入栈 
    402             tmp = tmp->left;              //一直递归到最左的结点 
    403         }    
    404         if (top) {                        //栈不为空, 从栈中取出一个结点指针 
    405             tmp = Stack[--top];           
    406             tmp = tmp->right;                   
    407         }
    408     }    
    409 }
    410 
    411 //中序非递归遍历二叉树 (LDR)
    412 template<typename T>
    413 void BinarySearchTree<T>::InprintTree_N( BinaryNode<T> * t) const           //非递归中序遍历二叉树 
    414 {
    415     const int maxn = 1024;
    416     BinaryNode<T> *Stack[maxn];
    417     int top = 0;
    418     BinaryNode<T> *tmp = root;
    419     
    420     while (tmp || top != 0)
    421     {
    422         while (tmp) {                  //迭代到最左的子树 
    423             Stack[top++] = tmp;        //左子树入栈 
    424             tmp = tmp->left;
    425         }
    426         if (top) {
    427             tmp = Stack[--top];            //出栈最左的子树 
    428             cout << tmp->element << ' ';   //输出该元素 
    429             tmp = tmp->right;              //并指向右结点开始迭代 
    430         }
    431     }
    432      
    433 }
    434 
    435 //非递归后序遍历二叉树 (LRD)
    436 template<typename T>
    437 void BinarySearchTree<T>::PostprintTree_N( BinaryNode<T> * t) const         
    438 {
    439        const int maxn = 1024;
    440     struct Mystack {
    441         BinaryNode<T> * link;
    442         int flag;
    443     };
    444     
    445     Mystack Stack[maxn]; 
    446     BinaryNode<T> * p = root, *tmp;
    447 
    448     if (root == nullptr) return;
    449 
    450     int top = -1,                  //栈顶初始化 
    451         sign = 0;                  //为结点tmp 的标志量 
    452     
    453     while ( p != nullptr || top != -1)
    454     {
    455         while (p != nullptr)       //遍历到最左 
    456         {
    457             Stack[++top].link = p; //并且一直入栈 
    458             Stack[top].flag = 1;   //设置flag为第一次入栈 
    459             p = p->left;         
    460         }        
    461         
    462         if (top != -1)         
    463         {                          
    464             tmp = Stack[top].link; 
    465             sign = Stack[top].flag;
    466             top--;                 //出栈 
    467                                    
    468             if (sign == 1)         //结点第一次进栈 
    469             {
    470                 top++;
    471                 Stack[top].link = tmp;
    472                 Stack[top].flag = 2;            //标记为第二次出栈 
    473                 p = tmp->right;    
    474             }
    475             else {                 //第二次出栈就输出 
    476                 cout << tmp->element << ' ';      //访问该结点数据域 
    477                 p = nullptr;
    478             }
    479         }
    480     
    481     }
    482     
    483 }
    484 
    485 //树形显示二叉树,也是中序遍历 
    486 template<typename T>
    487 void BinarySearchTree<T>::DisplayTreeShape(BinaryNode<T> *bt, int level) const
    488 {    
    489     if (bt)                                         //二叉树的树形显示算法
    490     {
    491         cout << endl;
    492         for (int i = 0; i < level - 1; i++)         
    493             cout << "   ";                            //确保在第level列显示结点 
    494         cout << bt->element;                        //显示结点 
    495         DisplayTreeShape(bt->left, level - 1);     //空二叉树不显示
    496 //        cout << endl;                               //显示右子树
    497         DisplayTreeShape(bt->right, level + 2);      //显示左子树 
    498     } 
    499 }
    500 
    501 int main()
    502 {
    503 //    srand((unsigned)time(nullptr));
    504     int testData, t = 0;
    505     BinarySearchTree<int> test;
    506     cout << "输入数字个数: 
    ";
    507     cin >> t;
    508     cout << "输入数字: 
    ";
    509     while (t--)
    510     {
    511         testData = rand() % 500 + 1;
    512         test.insert(testData);
    513     }
    514     cout << "
    全部元素为: 
    ";
    515     test.PreprintTree();
    516     
    517     cout << endl;
    518 //    cin >> testData;                //不符合查找二叉树 
    519 //    test.getNode(testData) = 10000;
    520     
    521     
    522     cout << "
    Max = " << test.findMax() << endl;
    523     cout << "Min = " << test.findMin() << endl;
    524 
    525     cout << "输入查找元素: 
    ";
    526     cin >> testData;
    527     cout << "是否包含 " << testData  << " : " << test.contains(testData) << endl; 
    528     test.PreprintTree();
    529     
    530     cout << endl;
    531     cout << "输入删除元素: 
    ";
    532     cin >> testData;
    533     test.remove(testData);
    534     
    535     cout << "
    树的高度: " << test.Depth() << endl;
    536     cout << "
    叶子的个数: " << test.CountLeaf() << endl; 
    537     cout << endl;
    538     
    539     cout << "先序遍历树元素: 
    ";
    540     test.PreprintTree();
    541     
    542     cout << "
    
    中序遍历树元素: 
    ";
    543     test.InprintTree();
    544     
    545     cout << "
    
    后序遍历树元素: 
    ";
    546     test.PostprintTree();
    547     
    548     cout << "
    
    层次遍历树元素: 
    ";
    549     test.LevelprintTree();
    550     
    551     cout << "
    
    先序遍历树元素(非递归): 
    ";
    552     test.PreprintTree_N();
    553     
    554     cout << "
    
    中序遍历树元素(非递归): 
    ";
    555     test.InprintTree_N();
    556     
    557     cout << "
    
    后序遍历树元素(非递归): 
    ";
    558     test.PostprintTree_N();
    559     
    560     cout << "
    
    二叉树的树形显示算法: 
    ";
    561     test.DisplayTreeShape(43);
    562     
    563     cout << endl;
    564     return 0;
    565 }
  • 相关阅读:
    SVN还原项目到某一版本(转)
    C# Web Service 不使用服务引用直接调用方法(转)
    动态调用webservice时 ServiceDescriptionImporter类在vs2010无法引用的解决方法 (转)
    log4net示例2-日志输入存入Access(转)
    C# log4net 配置及使用详解--日志保存到文件和Access(转)
    未能解析引用的程序集......因为它对不在当前目标框架“.NETFramework,Version=v4.0,Profile=Client”中的 (转)
    Hello log4net——做一个实用好用的log4net的demo(转)
    JS移动客户端--触屏滑动事件
    js生成二维码实例
    触屏版类似刷新页面文本框获取焦点的同时弹出手机键盘的做法
  • 原文地址:https://www.cnblogs.com/douzujun/p/6011858.html
Copyright © 2011-2022 走看看