数据结构中AVL的c++实现

参考链接:http://blog.csdn.net/cjbct/article/details/53613436


AVL树中,最重要的便是让树重新平衡,我们称个过程为旋转。旋转包括四种,主要是由于插入位置的原因导致的。旋转的过程可以看代码中的注释部分(569行-639行),有详细的解释。


这次编写的过程中,将C++模板类的定义了和函数实现进行了分开(但是仍然在头文件中),遇到了比较多的问题。先看看代码,然后对里面我遇到的问题进行总结。


先看看AVL树的实现代码  AVLTree.h:

[cpp]  view plain  copy
  1. #ifndef AVL_TREE_H  
  2. #define AVL_TREE_H  
  3.   
  4. #include<iostream>  
  5. using namespace std;  
  6.   
  7.   
  8. template <typename Comparable>  
  9. class AVLTree  
  10. {  
  11.   
  12. public:  
  13.     typedef enum _order {PREORDER, INORDER, POSTORDER} ORDER; // 通过enum定义常量  
  14.   
  15. public:  
  16.     AVLTree() :m_root(nullptr){}  
  17.     AVLTree(const AVLTree &rhs)  
  18.     {  
  19.         m_root = clone(rhs.m_root);  
  20.     }  
  21.     ~AVLTree()  
  22.     {  
  23.         makeEmpty();  
  24.     }  
  25.   
  26.     /** 
  27.     * 返回树的高度。空树的高度定义为-1 
  28.     */  
  29.     int getHeight() const  
  30.     {  
  31.         return m_root.height;  
  32.     }  
  33.   
  34.     /** 
  35.     * 找到树中的最小值,通过调用private的findMin实现递归 
  36.     */  
  37.     const Comparable & findMin() const  
  38.     {  
  39.         return findMin(m_root)->element;  
  40.     }  
  41.   
  42.     /** 
  43.     * 找到树中的最大值,通过调用private的findMax实现递归 
  44.     */  
  45.     const Comparable & findMax() const  
  46.     {  
  47.         return findMax(m_root)->element;  
  48.     }  
  49.   
  50.     /** 
  51.     * 当x找到时返回真,否则返回假 
  52.     * 调用了private的那个同名函数,这个是为了递归实现 
  53.     *(因为private中包含了一个AVLNode的指针t) 
  54.     */  
  55.     bool contains(const Comparable &x) const  
  56.     {  
  57.         return contains(x, m_root);  
  58.     }  
  59.   
  60.     /** 
  61.     * 判断树是否为空 
  62.     */  
  63.     bool isEmpty() const  
  64.     {  
  65.         return  nullptr == m_root;  
  66.     }  
  67.   
  68.     /** 
  69.     * 把树遍历一遍(顺序可以自己选择,默认为中序) 
  70.     */  
  71.     void printTree(ORDER or = INORDER, ostream & out = cout) const  
  72.     {  
  73.         if (isEmpty())  
  74.             out << "Empty tree!" << endl;  
  75.         else  
  76.         {  
  77.             switch (or)  
  78.             {   
  79.                 case PREORDER:  
  80.                     preOrder(m_root, cout);  
  81.                     break;   
  82.                 case INORDER:  
  83.                     inOrder(m_root, cout);  
  84.                     break;  
  85.                 case POSTORDER:  
  86.                     postOrder(m_root, cout);  
  87.                     break;  
  88.                 default:  
  89.                     cerr << "打印树的顺序只能为PREORDER, INORDER, POSTORDER!" << endl;  
  90.                     break;  
  91.             }  
  92.         }         
  93.     }  
  94.   
  95.     /** 
  96.     * 清空树 
  97.     */  
  98.     void makeEmpty()  
  99.     {  
  100.         makeEmpty(m_root);  
  101.     }  
  102.   
  103.     /** 
  104.     * 把x插入树中,如果重复了就忽略 
  105.     */  
  106.     void insert(const Comparable &x)  
  107.     {  
  108.         insert(x, m_root);  
  109.     }  
  110.   
  111.     /** 
  112.     * 把x从树中删除。如果x不在树中就什么都不做。 
  113.     */  
  114.     void remove(const Comparable &x)  
  115.     {  
  116.         remove(x, m_root);  
  117.     }  
  118.   
  119.     /** 
  120.     * 深拷贝 
  121.     */  
  122.     const AVLTree & operator= (const AVLTree &rhs)  
  123.     {  
  124.         if (this != &rhs)  
  125.         {  
  126.             AVLNode *tmp = clone(rhs.m_root);  
  127.             makeEmpty();  
  128.             m_root = tmp;  
  129.         }  
  130.         return *this;  
  131.     }  
  132.   
  133.   
  134. private:  
  135.     struct AVLNode{  
  136.         Comparable element;  
  137.         AVLNode *left;  
  138.         AVLNode *right;  
  139.         int height;  
  140.   
  141.         AVLNode(const Comparable &theElement,  
  142.             AVLNode *lt,  
  143.             AVLNode *rt,  
  144.             int h = 0)  
  145.             : element(theElement), left(lt), right(rt), height(h) {}  
  146.     };  
  147.   
  148.     AVLNode *m_root; // 根节点  
  149.     static const int ALLOW_IMBALANCE = 1; // 允许实施平衡的高度界限  
  150.   
  151.     /** 
  152.     * 用于比较两个数的大小(主要用于比较高度) 
  153.     */  
  154.     int max (int a, int b)  
  155.     {  
  156.         return a >= b ? a : b;   
  157.     }  
  158.   
  159.     /** 
  160.     * 获得节点高度,空树的高度为-1 
  161.     */  
  162.     inline int height(AVLNode *t) const  
  163.     {  
  164.         return nullptr == t ? -1 : t->height;  
  165.     }  
  166.   
  167.     /** 
  168.     * 在树t中插入元素x,如果重复则什么也不做 
  169.     */  
  170.     void insert(const Comparable &x, AVLNode * &t);  
  171.   
  172.     /** 
  173.     * 在树t中删除元素x 
  174.     */  
  175.     void remove(const Comparable &x, AVLNode * &t);  
  176.       
  177.   
  178.     /** 
  179.     * 查找最小的元素, 通过递归的方法 
  180.     */  
  181.     AVLNode * findMin(AVLNode *t) const;  
  182.       
  183.   
  184.     /** 
  185.     * 查找最大的元素, 通过循环的方法 
  186.     */  
  187.     AVLNode * findMax(AVLNode *t) const;  
  188.   
  189.     /** 
  190.     * 通过遍历的方法查找x是否在树(或子树)t中 
  191.     */  
  192.     bool contains(const Comparable &x, AVLNode * t) const;  
  193.       
  194.     /** 
  195.     * 清空树 
  196.     */  
  197.     void makeEmpty(AVLNode * &t);  
  198.       
  199.     /** 
  200.     * 按前序打印子树 
  201.     */  
  202.   
  203.     void preOrder(AVLNode *t, ostream & out) const;  
  204.     /** 
  205.     * 按中序打印子树 
  206.     */  
  207.   
  208.     void inOrder(AVLNode *t, ostream & out) const;  
  209.     /** 
  210.     * 按后序打印子树 
  211.     */  
  212.     void postOrder(AVLNode *t, ostream & out) const;  
  213.   
  214.     /** 
  215.     * 复制子树 
  216.     */  
  217.     AVLNode * clone(AVLNode *t) const;  
  218.   
  219.     /** 
  220.     * 平衡子树 
  221.     */  
  222.     void balance(AVLNode * &t);  
  223.   
  224.     /** 
  225.     * 左旋(右子树比左子树高2,并且新插入的元素在右子树的右边) 
  226.     * 此时以右子树(k1)为轴,它的根(k2)进行左旋 
  227.     * 可以理解为它的根在它的左边,所以左旋(在左边旋转) 
  228.     *      K2                           K1 
  229.     *     /  \                         /  \ 
  230.     *    X    k1         -----        K2   Z 
  231.     *         / \                    /  \   \ 
  232.     *        Y   Z                  X    Y   Z' 
  233.     *             \ 
  234.     *              Z' 
  235.     * Z'可能在Z的左边,也可以在Z的右边。例子中假设在右边。 
  236.     **/  
  237.     void rotateWithRightChild(AVLNode * & k2);  
  238.   
  239.     /** 
  240.     * 右旋(左子树比右子树高2,并且新插入的元素在左子树的左边) 
  241.     * 此时以左子树(k1)为轴,它的根(k2)进行右旋 
  242.     * 可以理解为它的根在它的右边,所以右旋(在右边旋转) 
  243.     *       k2                      k1 
  244.     *      /  \                    /  \ 
  245.     *     k1   Z      -------     X    k2 
  246.     *    /  \                    /     / \ 
  247.     *   X    Y                  X'     Y   Z  
  248.     *  / 
  249.     * X' 
  250.     * X'可能在X的左边,也可以在X的右边。例子中假设在左边。 
  251.     */  
  252.     void rotateWithLeftChild(AVLNode * & k2);  
  253.   
  254.     /** 
  255.     * 左右双旋(左子树K1比右子树D高2,并且新插入的元素在左子树K1的右边K2) 
  256.     * 第一步:对左子树k1进行一次左旋(轴为k2) 
  257.     * 第二步:对整个树k3进行一次右旋(轴为k2) 
  258.     *       k3                k3              k2 
  259.     *      /  \              /  \            /  \ 
  260.     *     k1   D    ----    k2   D  ----    k1   k3 
  261.     *    / \               / \             / \   / \ 
  262.     *   A   k2            k1  C           A   B  C  D 
  263.     *       / \          / \ 
  264.     *      B   C        A   B 
  265.     */  
  266.     void doubleWithLeftChild(AVLNode * & k3);  
  267.   
  268.     /** 
  269.     * 右左双旋(右子树K1比左子树A高2,并且新插入的元素在右子树K1的左边K2) 
  270.     * 第一步:对右子树k1进行一次右旋(轴为k2) 
  271.     * 第二步:对整个树k3进行一次左旋(轴为k2) 
  272.     *      k3              k3                 k2 
  273.     *     /  \            /  \               /  \ 
  274.     *    A    k1   ----  A    k2     ----  k3    k1 
  275.     *        / \             /  \         /  \  /  \ 
  276.     *       K2  D           B    k1      A    B C   D 
  277.     *      / \                  /  \ 
  278.     *     B   C                C    D 
  279.     */  
  280.     void doubleWithRightChild(AVLNode * & k3);  
  281.   
  282.     /** 
  283.     * 更新节点的高度 
  284.     */  
  285.     inline void updateHeight(AVLNode * & t)  
  286.     {  
  287.         t->height = max(height(t->left), height(t->right)) + 1;  
  288.     }  
  289.   
  290. };  
  291.   
  292.   
  293. /** 
  294. * 复制子树 
  295. */  
  296. template <typename Comparable>  
  297. typename AVLTree<Comparable>::AVLNode *   
  298.     AVLTree<Comparable>::clone(  
  299.         typename AVLTree<Comparable>::AVLNode *t) const  
  300. {  
  301.     if (t == nullptr)  
  302.         return nullptr;  
  303.   
  304.     return new AVLNode(t->element, clone(t->left), clone(t->right));  
  305. }  
  306.   
  307. /** 
  308. * 按前序打印子树 
  309. */  
  310. template <typename Comparable>  
  311. void AVLTree<Comparable>::preOrder(  
  312.     typename AVLTree<Comparable>::AVLNode*t,   
  313.     ostream & out) const  
  314. {  
  315.     if (nullptr != t)  
  316.     {     
  317.         out << t->element << endl;  
  318.         preOrder(t->left, out);  
  319.         preOrder(t->right, out);  
  320.     }  
  321. }  
  322.   
  323.   
  324.   
  325. /** 
  326. * 按中序打印子树 
  327. */  
  328. template <typename Comparable>  
  329. void AVLTree<Comparable>::inOrder(  
  330.     typename AVLTree<Comparable>::AVLNode *t,   
  331.     ostream & out) const  
  332. {  
  333.     if (nullptr != t)  
  334.     {  
  335.         inOrder(t->left, out);  
  336.         out << t->element << endl;  
  337.         inOrder(t->right, out);  
  338.     }  
  339. }  
  340.   
  341. /** 
  342. * 按后序打印子树 
  343. */  
  344. template <typename Comparable>  
  345. void AVLTree<Comparable>::postOrder(  
  346.     typename AVLTree<Comparable>::AVLNode*t,  
  347.     ostream & out) const  
  348. {  
  349.   
  350.     if (nullptr != t)  
  351.     {  
  352.         postOrder(t->left, out);  
  353.         postOrder(t->right, out);  
  354.         out << t->element << endl;  
  355.     }  
  356. }  
  357.   
  358.   
  359. /** 
  360. * 清空树 
  361. */  
  362. template <typename Comparable>  
  363. void AVLTree<Comparable>::makeEmpty(  
  364.     typename AVLTree<Comparable>::AVLNode * &t)  
  365. {  
  366.     if (t != nullptr)  
  367.     {  
  368.         makeEmpty(t->left);  
  369.         makeEmpty(t->right);  
  370.         delete t;  
  371.     }  
  372.     t = nullptr;  
  373. }  
  374.   
  375. /** 
  376. * 查找最小的元素, 通过递归的方法 
  377. */  
  378. template <typename Comparable>  
  379. typename AVLTree<Comparable>::AVLNode *   
  380.     AVLTree<Comparable>::findMin(  
  381.     typename AVLTree<Comparable>::AVLNode *t) const  
  382. {  
  383.     if (t == nullptr)  
  384.         return nullptr;  
  385.     if (t->left == nullptr)  
  386.         return t;  
  387.     return findMin(t->left);  
  388. }  
  389.   
  390. /** 
  391. * 查找最大的元素, 通过循环的方法 
  392. */  
  393. template <typename Comparable>  
  394. typename AVLTree<Comparable>::AVLNode *   
  395.     AVLTree<Comparable>::findMax(  
  396.     typename AVLTree<Comparable>::AVLNode *t) const  
  397. {  
  398.     if (t != nullptr)  
  399.         while (t->right != nullptr)  
  400.             t = t->right;  
  401.     return t;  
  402. }  
  403.   
  404. /** 
  405. * 在树t中删除元素x,一定要主要保持树的平衡 
  406. */  
  407. template <typename Comparable>  
  408. void AVLTree<Comparable>::remove(  
  409.     const Comparable &x,   
  410.     typename AVLTree<Comparable>::AVLNode * &t)   
  411. {  
  412.     if (t == nullptr)  
  413.         return// 没有找要删除的节点x  
  414.   
  415.     if (x < t->element)  
  416.         remove(x, t->left);  
  417.     else if (t->element < x)  
  418.         remove(x, t->right);  
  419.     else if (t->left != nullptr &&  
  420.         t->right != nullptr)  
  421.     {  
  422.         t->element = findMin(t->right)->element;  
  423.         remove(t->element, t->right);  
  424.     }  
  425.     else  
  426.     {  
  427.         //typename AVLTree<Comparable>::AVLNode * oldNode = t;  
  428.         auto oldNode = t; // 这一句等于上面的那长长的语句,可以看出C++11中的auto还是非常有用 的  
  429.         t = (t->left != nullptr) ? t->left : t->right;  
  430.         delete oldNode;  
  431.     }  
  432.   
  433.     balance(t);  
  434. }  
  435.   
  436. /** 
  437. * 在树t中插入元素x,如果重复则什么也不做 
  438. */  
  439. template <typename Comparable>  
  440. void AVLTree<Comparable>::insert(  
  441.     const Comparable &x,   
  442.     typename AVLTree<Comparable>::AVLNode * &t)   
  443. {  
  444.     if (nullptr == t)  
  445.         t = new AVLNode(x, nullptr, nullptr);  
  446.     else if (x < t->element)  
  447.     {  
  448.         insert(x, t->left); // 如果带插入的值小于目前的节点,则插入在左子树  
  449.         /* 
  450.         if (height(t->left) - height(t->right) == 2) // 插入后如果节点的左子树比右子树高2 
  451.         { 
  452.             if (x < t->left->element) 
  453.                 rotateWithLeftChild(t); // 右旋 
  454.             else 
  455.                 doubleWithLeftChild(t); // 左-右双旋 
  456.         } 
  457.         */  
  458.   
  459.     }  
  460.     else if (t->element < x)  
  461.     {  
  462.         insert(x, t->right);// 如果带插入的值大于目前的节点,则插入在右子树  
  463.         /* 
  464.         if (height(t->right) - height(t->left) == 2)// 插入后如果节点的右子树比左子树高2 
  465.         { 
  466.             if (t->right->element < x) 
  467.                 rotateWithRightChild(t); // 左旋 
  468.             else 
  469.                 doubleWithRightChild(t); // 右-左双旋 
  470.         } 
  471.         */  
  472.   
  473.     }  
  474.     else  
  475.         ; // 表示在树中找到了x,则什么也不做  
  476.   
  477.     balance(t); // 每次完成插入都检查子树是否平衡(并且默认更新节点t的高度)  
  478. }  
  479.   
  480. /** 
  481. * 平衡子树 
  482. */  
  483. template <typename Comparable>  
  484. void AVLTree<Comparable>::balance(  
  485.     typename AVLTree<Comparable>::AVLNode * &t)  
  486. {  
  487.     if (nullptr == t)  
  488.         return;  
  489.     // 如果左子树的高度与右子树高度差大于实施平衡调整的限度  
  490.     if (height(t->left) - height(t->right) > AVLTree<Comparable>::ALLOW_IMBALANCE)  
  491.     {  
  492.         // 判断是左子树的左边高还是右边高,如果左子树左边高  
  493.         if (height(t->left->left) >= height(t->left->right))  
  494.         {  
  495.             rotateWithLeftChild(t);   //那么就是右旋
  496.         }  
  497.         else  
  498.         {   
  499.             doubleWithLeftChild(t);  //那么就是先右旋再左旋
  500.         }  
  501.   
  502.     }  
  503.     // 如果右子树的高度与左子树高度差大于实施平衡调整的限度  
  504.     else if (height(t->right) - height(t->left) > AVLTree<Comparable>::ALLOW_IMBALANCE)  
  505.     {  
  506.           //如果右面子树高,那么就左旋
  507.         if (height(t->right->right) >= height(t->right->left))  
  508.         {  
  509.             rotateWithRightChild(t);  
  510.         }  
  511. //左面子树高,那么就先右旋再左旋
  512.         else  
  513.         {  
  514.             doubleWithRightChild(t);  
  515.         }  
  516.     }  
  517.     else  
  518.         ;  
  519.   
  520.     updateHeight(t);  
  521. }  
  522.   
  523. /** 
  524. * 通过遍历的方法查找x是否在树(或子树)t中 
  525. */  
  526. template <typename Comparable>  
  527. bool AVLTree<Comparable>::contains(  
  528.     const Comparable &x,   
  529.     typename AVLTree<Comparable>::AVLNode * t) const  
  530. {  
  531.     if (t == nullptr) // 遍历中未找到元素的中止条件  
  532.         return false;  
  533.     else if (x < t->element)  
  534.         return contains(x, t->left);  
  535.     else if (t->element < x)  
  536.         return contains(x, t->right);  
  537.     else // 如果 x 不大于 也 不小于t所指的节点中的元素,则x==t->element  
  538.         return true;  
  539. }  
  540.   
  541. /** 
  542. * 右旋(左子树比右子树高2,并且新插入的元素在左子树的左边) 
  543. * 此时以左子树(k1)为轴,它的根(k2)进行右旋 
  544. * 可以理解为它的根在它的右边,所以右旋(在右边旋转) 
  545. *       k2                      k1 
  546. *      /  \                    /  \ 
  547. *     k1   Z      -------     X    k2 
  548. *    /  \                    /     / \ 
  549. *   X    Y                  X'     Y   Z 
  550. *  / 
  551. * X' 
  552. * X'可能在X的左边,也可以在X的右边。例子中假设在左边。 
  553. */  
  554. template <typename Comparable>  
  555. void AVLTree<Comparable>::rotateWithLeftChild(  
  556.     typename AVLTree<Comparable>::AVLNode * & k2)  
  557. {  
  558.     //typename AVLTree<Comparable>::AVLNode * k1 = k2->left; // 获得k2的左节点  
  559.     auto k1 = k2->left; // 使用auto定义  
  560.     // 开始旋转  
  561. //先将k1->right(也就是图中的Y,赋值给k2的左子树)
  562. //然后将k2的所有节点赋值给k1的右子树
  563.     k2->left = k1->right;   
  564.     k1->right = k2;  
  565.     //更新高度, 先更新k2可以,更新k1时减少一次height函数的调用  
  566.     k2->height = max(height(k2->left), height(k2->right)) + 1;//等价于updateHeight(k2)  
  567.     k1->height = max(height(k1->left), k2->height) + 1;  
  568.   
  569.     k2 = k1;  //更新根节点
  570.       
  571. }  
  572.   
  573. /** 
  574. * 左旋(右子树比左子树高2,并且新插入的元素在右子树的右边) 
  575. * 此时以右子树(k1)为轴,它的根(k2)进行左旋 
  576. * 可以理解为它的根在它的左边,所以左旋(在左边旋转) 
  577. *      K2                           K1 
  578. *     /  \                         /  \ 
  579. *    X    k1         -----        K2   Z 
  580. *         / \                    /  \   \ 
  581. *        Y   Z                  X    Y   Z' 
  582. *             \ 
  583. *              Z' 
  584. * Z'可能在Z的左边,也可以在Z的右边。例子中假设在右边。 
  585. **/  
  586. template <typename Comparable>  
  587. void AVLTree<Comparable>::rotateWithRightChild(  
  588.     typename AVLTree<Comparable>::AVLNode * & k2)  
  589. {  
  590.     //typename AVLTree<Comparable>::AVLNode * k1 = k2->right;  
  591.     auto k1 = k2->right; // 使用auto定义  
  592.     // 开始旋转  
  593.     k2->right = k1->left;  
  594.     k1->left = k2;  
  595.     //更新高度, 先更新k2可以减少一次height函数的调用  
  596.     k2->height = max(height(k2->left), height(k2->right)) + 1;  
  597.     k1->height = max(k2->height, height(k1->right)) + 1;   
  598.   
  599.     k2 = k1;  
  600. }  
  601.   
  602. /** 
  603. * 左右双旋(左子树K1比右子树D高2,并且新插入的元素在左子树K1的右边K2) 
  604. * 第一步:对左子树k1进行一次左旋(轴为k2) 
  605. * 第二步:对整个树k3进行一次右旋(轴为k2) 
  606. *       k3                k3              k2 
  607. *      /  \              /  \            /  \ 
  608. *     k1   D    ----    k2   D  ----    k1   k3 
  609. *    / \               / \             / \   / \ 
  610. *   A   k2            k1  C           A   B  C  D 
  611. *       / \          / \ 
  612. *      B   C        A   B 
  613. * 注:一般来说,只会有B或C一个存在,就会进行树的平衡调整 
  614. */  
  615. template <typename Comparable>  
  616. void AVLTree<Comparable>::doubleWithLeftChild(  
  617.     typename AVLTree<Comparable>::AVLNode * & k3)  
  618. {  
  619.     rotateWithRightChild(k3->left);  //先进行一次左旋
  620.     rotateWithLeftChild(k3);  //再进行一次右旋
  621. }  
  622.   
  623.   
  624. /** 
  625. * 右左双旋(右子树K1比左子树A高2,并且新插入的元素在右子树K1的左边K2) 
  626. * 第一步:对右子树k1进行一次右旋(轴为k2) 
  627. * 第二步:对整个树k3进行一次左旋(轴为k2) 
  628. *      k3              k3                 k2 
  629. *     /  \            /  \               /  \ 
  630. *    A    k1   ----  A    k2     ----  k3    k1 
  631. *        / \             /  \         /  \  /  \ 
  632. *       K2  D           B    k1      A    B C   D 
  633. *      / \                  /  \ 
  634. *     B   C                C    D 
  635. *注:一般来说,只会有B或C一个存在,就会进行树的平衡调整 
  636. */  
  637. template <typename Comparable>  
  638. void AVLTree<Comparable>::doubleWithRightChild(  
  639.     typename AVLTree<Comparable>::AVLNode * & k3)  
  640. {  
  641.     rotateWithLeftChild(k3->right);  
  642.     rotateWithRightChild(k3);  
  643. }  
  644. #endif  //AVL_TREE_H  

