zoukankan      html  css  js  c++  java
  • 数据结构综合性实验:多种功能的平衡二叉排序树

      数据结构的期末作业是关于平衡二叉排序树的综合性实验,其中需要完成的功能有:

    (1) 插入新结点 

    (2) 前序、中序、后序遍历二叉树 (递归)

    (3) 前序、中序、后序遍历的非递归算法 

    (4) 层次遍历二叉树 

    (5) 在二叉树中查找给定关键字(函数返回值为成功1,失败0) 

    (6) 交换各结点的左右子树 

    (7) 求二叉树的深度 

    (8) 叶子结点数

    (9) 删除某结点

      搞了两三天,上面的功能都实现了。而且我弄的是模板,兼容性也就相对强了一些。

      其实这对我只是一个锻炼而已,目测代码方面还有很多的地方可以改进,欢迎读者提出或指正。

      弄这个的时候发现一个比较矛盾的地方,就是其中会有树交换子树的操作。交换后,原来升序将会变成降序,反之亦然。所以,我在做的时候就不是单纯的给出交换子树的算法,而是在这个处理过后修改一个标记。初始化排序是按非降排序的,如果进行过一次倒置操作,树将以非升方式排序。这样就保持了二叉排序树的特性了。

     

    View Code
      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cstdlib>
      5 #include <algorithm>
      6 #include <cassert>
      7 #include <ctime>
      8 
      9 using namespace std;
     10 
     11 /********** simple stack template by Lyon   2012.11.24 **********/
     12 template <class T>
     13 class Stack {
     14     int maxSize, curSize;
     15     T *elem;
     16 public:
     17     void init() { // initialize stack
     18         maxSize = 16;
     19         curSize = 0;
     20         elem = (T *) malloc(maxSize * sizeof(T));
     21     }
     22     bool empty() { // whether the stack is empty
     23         return curSize == 0;
     24     }
     25     int size() { // get the size
     26         return curSize;
     27     }
     28     void push(T e) { // push e into stack
     29         while (curSize >= maxSize) {
     30             maxSize <<= 1;
     31             elem = (T *) realloc(elem, maxSize * sizeof(T));
     32         }
     33         elem[curSize++] = e;
     34     }
     35     void pop() { // pop out the top element
     36         assert(curSize > 0);
     37         curSize--;
     38     }
     39     T top() { // get the top element
     40         assert(curSize > 0);
     41         return elem[curSize - 1];
     42     }
     43 } ;
     44 /****************************************************************/
     45 
     46 /********** simple queue template by Lyon   2012.11.24 **********/
     47 template <class T>
     48 class Queue {
     49     struct Node {
     50         T elem;
     51         Node *next;
     52         Node (T &x) {
     53             elem = x;
     54             next = NULL;
     55         }
     56     } *head, *tail;
     57     int curSize;
     58 public:
     59     void init() { // initialize queue
     60         head = tail = NULL;
     61         curSize = 0;
     62     }
     63     bool empty() { // whether the queue is empty
     64         return curSize == 0;
     65     }
     66     int size() { // get the size
     67         return curSize;
     68     }
     69     void push(T &e) { // push e into queue
     70         if (head == NULL) {
     71             head = tail = new Node(e);
     72         } else {
     73             tail->next = new Node(e);
     74             tail = tail->next;
     75         }
     76         curSize++;
     77     }
     78     void pop() { // pop out the front element
     79         assert(head != NULL);
     80         Node *tmp = head;
     81         head = head->next;
     82         if (tail == tmp) tail = NULL;
     83         delete tmp;
     84         curSize--;
     85     }
     86     T front() { // get the front element
     87         assert(head != NULL);
     88         return head->elem;
     89     }
     90     T back() { // get the back element
     91         assert(tail != NULL);
     92         return tail->elem;
     93     }
     94 } ;
     95 /****************************************************************/
     96 
     97 /********** SBTree(short for Size-Balanced Tree) template by Lyon  2012.11.24 **********/
     98 template <class T>
     99 struct SBTNode { // size-balanced tree's node
    100     int size, depth, leaf; // size - subtree's size, depth - subtree's depth, leaf - the number of leaf in subtree
    101     T key;
    102     SBTNode<T> *c[2]; // two child
    103     SBTNode<T> (T k) {
    104         key = k;
    105         size = 1;
    106         depth = 1;
    107         leaf = 1;
    108         c[0] = c[1] = NULL;
    109     }
    110 } ;
    111 template <class T>
    112 class SBTree { // size-balanced tree
    113     SBTNode<T> *Root;
    114     bool less; // the way of sort
    115     void delTree(SBTNode<T> *&rt) { // delete the tree
    116         if (!rt) return ;
    117         delTree(rt->c[0]);
    118         delTree(rt->c[1]);
    119         delete rt;
    120         rt = NULL;
    121         less = false;
    122     }
    123     void rotate(SBTNode<T> *&x, bool left) { // rotate subtree x
    124         bool right = !left;
    125         SBTNode<T> *y = x->c[left];
    126         x->c[left] = y->c[right];
    127         y->c[right] = x;
    128         y->size = x->size;
    129         x->size = (x->c[0] ? x->c[0]->size : 0) + (x->c[1] ? x->c[1]->size : 0) + 1;
    130         x->depth = max(x->c[0] ? x->c[0]->depth : 0, x->c[1] ? x->c[1]->depth : 0) + 1;
    131         y->depth = max(y->c[0] ? y->c[0]->depth : 0, y->c[1] ? y->c[1]->depth : 0) + 1;
    132         x->leaf = x->c[0] == NULL && x->c[1] == NULL ? 1 : (x->c[0] ? x->c[0]->leaf : 0) + (x->c[1] ? x->c[1]->leaf : 0);
    133         x = y;
    134     }
    135     void maintain(SBTNode<T> *&rt, bool right) { // maintain subtree rt, if the right side of subtree is deeper
    136         if (!rt->c[right] || !rt) return ;
    137         bool left = !right;
    138         int ls = rt->c[left] ? rt->c[left]->size : 0;
    139         if (rt->c[right]->c[right] && rt->c[right]->c[right]->size > ls) rotate(rt, right);
    140         else if (rt->c[right]->c[left] && rt->c[right]->c[left]->size > ls) rotate(rt->c[right], left), rotate(rt, right);
    141         else return ;
    142         maintain(rt->c[0], false);
    143         maintain(rt->c[1], true);
    144         maintain(rt, false);
    145         maintain(rt, true);
    146     }
    147     void insert(SBTNode<T> *&rt, SBTNode<T> *x) { // insert x into subtree rt
    148         if (!rt) {
    149             rt = x;
    150             return ;
    151         }
    152         rt->size++;
    153         insert(rt->c[(x->key >= rt->key) ^ less], x);
    154         maintain(rt, (x->key >= rt->key) ^ less);
    155         rt->depth = max(rt->c[0] ? rt->c[0]->depth : 0, rt->c[1] ? rt->c[1]->depth : 0) + 1;
    156         rt->leaf = rt->c[0] == NULL && rt->c[1] == NULL ? 1 : (rt->c[0] ? rt->c[0]->leaf : 0) + (rt->c[1] ? rt->c[1]->leaf : 0);
    157     }
    158     bool erase(SBTNode<T> *&rt, T k) { // erase key k in subtree rt
    159         if (!rt) return false;
    160         rt->size--;
    161         if (k == rt->key) {
    162             SBTNode<T> *t;
    163             if (!rt->c[0] && !rt->c[1]) {
    164                 delete rt;
    165                 rt = NULL;
    166             } else if (!rt->c[1]) {
    167                 t = rt, rt = rt->c[0];
    168                 delete t;
    169             } else if (!rt->c[0]) {
    170                 t = rt, rt = rt->c[1];
    171                 delete t;
    172             } else {
    173                 t = rt->c[1];
    174                 while (t->c[0]) t = t->c[0];
    175                 rt->key = t->key;
    176                 return erase(rt->c[1], t->key);
    177             }
    178         } else return erase(rt->c[(k > rt->key) ^ less], k);
    179         if (rt) {
    180             rt->depth = max(rt->c[0] ? rt->c[0]->depth : 0, rt->c[1] ? rt->c[1]->depth : 0) + 1;
    181             rt->leaf = rt->c[0] == NULL && rt->c[1] == NULL ? 1 : (rt->c[0] ? rt->c[0]->leaf : 0) + (rt->c[1] ? rt->c[1]->leaf : 0);
    182         }
    183         return true;
    184     }
    185     void Traverse(SBTNode<T> *rt, int kind) { // recursive traverse : 1.pre 2.in 3.post
    186         if (!rt) return ;
    187         if (kind == 1) cout << rt->key << ends;
    188         Traverse(rt->c[0], kind);
    189         if (kind == 2) cout << rt->key << ends;
    190         Traverse(rt->c[1], kind);
    191         if (kind == 3) cout << rt->key << ends;
    192     }
    193     void nonRecursiveTraverse(int kind) { // non-recursive traverse : 1.pre 2.in 3.post
    194         Stack<pair<SBTNode<T> *, int> > rec;
    195         SBTNode<T> *cur;
    196         int t;
    197         rec.init();
    198         rec.push(make_pair(Root, 1));
    199         while (rec.size()) {
    200             cur = rec.top().first;
    201             t = rec.top().second;
    202             rec.pop();
    203             if (cur && t == kind) cout << cur->key << ends;
    204             if (!cur || t >= 3 || t <= 0) continue;
    205 //            cout << cur->key << '-' << t << ends;
    206             rec.push(make_pair(cur, t + 1));
    207             rec.push(make_pair(cur->c[t - 1], 1));
    208         }
    209     }
    210     void reverse(SBTNode<T> *rt) { // reverse subtree rt
    211         if (!rt) return ;
    212         swap(rt->c[0], rt->c[1]);
    213         reverse(rt->c[0]);
    214         reverse(rt->c[1]);
    215     }
    216 public:
    217     void init(bool cmp = false) { // initialize SBTree
    218         Root = NULL;
    219         less = cmp;
    220     }
    221     bool empty() {
    222         return Root == NULL;
    223     }
    224     void delTree() { // delete SBTree
    225         delTree(Root);
    226         cout << "The Size-balanced Tree is deleted!" << endl;
    227     }
    228     void insert(T x) { // insert x into SBTree
    229         SBTNode<T> *tmp = new SBTNode<T>(x);
    230         insert(Root, tmp);
    231         cout << "Element " << x << " Insert Successfully!" << endl;
    232     }
    233     bool erase(T k) { // erase k in SBTree
    234         if (erase(Root, k)) {
    235             cout << "Element " << k << " Erase Successfully!" << endl;
    236             return true;
    237         } else {
    238             cout << "Element " << k << " not found!" << endl;
    239             return false;
    240         }
    241     }
    242     void preTraverse() { // output the pre-traverse array
    243         cout << "The pre-Traverse array is:" << endl;
    244         Traverse(Root, 1);
    245         cout << endl;
    246     }
    247     void inTraverse() { // output the in-traverse array
    248         cout << "The in-Traverse array is:" << endl;
    249         Traverse(Root, 2);
    250         cout << endl;
    251     }
    252     void postTraverse() { // output the post-traverse array
    253         cout << "The post-Traverse array is:" << endl;
    254         Traverse(Root, 3);
    255         cout << endl;
    256     }
    257     void nonRecursivePreTraverse() { // in non-recursive way
    258         cout << "The pre-Traverse array is (non-recursive):" << endl;
    259         nonRecursiveTraverse(1);
    260         cout << endl;
    261     }
    262     void nonRecursiveInTraverse() { // in non-recursive way
    263         cout << "The in-Traverse array is (non-recursive):" << endl;
    264         nonRecursiveTraverse(2);
    265         cout << endl;
    266     }
    267     void nonRecursivePostTraverse() { // in non-recursive way
    268         cout << "The post-Traverse array is (non-recursive):" << endl;
    269         nonRecursiveTraverse(3);
    270         cout << endl;
    271     }
    272     bool find(T key) { // find key value in SBTree
    273         SBTNode<T> *p = Root;
    274         while (true) {
    275             if (!p) return false;
    276             if (key == p->key) return true;
    277             if ((key < p->key) ^ less) p = p->c[0];
    278             else p = p->c[1];
    279         }
    280     }
    281     int depth() {
    282         return Root->depth;    // the depth of SBTree
    283     }
    284     int leaves() {
    285         return Root->leaf;    // the number of leaf in SBTree
    286     }
    287     void reverse() { // reverse SBTree
    288         less = !less;
    289         reverse(Root);
    290         cout << "Tree is reversed!" << endl;
    291     }
    292     void nonRecursiveReverseDFS() { // in non-recursive way
    293         less = !less;
    294         Stack<pair<SBTNode<T> *, int> > rec;
    295         SBTNode<T> *cur;
    296         int t;
    297         rec.init();
    298         rec.push(make_pair(Root, 1));
    299         while (rec.size()) {
    300             cur = rec.top().first;
    301             t = rec.top().second;
    302             rec.pop();
    303             if (!cur || t >= 3 || t <= 0) continue;
    304             if (t == 1) swap(cur->c[0], cur->c[1]);
    305 //            cout << cur->key << '-' << t << ends;
    306             rec.push(make_pair(cur, t + 1));
    307             rec.push(make_pair(cur->c[t - 1], 1));
    308         }
    309     }
    310     void nonRecursiveReverseBFS() {
    311         less = !less;
    312         Queue<SBTNode<T> *> tmp;
    313         SBTNode<T> *cur;
    314         tmp.init();
    315         tmp.push(Root);
    316         while (tmp.size()) {
    317             cur = tmp.front();
    318             swap(cur->c[0], cur->c[1]);
    319             if (cur->c[0]) tmp.push(cur->c[0]);
    320             if (cur->c[1]) tmp.push(cur->c[1]);
    321         }
    322         cout << "Tree is reversed!" << endl;
    323     }
    324     void levelTraverse() { // level traverse
    325         Queue<SBTNode<T> *> q;
    326         cout << "The level traverse array is:" << endl;
    327         q.init();
    328         q.push(Root);
    329         SBTNode<T> *cur;
    330         while (q.size()) {
    331             cur = q.front();
    332             q.pop();
    333             cout << cur->key << ends;
    334             if (cur->c[0]) q.push(cur->c[0]);
    335             if (cur->c[1]) q.push(cur->c[1]);
    336         }
    337         cout << endl;
    338     }
    339 } ;
    340 /*************************************************************************************/
    341 
    342 
    343 
    344 #define REP(i, n) for (int i = 0; i < n; i++)
    345 SBTree<int> SBT;
    346 
    347 int main() {
    348     int n, e, op;
    349     char buf[100];
    350 
    351     SBT.init();
    352     cout << "请输入树的节点个数:";
    353     cin >> n;
    354     cout << "请输入" << n << "个整数:";
    355     REP(i, n) {
    356         cin >> e;
    357         SBT.insert(e);
    358     }
    359     system("pause > nul");
    360     system("cls");
    361     while (true) {
    362         while (true) {
    363             cout << "━━━━━━━━━━━━━━━━━┓\n";
    364             cout << "  1.查看树的前中后序及层次遍历    ┃\n";
    365             cout << "  2.查看树的前中后序遍历(非递归)┃\n";
    366             cout << "  3.查找树的结点                  ┃\n";
    367             cout << "  4.查看树的深度和叶子结点个数    ┃\n";
    368             cout << "  5.交换树的左右子树              ┃\n";
    369             cout << "  6.插入新的结点                  ┃\n";
    370             cout << "  7.删除结点                      ┃\n";
    371             cout << "  8.退出程序                      ┃\n";
    372             cout << "━━━━━━━━━━━━━━━━━┛\n";
    373             cout << "请输入操作编号:";
    374             cin >> op;
    375             if (0 <= op && op <= 8) break;
    376             cout << "输入错误,请重新输入!" << endl;
    377             system("pause > nul");
    378             system("cls");
    379         }
    380         switch (op) {
    381         case 1:
    382             if (SBT.empty()) cout << "当前树为空树" << endl;
    383             else {
    384                 SBT.preTraverse();
    385                 SBT.inTraverse();
    386                 SBT.postTraverse();
    387                 SBT.levelTraverse();
    388             }
    389             break;
    390         case 2:
    391             if (SBT.empty()) cout << "当前树为空树" << endl;
    392             else {
    393                 SBT.nonRecursivePreTraverse();
    394                 SBT.nonRecursiveInTraverse();
    395                 SBT.nonRecursivePostTraverse();
    396             }
    397             break;
    398         case 3:
    399             cout << "请输入需要查找结点的值:";
    400             cin >> e;
    401             if (SBT.find(e)) cout << "查找成功,该结点存在!" << endl;
    402             else cout << "查找失败,该结点不存在!" << endl;;
    403             break;
    404         case 4:
    405             cout << "树的深度为:" << SBT.depth() << endl;
    406             cout << "树的叶子结点个数为:" << SBT.leaves() << endl;
    407             break;
    408         case 5:
    409             cout << "确定要交换树的左右结点吗?(交换以后,元素升降序将改变)" << endl << "按'Y'键后回车继续:";
    410             cin >> buf;
    411             strlwr(buf);
    412             if (buf[0] == 'y') {
    413                 SBT.reverse();
    414                 cout << "操作成功" << endl;
    415             } else cout << "已放弃操作" << endl;
    416             break;
    417         case 6:
    418             cout << "请输入新结点的值:";
    419             cin >> e;
    420             SBT.insert(e);
    421             cout << "结点已成功插入" << endl;
    422             break;
    423         case 7:
    424             if (SBT.empty()) cout << "当前树为空树,不能进行删除操作" << endl;
    425             else {
    426                 SBT.nonRecursiveInTraverse();
    427                 cout << "请输入要删除的结点的值: ";
    428                 cin >> e;
    429                 if (!SBT.erase(e)) cout << "操作失败,该结点不存在" << endl;
    430                 else cout << "操作成功" << endl;
    431             }
    432             break;
    433         case 8:
    434             SBT.delTree();
    435             cout << "操作成功,可以安全退出!" << endl;
    436             system("pause > nul");
    437             return 0;
    438         default:
    439             cout << "出现异常!" << endl;
    440             return -1;
    441         }
    442         system("pause > nul");
    443         system("cls");
    444     }
    445 }

     

    ——written by Lyon

  • 相关阅读:
    农历
    成熟度模型-数据安全
    vscode升级go插件
    关于作者
    SpringBoot入门十二(整合之项目打包部署运行)
    SpringBoot入门十一(整合之RedisTemplate的使用)
    SpringBoot入门十(整合之Junit测试)
    SpringBoot入门九(整合之通用mapper)
    SpringBoot入门八(整合之mybatis)
    SpringBoot入门七(整合之事务和连接池)
  • 原文地址:https://www.cnblogs.com/LyonLys/p/2012_11_24_Lyon.html
Copyright © 2011-2022 走看看