二叉搜索树,编码问题

Binary search tree, coding issue

由于某些奇怪的原因,我的 BST 树并没有真正按预期运行,这是我编写的代码:

#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <limits.h>

//Creating the main structure of the main BST Tree
struct treeNode{
    int key; //The key of the node
    struct treeNode *leftChild; //The left child of the node
    struct treeNode *rightChild; //The right child of the node
    struct treeNode *parent; //The parent of the node
};

//Function for implementing and creating a new node in the BST
struct treeNode* newNode(int x){
    struct treeNode *n;
    n = malloc(sizeof(struct treeNode));
    n->key = x;
    n->leftChild = NULL;
    n->rightChild = NULL;
    n->parent = NULL;

    return n;

}

//Function for finding the minimun value in a treeNode
struct treeNode* BSTTreeMin(struct treeNode *root){
    
    if(root->leftChild == NULL){
        return root; //if the left child is nil, return the root
    }
    else{
        return BSTTreeMin(root->leftChild); //otherwise we repeform the same operation on the left child
    }
}

//Function for searching a specific node in the BST
struct treeNode* BSTTreeSearch(struct treeNode *root,int x){
    if(root == NULL || root->key == x){
        return root; //if root corresponds to key then the element x is found 
    }
    if(x < root->key){
        return BSTTreeSearch(root->leftChild, x); // in the case where the element x is smaller than root-->key then it searches the left child
    }
    else{
        return BSTTreeSearch(root->rightChild, x);// in the opposite case, it searches the right child
    }
}

//function for inserting a new key in the BST
struct treeNode* BSTTreeInsert(struct treeNode *root, struct treeNode *z){
    struct treeNode *y = NULL;
    struct treeNode *x = root;
    while(x != NULL){
        y = x;
        if(z->key <= x->key){
            x = x->leftChild;
        }
        else{
            x = x->rightChild;
        }
    }
    z->parent = y;
    if(y == NULL){
        root = z;
    }
    else if(root != NULL && z->key <= y->key){
        y->leftChild = z;
    }
    else{
        y->rightChild = z;
    }
}

struct treeNode* BSTTreeTransplant(struct treeNode *root, struct treeNode *u, struct treeNode *v){
    if(u->parent == NULL){
        root = v;
    }
    else if(u == u->parent->leftChild){
        u->parent->leftChild = v;
    }
    else{
        u->parent->rightChild = v;
    }
    if(v != NULL){
        v->parent = u->parent;
    }
}
//function for delete a node in a BST
struct treeNode* BSTTreeDelete(struct treeNode *root, struct treeNode *z){
    if(z->leftChild == NULL){
        BSTTreeTransplant(root, z, z->rightChild);
    }
    else if(z->rightChild == NULL){
        BSTTreeTransplant(root, z, z->leftChild);
    }
    else{
        struct treeNode *y = BSTTreeMin(z->rightChild);
        if(y->parent != z){
            BSTTreeTransplant(root, y, y->rightChild);
            y->rightChild = z->rightChild;
            y->rightChild->parent = y;
        }
        BSTTreeTransplant(root, z, y);
        y->leftChild = z->leftChild;
        y->leftChild->parent = y;
    }
}

//Function for emptying a BST
void BSTTreeDeallocate(struct treeNode *root){
    if(root == NULL){
        return;
    }
    BSTTreeDeallocate(root->leftChild);
    BSTTreeDeallocate(root->rightChild);
    free(root);
}

//function that checks if the Bst is valid (antagonistic function)
int isValidBstHelper(struct treeNode *root, int low, int high) {
    return root == NULL || 
        (root->key >= low && root->key <= high &&
         isValidBstHelper(root->leftChild, low, root->key) &&
         isValidBstHelper(root->rightChild, root->key, high)); 
}

//function that initiate the validity check of the Bst
int isValidBst(struct treeNode *root) {
    return isValidBstHelper(root, INT_MIN, INT_MAX);
}

//Main experiment function for this program, calculating the time for inserting, deleting and searching nodes in our BST
double SingleExperiment(int max_keys,double max_search,double max_delete,int max_instances){
    double t_tot = 0;
    int i;
    int key;
    double search;
    double delete;

    for(i = 1; i <= max_instances; i++){
        clock_t start_t, end_t;
        
        srand(0);
        struct treeNode *root;
        root = newNode(rand()); // Initializing the root of the tree

        struct treeNode *i = newNode(rand());
        struct treeNode *d = newNode(rand());

        start_t = clock();
        for(key = 1; key <= max_keys; key++){
            BSTTreeInsert(root,i); //Starting with the insertion of the nodes
        }
        for(search = 1; search <= max_search; search++){
            BSTTreeSearch(root, rand()); //Following by the searching of the nodes
        }
        for(delete = 1; delete <= max_delete; delete++){
            BSTTreeDelete(root, d); //Finally, the deletion of the nodes
        }

        end_t = clock();
        double t_elapsed = (double)(end_t - start_t); //Calculation of the time elapased
        t_tot += t_elapsed; //Adding the time to the total time

        //inorder(root); //checks if the BST is in order --> prints an ordered array

        //Checking if the Bst is valid
        if (isValidBst(root)) {
            printf("The tree is a valid BST \n");
        } else {
            printf("The tree is NOT a valid BST \n");
        }

        BSTTreeDeallocate(root); //Emptying the tree

    }
    return t_tot/max_keys; //Returning the average time
}

//main function (represents the experiment function)
int main(void){ 
    int min_keys = 5;
    int max_keys = 10;
    int max_instances = 5;
    int percentage_search = 60;
    int keys;
    int seed = 0;
    //setting up the main parameters for the experiment

    printf("Binary Search Tree \n");
    for(keys = min_keys; keys <= max_keys; keys = keys +1){
        srand(seed);
        double max_search = keys * percentage_search / 100;
        double max_delete = keys - max_search;

        double time = SingleExperiment(keys,max_search,max_delete,max_instances);
        printf("%d %f\n",keys,time);//printing the time associate to each key value
        
        seed = seed +1;
    }

    return 0;

}

每次迭代的结果应该是“树是有效的”,以及每个键数的总时间。每当我启动该程序时,它只打印出“二进制搜索树”而没有其他内容。 你能帮帮我吗?

在此先感谢大家!

主要问题出现在这个循环中:

    for(key = 1; key <= max_keys; key++){
        BSTTreeInsert(root,i);
    }

忽略 i 作为节点变量名的错误选择(它已经用作循环变量),这将插入 same 节点反复。这意味着此循环的第二次迭代将插入一个已经在树中的节点。这将使节点成为自己的子节点(自引用)。因此,此循环的第三次迭代将永远不会到达树中的叶子,因为它一直遵循该自我引用,运行 转圈。

快速修复是在每次迭代中插入 new 个节点:

    for(key = 1; key <= max_keys; key++){
        BSTTreeInsert(root, newNode(rand());
    }

现在,这解决了您的问题,但我仍然想指出,实验代码的其余部分并没有多大用处:

  • BSTTreeSearch 非常非常有可能用树中没有出现的值调用,并且没有测试函数 returns 是否确实是预期结果.但是也应该有 positive 测试——看看树中 are 的值是否真的被找到了。

  • BSTTreeDeletesame 节点重复调用。此外,此节点从未插入树中,因此这些调用永远不会从树中删除任何节点。

您可能想对此进行改进 -- 但它超出了您的问题范围。