我就按代码行序来总结:

1、定义了一个private clone函数(217行,296行),供拷贝构造函数(17行)和赋值操作符函数调用(122行)。

2、分别定义了public函数和对应的private函数,从而能够使用递归的方式实现一些功能,比如findMax和findMin。

3、树的深度优先遍历分为三种,前序遍历,中序遍历和后序遍历,因此在打印树的函数中,可以通过参数指定是通过什么方法进行遍历。为了更加清楚的表现出遍历的形式,使用enum定义了一些常量(13行),供printTree(71行使用)。由于printTree有两个参数,而且都有默认的参数。由于有默认参数的形参应该放在形参列表的末尾,而且我觉得经常使用的参数时调整打印的顺序,第一个参数是接收打印顺序,第二个参数时接收打印到的输出流。然后通过switch语句选择打印的方式,调用不同的私有函数。

在应用程序部分,就能使用t.printTree(AVLTree<int>::INORDER);来清晰明白的调用需要使用的打印方法(t是一个AVLTree<int>类型的对象)。

4、135行定义AVLNode中,保存了节点的高度信息(这是一般的二叉搜索树没有的)

5、在二叉搜索树的程序中,定义remove函数和insert函数为const,这是因为一般的二叉搜索树其实只是保存了一个指向根节点的指针,const可以保证指针的值不变,但是所指的根节点里面的内容(注意:指针的内容没变)如果修改了,也是可以通过编译的。然而在AVL树中,我们可能会因为调整数的平衡使得根节点所指的向的节点,比如本来指向A节点,由于调整树,可能树根就变成B节点了,这时候A和B的地址是不一样的,所以AVLTree对象中的成员m_root的值会变化,因此remove函数和insert函数不能再为const了。

