C++ 如何删除平衡bst中的第k个最小元素

C++ 如何删除平衡bst中的第k个最小元素,c++,algorithm,data-structures,binary-search-tree,C++,Algorithm,Data Structures,Binary Search Tree,我必须删除平衡bst中的第k个最小元素。该代码在大多数情况下都有效,但当我尝试删除根时,它会断开节点之间的连接,并打印部分剩余的bbst。当我尝试删除内部节点或叶节点时,它会起作用 代码如下: #include <iostream> using namespace std; struct arbore_binar { int key; struct arbore_binar* left; struct arbore_binar* right; in

我必须删除平衡bst中的第k个最小元素。该代码在大多数情况下都有效,但当我尝试删除根时,它会断开节点之间的连接,并打印部分剩余的bbst。当我尝试删除内部节点或叶节点时,它会起作用

代码如下:

#include <iostream>
using namespace std;


struct arbore_binar {
    int key;
    struct arbore_binar* left;
    struct arbore_binar* right;
    int size = 0;
};

arbore_binar* nod_arbore(int key) {
    arbore_binar* node = (arbore_binar*)malloc(sizeof(arbore_binar));
    node->key = key;
    node->left = NULL;
    node->right = NULL;

    return node;
}

struct arbore_binar* Build_Tree(int a[], int i, int j, int size) {

    if (i > j)
    {
        
        return NULL;
        size = 0;
    }
    int m = (i + j) / 2;

    arbore_binar* rad = nod_arbore(a[m]);

    rad->left = Build_Tree(a, i, m - 1, size+1);
    rad->right = Build_Tree(a, m + 1, j, size+1);


        if ((rad->right) && (rad->left))
            rad->size = rad->right->size + 1 + rad->left->size;

        else
            rad->size = size;
    
    if ((!rad->left) && (!rad->right))
        rad->size = 1;


    //printf("%d %d \n",rad->key,  rad->size);
   

    return rad;

}


void postorder(arbore_binar* p, int indent = 0)
{
    if (p != NULL) {
        
        
        if (indent) {
            
            std::cout <<std::string(indent, ' ') ;
        }

        cout << p->key << endl;
        if (p->left) postorder(p->left, indent + 4);
        if (p->right) postorder(p->right, indent + 4);
    }
}

struct arbore_binar* OS_SELECT(arbore_binar* rad, int poz) {

    if (poz == 0)
        return NULL;

    int r = 1;
    if (!rad)
        return NULL;

    if(rad->left)
    r= rad->left->size + 1;
       

    if (poz == r)
        return rad;

    else if (poz < r && rad->left)
        return OS_SELECT(rad->left, poz);

    else
    {
        if(rad->right)
        return OS_SELECT(rad->right, poz - r);
    }
        
    
        

}

struct arbore_binar* succesor(arbore_binar* rad) {
    struct arbore_binar* current = rad;

    while (current && current->left != NULL)
        current = current->left;

    return current;
}


struct arbore_binar* OS_DELETE(arbore_binar* rad, int poz) {

    if (poz == 0)
        return NULL;

    int r = 1;
    if (!rad)
        return NULL;

    if (rad->left) {
        r = rad->left->size + 1;
    }
        
    if (poz < r && rad->left) {
        rad->left = OS_DELETE(rad->left, poz);
        return rad;
    }
        

    else if(poz>r && rad->right)
    {
        rad->right= OS_DELETE(rad->right, poz - r);
        return rad;
    }

   
        if (!rad->left)
        {
            arbore_binar* actual = rad->right;
            free(rad);
            return actual;
        }


        else if (!rad->right) {
            arbore_binar* actual = rad->left;
            free(rad);
            return actual;
        }
        else {
            arbore_binar* parinte = rad;
            arbore_binar* actual = succesor(rad->right);

            if (parinte != rad)
                parinte->left = actual->right;
            else
                parinte->right = actual->right;

            rad->key=actual->key;

            free(actual);
            return rad;


        }
        
    

}

void demo() {
    int array[] = { 1,2,3,4,5,6,7,8,9,10,11 };

    arbore_binar* rad = Build_Tree(array, 0, 10, 0);
    postorder(rad);
    printf("\n");
    printf("%d \n", rad->size);

    arbore_binar* cautat = nod_arbore(0);
    cautat = OS_SELECT(rad, 5);
    if (cautat)
        printf("Elementul de gasit este: %d \n", cautat->key);
    else printf("Prea mic arbore\n");
    printf("\n");
    cautat = OS_DELETE(rad, 6);
    if (cautat)
        printf("Elementul de sters este: %d \n", cautat->key);
    else printf("Prea mic arbore\n");
    printf("\n");
    postorder(rad);

}

int main()
{
    demo();
}


但可以清楚地看到,它断开了与9的连接,因此无法正确打印。我能做些什么来改进它呢?

我不会写代码。我知道你自己能搞定。请尝试解释从BST删除节点的方式。有三种基本情况:

如果节点是一个没有子节点的叶,只需删除该节点即可

如果节点有一个子节点,则该节点将被删除,并且其子节点将回到其位置

如果节点有两个子节点,则转到要删除的节点的左侧子节点。在那之后,尽你所能向右走。使用案例1或案例2,删除您所在的节点最多可以有一个子节点,并且已删除节点的标签将写入您需要删除的节点中

对于3,有一种替代方法:您可以转到节点的左侧子节点,然后再尽量向左

无论如何,我不知道你在谈论平衡BST时是什么意思。你在程序中构建的树不是平衡BST。平衡BST是AVL树和红黑树,它们的插入和删除算法虽然基本相同,但应该包含树的平衡


如果我理解你在做什么,你可以使用分而治之从排序数组中建立树。我必须指出,若你们对数组进行了排序,就不需要BST。您可以使用二进制搜索,这将比您在BST中搜索数组更快。事实上,您将使用具有相同复杂性的算法:Olg n,但您不需要构建BST。BST的思想是,如果您有随机数组,则平均加快搜索速度。对于随机数组,搜索的平均复杂度为Olg n,最坏情况仍然存在。但是如果你使用平衡BST,即AVL或红黑树,你将有复杂度为Olg n的最坏情况搜索。

你可以按顺序遍历并倒计时你访问的节点数

包括
包括为什么尾部递归是。。。这很难。

当您使用调试器运行程序时,您看到了什么?这正是调试器的用途。如果您不知道如何使用调试器,这是一个很好的机会,可以学习如何使用调试器一次运行一行程序,监视所有变量及其值的变化,并分析程序的逻辑执行流。了解如何使用调试器是每个C++开发人员所需的技能,没有例外。在调试器的帮助下,您应该能够快速找到您编写的此程序和所有未来程序中的所有问题,而无需向任何人寻求帮助。
6
    3
        1
            2
        4
            5
    9
        7
            8
        10
            11
11
Elementul de gasit este: 5

Elementul de sters este: 7

7
    3
        1
            2
        4
            5
    8