求折半查找成功时的平均查找长度

/**
*    实验题目:
*        求折半查找成功时的平均查找长度
*    实验目的:
*        深入掌握折半查找过程和折半查找算法分析
*    实验内容:
*        设计程序,建立有序序列R[0...n-1]进行二分查找产生的判断树,
*    在此基础上完成如下功能:
*    1、输出n=11时的判定树并求成功情况下的平均查找长度ASL。
*    2、通过构造判定树可以求得成功情况下的平均查找长度ASL1;当将
*    含有n个结点的判定树看成是一颗满二叉树时,其成功情况下的平均
*    查找长度的理论值ASL2约为log2(n+1)-1。对于n=10、100、1000、
*    10000、100000和1000000,求出其ASL1和ASL2和两者的差值。
*/

#include
#include
#include

typedef struct node
{
    long index;                             //  当前结点对应的记录下标
    int level;                              //  当前结点的层次->树的高度
    struct node *lchild;                    //  左孩子指针
    struct node *rchild;                    //  右孩子指针
}dec_node;                                  //  判定树结点类型

/**
*   功能:
*       由create_dec_tree调用以建立判定树。由R[low...high]创建根结点
*   的判定树,height为树的高度,初始时,由R[0...n-1]创建判定树,height
*   的初始值为1。
*
*/
static void create_dec_tree1(dec_node *&b, long low, long high, int height)     //  指针的引用
{
    int mid;

    if(low <= high)
    {
        mid = (low + high) / 2;
        b = (dec_node *)malloc(sizeof(dec_node));                               //  动态分配存储空间
        b->index = mid;
        b->level = height;                                                      //  树的高度
        create_dec_tree1(b->lchild, low, mid - 1, height + 1);
        create_dec_tree1(b->rchild, mid + 1, high, height + 1);
    }
    else
        b = NULL;
}

/*------------------建立判定树b------------------*/
static void create_dec_tree(dec_node *&b, long n)
{
    create_dec_tree1(b, 0, n - 1, 1);
}

/*-----------------销毁判定树b------------------*/
static void destroy_dec_tree(dec_node *&b)
{
    if(b != NULL)
    {
        destroy_dec_tree(b->lchild);
        destroy_dec_tree(b->rchild);
        free(b);
    }
}

/*----------------以括号表示法输出判定树b------------------*/
static void disp_dec_tree(dec_node *b)
{
    if(b != NULL)
    {
        printf("%d[%d]", b->index, b->level);
        if(b->lchild != NULL || b->rchild != NULL)
        {
            printf("(");                    //  有孩子结点时才输出(
            disp_dec_tree(b->lchild);       //  递归处理左子树
            if(b->rchild != NULL)
                printf(",");                //  有右孩子结点时才输出,
            disp_dec_tree(b->rchild);       //  递归处理右子树
            printf(")");                    //  有孩子结点时才输出)
        }
    }
}

/*----------------求判定树b中比较的总次数------------------*/
static int sum(dec_node *b)
{
    if(b != NULL)
    {
        if(b->lchild == NULL && b->rchild == NULL)
            return b->level;
        else
            return sum(b->lchild) + sum(b->rchild) + b->level;
    }
    else
        return 0;
}

/*----------------求成功情况下的平均查找长度------------------*/
static double asl_succ(dec_node *b, long n)
{
    return 1.0 * sum(b) / n;
}

int main(int argc, char *argv[])
{
    dec_node *b;
    long n = 11;
    double d, asl1, asl2;

    create_dec_tree(b, n);                  //  建立判定树b
    printf("R[0...%d]判定树:\n\t", n - 1);
    disp_dec_tree(b);
    printf("\n\tASL = %g\n", asl_succ(b, n));
    destroy_dec_tree(b);
    printf("成功平均查找长度分析:\n");
    printf("\tn\t\tASL1\t\tASL2\t\t差值\n");
    for(n = 10; n <= 1000000; n *= 10)
    {
        create_dec_tree(b, n);
        asl1 = asl_succ(b, n);
        asl2 = log(n + 1) - 1;
        d = asl1 - asl2;
        printf("%10d\t\t%g\t\t%g\t\t%g\n", n, asl1, asl2, d);
        destroy_dec_tree(b);
    }

    return 0;
}
运算结果:

R[0...10]判定树:
        5[1](2[2](0[3](,1[4]),3[3](,4[4])),8[2](6[3](,7[4]),9[3](,10[4])))
        ASL = 3
成功平均查找长度分析:
        n               ASL1            ASL2            差值
        10              2.9             1.3979          1.5021
       100              5.8             3.61512         2.18488
      1000              8.987           5.90875         3.07825
     10000              12.3631         8.21044         4.15266
    100000              15.6895         10.5129         5.17652
   1000000              18.9514         12.8155         6.13593

你可能感兴趣的:(数据结构与算法)