6、149行定义了一个静态常量。由于静态常量需要在一开始就赋值,所以在类定义的时候就赋值了。

7、224~280行是如何旋转的方法,函数的定义在(569行-639行)。里面写了我是如何理解左旋右旋的,并且附上了过程图。

8、我以前定义模板类的时候都把成员函数的实现写在类定义里面。这次我把成员函数的实现分离出来了,遇到了不少问题。最主要的就是在135行定义了一个AVLNode的struct,如果在分离形势下要使用这个结构体类型的对象,应该显式的声明其为AVLNode<T> 中的类型typename AVLTree<Comparable>::AVLNode。

9、在类的成员函数实现的过程中,可以使用auto免去写长长的类型的痛苦:比如427~428行。

10、562行也可以像注释那样写,但是563行直接写可以免去调用一次height函数



然后是我的测试代码:testDemo.cpp

[cpp]  view plain  copy
  1. #include<iostream>  
  2. #include<random>  
  3. #include<ctime>  
  4. using namespace std;  
  5.   
  6. #include"AVLTree.h"  
  7.   
  8. int main()  
  9. {  
  10.     AVLTree<int> t; // 创建一个AVL叉搜索树  
  11.   
  12.     int a[16] = { 1, 2, 3, 4, 5, 6,  
  13.         7, 8, 9, 10, 11, 12,  
  14.         13, 14, 15, 16 };  
  15.   
  16.     cout << "==== 测试插入(先插入1~8,插入15~9):" << endl;  
  17.     for (size_t i = 0; i < 8; ++i)  
  18.     {  
  19.         t.insert(a[i]);  
  20.     }  
  21.   
  22.     for (size_t i = 15; i >= 8; --i)  
  23.     {  
  24.         t.insert(a[i]);  
  25.     }  
  26.       
  27.     cout << "==== 测试中序打印:" << endl;  
  28.     t.printTree(AVLTree<int>::INORDER);  
  29.     cout << "==== 测试前序打印:" << endl;  
  30.     t.printTree(AVLTree<int>::PREORDER);  
  31.   
  32.       
  33.     cout << "==== 测设删除:" << endl;  
  34.     for (size_t i = 0; i < 16; i+=2)  
  35.     {  
  36.         t.remove(i);  
  37.     }  
  38.     t.printTree();  
  39.       
  40.     cout << "==== 测试拷贝构造函数:" << endl;  
  41.     AVLTree<int> t2(t);  
  42.     t2.printTree();  
  43.       
  44.     cout << "==== 测试赋值操作:" << endl;  
  45.     AVLTree<int> t3;  
  46.     t3 = t;  
  47.     t.printTree();  
  48.       
  49.     cout << "==== 测试最大最小值:" << endl;  
  50.     cout << "最大值:" << t.findMax() << endl;  
  51.     cout << "最小值:" << t.findMin() << endl;  
  52.       
  53.     return 0;  
  54.   
  55. }  

运行结果如图:



通过中序,我们可以看出这个树是一棵二叉搜索树,然后通过中序和前序,我画出了树的形状


可以看出,这棵树是平衡的,也就是说这个AVL树的旋转算法的实现目前来看没有问题

以下是后面的结果




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值