最优二叉查找树

问题描述:对于给定的一组改路,构造一个期望搜索代价最小的二叉查找树。
《算法导论》第二版213页。

源程序:

#include <iostream>
#include <vector>
using namespace std;

#define KEY_NUMBER 5
#define INFINITY 1000

//期望搜索代价,只使用1<=i<=n+1,0<=j<=n的表项
// 其中expected_cost[i,i-1]表示i为根的搜索树的期望搜索代价,该搜索树只包含虚拟键d[i-1]
float expected_cost[KEY_NUMBER + 2][KEY_NUMBER + 2];
//只使用1<=i<=j<=n的表项
int root[KEY_NUMBER + 1][KEY_NUMBER + 1];
//概率和数组
float w[KEY_NUMBER + 2][KEY_NUMBER + 2];

/*
 *先根遍历最优二叉查找树
 * start: 待遍历的子树的起始关键字
 * end:待遍历的子树的结束关键字
 * mid:待遍历的子树的树根对应的关键字
 * leaf_index:下一个访问的虚拟键下标
 */
void ConstructRecursively(int start,int end,int mid,int& leaf_index)
{
    if(start == mid)
    {
        cout << "d[" << leaf_index << "]是k[" << mid << "]左孩子" << endl;
        leaf_index ++;
        if(mid == end)
        {
            cout << "d[" << leaf_index << "]是k[" << mid << "]右孩子" << endl;
            leaf_index ++;
        }
        else
        {
            int right_child = root[mid + 1][end];
            cout << "k[" << right_child << "]是k[" << mid << "]右孩子" << endl;
            ConstructRecursively(mid + 1,end,right_child,leaf_index);
        }
    }
    else
    {
        int left_child = root[start][mid - 1];
        cout << "k[" << left_child << "]是k[" << mid << "]左孩子" << endl;
        ConstructRecursively(start,mid - 1,left_child,leaf_index);
        if(mid == end)
        {
            cout << "d[" << leaf_index << "]是k[" << mid << "]右孩子" << endl;
            leaf_index ++;
        }
        else
        {
            int right_child = root[mid + 1][end];
            cout << "k[" << right_child << "]是k[" << mid << "]右孩子" << endl;
            ConstructRecursively(mid + 1,end,right_child,leaf_index);
        }
    }
}

void Construct(int n)
{
    int root_index = root[1][n];
    cout << "k[" << root_index << "]是根" << endl;
    int leaf_index = 0;
    ConstructRecursively(1,n,root_index,leaf_index);
}

void OptimalSearch(float *p,float *q,int n)
{
    //初始化
    for(int i = 1;i <= n + 1;++ i)
    {
        expected_cost[i][i - 1] = q[i - 1];
        w[i][i - 1] = q[i - 1];
    }
    for(int len = 1;len <= n;++ len)
    {
        for(int i = 1;i <= n + 1 - len;++ i)
        {
            int j = i + len - 1;
            expected_cost[i][j] = INFINITY;
            w[i][j] = w[i][j - 1] + q[j] + p[j];
            for(int k = i;k <= j;++ k)
            {
                double cost = expected_cost[i][k - 1] + expected_cost[k + 1][j] + w[i][j];
                if(cost < expected_cost[i][j])
                {
                    expected_cost[i][j] = cost;
                    root[i][j] = k;
                }
            }
        }
    }
}

int main()
{
    float p[6] = {0,0.15,0.10,0.05,0.10,0.20};
    float q[6] = {0.05,0.10,0.05,0.05,0.05,0.10};
    OptimalSearch(p,q,5);
    Construct(5);
    return 0;
}

看来看去,还是算法导论写得好~~

posted @ 2016-09-04 23:10  苏苏苏紫Sue  阅读(296)  评论(0编辑  收藏  举报