【问题标题】:Count number of comparisons in binary search tree计算二叉搜索树中的比较次数
【发布时间】:2014-04-26 13:32:01
【问题描述】:

我想计算在二叉搜索树中查找数据所需的比较次数。 到目前为止,我有检查数据是否在树中的功能。我对如何计算比较感到困惑,因为函数是递归的。我需要为此使用全局变量吗?但在这种情况下,它会一直保持不变,我不能第二次使用它。谢谢!

#pragma warning(disable: 4996)
#include <stdio.h>
#include <stdlib.h>

typedef int Titem;
typedef struct node* Tpointer;
typedef struct node{
    Titem item;
    Tpointer left;
    Tpointer right;
}Tnode;
typedef Tpointer TBinSTree;

void initialize(TBinSTree* bintree);
void insert_to_tree(TBinSTree* bintree, Titem item);
int isInTree(TBinSTree* bintree, Titem item, int* counter);
void print_tree(TBinSTree bintree);

#include "bintree.h"

void initialize(TBinSTree* bintree){
    *bintree = NULL;
}
void insert_to_tree(TBinSTree* bintree, Titem newitem){
    Tpointer newnode = *bintree;
    if (*bintree == NULL){// if tree is empty
        newnode = (Tpointer)malloc(sizeof(Tnode));
        newnode->left = NULL;
        newnode->right = NULL;
        newnode->item = newitem;
        *bintree = newnode;
    }
    else{
        if (newnode->item > newitem)
            insert_to_tree(&newnode->left, newitem);
        if (newnode->item < newitem)
            insert_to_tree(&newnode->right, newitem);
    }
}
int isInTree(TBinSTree* bintree, Titem item, int* counter){
    Tpointer current = *bintree;
    (*counter)++;
    if (current == NULL){// Base case == empty tree
        printf("Item %d is not in the tree\n", item);
        printf("Number of comparisons (case NULL) is: %d\n", *counter);
        return 1;
    }
    else {
        if (current->item == item){ //see if found here
            printf("Item %d is in the tree\n", item);
            printf("Number of comparisons (case node.item == item) is: %d\n", *counter);
            return 0;
        }
        else{ //otherwise recur down the correct subtree
            if (item < current->item)
                return isInTree(&current->left, item, counter);
            else
                return isInTree(&current->right, item, counter);
        }
    }
}
void print_tree(TBinSTree bintree){ // inorder traverse
    if (bintree != NULL) {
        print_tree(bintree->left);
        printf("%d\n", bintree->item);
        print_tree(bintree->right);
    }
}

#include "bintree.h"
#include <time.h>

#define NUMBERS 10000

int main(void){

    srand(time(NULL));
    TBinSTree tree;
    int item_to_search;
    int count = 0;

    initialize(&tree);
    for (int i = 0; i < NUMBERS; i++){
        insert_to_tree(&tree, rand() % 10000);
    }
    for (int i = 0; i < 3; i++){
        count = 0;
        printf("Input %d item to search: ", i+1);
        scanf("%d", &item_to_search);
        isInTree(&tree, item_to_search, &count);
    }
    return 0;
}

UPD1 我已经更新了代码,但现在 NULL 案例打印语句被调用了两次。 UPD2 这是代码的最终版本,非常适合我的应用程序。

【问题讨论】:

    标签: c recursion comparison binary-tree binary-search-tree


    【解决方案1】:

    您还可以在调用计数器时传递对计数器的引用,例如

    int isInTree(TBinSTree* bintree, Titem item, int* counter)
    {
        ...
        if (counter != null)
        {
            (*counter)++;
            printf("Number of comparisons is %d\n", *counter);
        }
        ...
            return isInTree(&tmp->left, item, counter);
        ...
    }
    
    int counter = 0;
    isInTree(foo, bar, &counter);
    

    将其传递到下一个递归中:这样您就可以对函数的不同调用使用不同的计数器变量。

    【讨论】:

    • 这很好,谢谢!但是,如果我想在函数内部而不是 main 中打印计数器怎么办?
    • 您需要使用 *counter 再次取消引用该号码 - 是的。我已将其添加到我的代码中。顺便说一句,我怀疑您只关心每次迭代的一个比较:我认为空检查不重要,您也可以考虑将项目和当前节点的项目作为单一比较进行比较。在这种情况下,您实际上只是在计算递归到的树的深度。
    【解决方案2】:
    int counter = 0;
    int isInTree(TBinSTree* bintree, Titem item){
    
        Tpointer tmp = *bintree;
        counter++;
        if (tmp == NULL){// Base case == empty tree
            printf("Number of comparisons is: \n", counter);
            return 1;
        }
        else {
            counter++;
            if (tmp->item == item){ //see if found here
                printf("Number of comparisons is: \n", counter);
                return 0;
            }
            else{ //otherwise recur down the correct subtree
                counter++;
                if (item < tmp->item)
                    return isInTree(&tmp->left, item);
                else
                    return isInTree(&tmp->right, item);
            }
        }
    }
    

    使用全局变量并将其设置为0,同时再次调用搜索函数。

    counter = 0;
    isInTree(...); //call to search
    //print counter variable.
    
    
    counter = 0;
    isInTree(...); //another call to search
    //print counter variable.
    

    【讨论】:

    • 如果他使用多个线程,这将给出有偏差的结果。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-05
    • 2021-06-11
    • 2010-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多