zoukankan      html  css  js  c++  java
  • 二叉排序树的实现(生成,查找,删除)

    (若有错误,敬请指正,谢谢!)

    二叉排序树是什么?————> 二叉排序树

       一个待排序数组中,第一个数据元素作为根节点,然后处理数组中后序的每一个元素,生成二叉树;对于之后的每一个元素我们都可以用插入的方式进行生成,相当于在一棵只有根节点的树上不断的进行插入操作,直到生成我们所需的二叉排序树;

       那么对于插入算法来说,我们首先需要找到目前数据元素所需插入节点的地方,通过二叉排序树的节点大小关系(右孩子>根节点>左孩子)我们来定位待插入元素的位置。一般来说,查找也是做得这个工作,只不过插入操作在定位的基础上还需要进行数据的写入;

       最后删除操作有点麻烦,因为我们删除节点后,对剩下的二叉排序树,我们需要更新成一个新的二叉排序树。对于删除的节点我们可以分成三个类型,叶子节点(直接删除)、单侧孩子节点(删除后,还需要把其孩子节点接上)、双侧孩子节点(找到顶替删除节点位置的节点,并处理该节点的孩子);

    叶子节点:直接删除,不用考虑后序因素,我们可以直接把前驱节点的左孩子或右孩子置空,删除叶子节点;(至于直接删除叶子节点,不去管前驱节点的左右孩子,没有详细的实验)

    单侧孩子节点:同样是利用前驱节点处理,该节点后面的孩子占据该节点的位置;

    双侧孩子节点:可以有两种替换方式,一种是查询该节点右子树中最小的元素顶替该节点,一种是查询该节点左子树中最大的元素顶替该节点;这两种实质上都是一样的,都需要处理替换节点的孩子,当然显而易见,该替换节点只可能最多一侧有子树,这是一个比较好的消息。我们首先需要找到该替换节点,也需确定其前驱节点,处理时还需要处理替换节点子树的连接;

    生成:

    1 BiTree CreateBiT(int * array0, int n0) {    // 生成
    2     BiTree BT = NULL;
    3     int i = 0;
    4     while (i < n0) {
    5         InsertBiT(BT, array0[i]);
    6         i++;
    7     }
    8     return BT;
    9 }

    插入:

     1 bool InsertBiT(BiTree & root, int k) {        // 插入
     2     if (root == NULL) {            // 假设数据中不存在相同数据
     3         root = (BiTree)malloc(sizeof(BiTNode));
     4         root->key = k;
     5         root->lchild = root->rchild = NULL;
     6         return true;
     7     }
     8     else if (k < root->key)
     9         return InsertBiT(root->lchild, k);
    10     else
    11         return InsertBiT(root->rchild, k);
    12 }

    查找:(查找算法可能存在一点问题)

     1 int  SearchBiT(BiTree root, int data, BiTree &temp) {    // 查找
     2     if (root == NULL || root->key == data) {
     3         temp = root;
     4         return 1;
     5     }        // 存在非任意值都有返回值问题
     6     if (data < root->key)
     7         SearchBiT(root->lchild, data, temp);
     8     else
     9         SearchBiT(root->rchild, data, temp);
    10 }

    删除:

    叶子节点:

    1 if (p->rchild == NULL && p->lchild == NULL) { // 叶子节点
    2         if (temp->lchild == p)
    3             temp->lchild = NULL;
    4         else
    5             temp->rchild = NULL;
    6     }

    单侧子树节点:

     1 if (p->lchild == NULL) {        // *p节点左子树空判断
     2     if (root == p)
     3         root = p->rchild;
     4     else if (temp->lchild == p)
     5         temp->lchild = p->rchild;
     6     else
     7         temp->rchild = p->rchild;
     8 }
     9 else if (p->rchild == NULL) {    // *p节点右子树空判断
    10     if (root == p)
    11         root = p->lchild;
    12     else if (temp->rchild == p)
    13         temp->lchild = p->lchild;
    14     else
    15         temp->rchild = p->lchild;
    16 }

    双侧子树节点:

     1 BiTree s, par;
     2         s = p->rchild;
     3         par = p;
     4         while (s->lchild != NULL) {
     5             par = s;
     6             s = s->lchild;
     7         }
     8         p->key = s->key;
     9         if (p->rchild->lchild == NULL)
    10             p->rchild = s->rchild;
    11         else
    12             par->lchild = s->rchild;
    13         free(s);

    现在又有很多问题需要我们解决了;

    那么假设只有一个元素,我们如何删除?

    对于没有前驱节点的节点我们该怎么删除?

    为什么双侧子树节点在查找替换节点之后,需要判断   p->rchild->lchild == NULL   ?

    不利用前驱节点,直接写  p = p->rchild / lchild  可行吗?

    全部解决之后,想必二叉排序树也就迎刃而解了;

     

     

    附:

      1 #include<iostream>
      2 #include<cstdlib>
      3 
      4 using namespace std;
      5 
      6 typedef struct BiTNode {// 结点结构
      7     int key;            // 关键字
      8     struct BiTNode  *lchild, *rchild;   // 左右孩子指针
      9 } BiTNode, *BiTree;
     10 
     11 bool InsertBiT(BiTree & root, int k) {        // 插入
     12     if (root == NULL) {            // 假设数据中不存在相同数据
     13         root = (BiTree)malloc(sizeof(BiTNode));
     14         root->key = k;
     15         root->lchild = root->rchild = NULL;
     16         return true;
     17     }
     18     else if (k < root->key)
     19         return InsertBiT(root->lchild, k);
     20     else
     21         return InsertBiT(root->rchild, k);
     22 }
     23 
     24 BiTree CreateBiT(int * array0, int n0) {    // 生成
     25     BiTree BT = NULL;
     26     int i = 0;
     27     while (i < n0) {
     28         InsertBiT(BT, array0[i]);
     29         i++;
     30     }
     31     return BT;
     32 }
     33 
     34 int  SearchBiT(BiTree root, int data, BiTree &temp) {    // 查找
     35     if (root == NULL || root->key == data) {
     36         temp = root;
     37         return 1;
     38     }        // 存在非任意值都有返回值问题
     39     if (data < root->key)
     40         SearchBiT(root->lchild, data, temp);
     41     else
     42         SearchBiT(root->rchild, data, temp);
     43 }
     44 
     45 bool DeleteBiT(BiTree & root, int data) {        // 删除
     46     BiTree p, temp = root, *q = new BiTree;
     47     cout << "*****检测删除数据是否存在*****" << endl;
     48     SearchBiT(root, data, p);
     49     if (p == NULL) {
     50         cout << "不存在该数据,error!" << endl;
     51         return false;
     52     }            
     53     else
     54         cout << "查找成功,数据存在" << endl;
     55     while (temp->rchild != p && temp->lchild != p)
     56         if (temp->key < p->key)        // 无赖之下,求出上一个节点
     57             temp = temp->rchild;
     58         else if (temp->key > p->key)
     59             temp = temp->lchild;
     60         else if (root->lchild == NULL && root->rchild == NULL) {
     61             root = NULL;            // 若判断到此处,表明数据只有一个,并且删除这个元素
     62             return true;
     63         }
     64         else
     65             break;
     66     if (p->rchild == NULL && p->lchild == NULL) { // 叶子节点
     67         if (temp->lchild == p)
     68             temp->lchild = NULL;
     69         else
     70             temp->rchild = NULL;
     71     }
     72     else if (p->lchild == NULL) {        // *p节点左子树空判断
     73         if (root == p)
     74             root = p->rchild;
     75         else if (temp->lchild == p)
     76             temp->lchild = p->rchild;
     77         else
     78             temp->rchild = p->rchild;
     79     }
     80     else if (p->rchild == NULL) {    // *p节点右子树空判断
     81         if (root == p)
     82             root = p->lchild;
     83         else if (temp->rchild == p)
     84             temp->lchild = p->lchild;
     85         else
     86             temp->rchild = p->lchild;
     87     }
     88     else {            // 左右子树都存在
     89         BiTree s, par;
     90         s = p->rchild;
     91         par = p;
     92         while (s->lchild != NULL) {
     93             par = s;
     94             s = s->lchild;
     95         }
     96         p->key = s->key;
     97         if (p->rchild->lchild == NULL)
     98             p->rchild = s->rchild;
     99         else
    100             par->lchild = s->rchild;
    101         free(s);
    102     }
    103     return true;
    104 }
    105 
    106 void InOrder(BiTree Bt) {
    107     if (Bt != NULL) {
    108         InOrder(Bt->lchild);
    109         cout << Bt->key << " ";
    110         InOrder(Bt->rchild);
    111     }
    112 }
    113 
    114 int main()
    115 {
    116     int i, n, v, k;
    117     BiTree Bt, bt = NULL;
    118     cout << "请输入待排数组序列个数,以及待排序列:";
    119     cin >> n;
    120     int *array = new int[n];
    121     for (i = 0; i < n; i++)
    122         cin >> array[i];
    123     Bt = CreateBiT(array, n);
    124     cout << "--------------------" << endl << "请输入查找关键字:v = ";
    125     cin >> v;
    126     SearchBiT(Bt, v, bt);
    127     if (bt == NULL)
    128         cout << "不存在该关键字" << endl;
    129     else
    130         cout << "存在该关键字,v = " << bt->key << " 查找成功!" << endl;
    131     cout << "--------------------" << endl << "请输入删除关键字:w = ";
    132     cin >> v;
    133     k = DeleteBiT(Bt, v);
    134     if (k == 1)
    135         cout << "删除成功!" << endl;
    136     else
    137         cout << "删除失败!" << endl;
    138     cout << "--------------------" << endl << "二叉排序树输出:" << endl;
    139     InOrder(Bt);
    140     if (Bt == NULL)
    141         cout << "数据已全部删除" << endl;
    142     return 0;
    143 }
    View Code

    2020-05-27

  • 相关阅读:
    MSDN Magazine搞错了
    Visual Studio 2005中设置调试符号(Debug Symbols)
    BCB 6的问题
    吴裕雄天生自然Spring Boot使用Spring Data JPA实现人与身份证的一对一关系映射
    吴裕雄天生自然Spring BootSpring Data JPA
    吴裕雄天生自然Spring BootSpring Boot对JSP的支持
    吴裕雄天生自然Spring BootSpring Boot的异常统一处理
    吴裕雄天生自然Spring Boot使用Spring Data JPA实现Author与Article的一对多关系映射
    吴裕雄天生自然Spring Boot解决 Error creating bean with name 'entityManagerFactory' defined in class path resource
    吴裕雄天生自然Spring Boot@ExceptionHandler注解和@ControllerAdvice注解
  • 原文地址:https://www.cnblogs.com/2015-16/p/12974837.html
Copyright © 2011-2022 走看看