最优二叉搜索树(Optimal Binary Search Tree)_20230401

这篇具有很好参考价值的文章主要介绍了最优二叉搜索树(Optimal Binary Search Tree)_20230401。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

最优二叉搜索树(Optimal Binary Search Tree)

  1. 前言

如果有序数组或有序表中的各个元素查找概率相等,那么采用二叉搜索树(BST)进行折半查找,性能最优。如果有序表中各个记录的查找概率不相等,情况又如何呢?

先看一个具体例子。已知有序表keys, 同时给出各个元素的查询频率,注意到各个元素的查询频率不相同。要求在此条件下,构造出最优搜索二叉查找树。

keys[] = {10, 12, 20}, 

freq[] = {34, 8, 50}

如果各个元素概率相等,在此基础上,构造二叉搜索树,结果为一颗平衡搜索树。

                12         
              /    \             
            10     20  

考虑各个元素的查找概率和二叉树的不同形式,可以构造五颗不同的二叉搜索树,最优二叉搜索树则是带权路径最小的的和:
P a t h   W e i g h t = Σ ( w e i g h t [ i ] ∗ h e i g h t [ i ] ) ( 0 < = i < n ) Path\ Weight=Σ(weight[i]*height[i]) (0<=i<n) Path Weight=Σweight[i]height[i])(0<=i<n)


    10                12                 20         10              20
      \             /    \              /             \            /
      12          10     20           12               20         10  
        \                            /                 /           \
         20                        10                12             12  
      I               II             III             IV             V

分别对5种形式的二叉搜索树的带权路径和进行计算,采用列表的形式储存计算结果,则得到下述列表形式,

二叉树编号 带权路径和 备注
I =>34+8*2+50*3=200
II =>8+34*2+50*2=176
III =>50+8*2+34*3=168
IV =>34+50*2+8*3=158
V =>50+34*2+8*3=142 最优二叉搜索树

可以得到结论,等概率的二叉搜索树的带权路径和为176,并不是最优二叉搜索树,本例子中的最优二叉搜索树为第V种形式。还可以看出,最优二叉搜索树并不一定是深度最小的树,第V种二叉树的深度为3,第II种的普通的二叉搜索树的深度为2,即第V种树的深度比第II中多1,但是其带权路径和保持最小。另外还有一个结论,从本例中并不能明显看出,根节点权值不一定是最大权值节点。

上述两点声明和表述主要是说明,构造最小最优二叉搜索树不能简单采用贪心算法,贪心算法通常把最大权值放在根结点,并且设法降低树的高度,贪心算法并不能保证得到最优二叉搜索树。

  1. 问题求解

按照惯例,依照《算法导论》中的CRCC方法,采用动态规划方法对最优二叉搜索树问题进行求解。首先需要表征最优问题解的基本结构。

  • 表征最优问题解的结构(Characterize the structure of the optimal solution)

考察最优二叉搜索树的任意一颗子树,子树包含某个连续元素:
k i . . . . k j ,   1 ≤ i ≤ j ≤ n k_i....k_j, \ 1≤i≤j≤n ki....kj, 1ijn
根据递归特性,子树本身一定属于最优二叉搜索树,结论可以用反证法进行证明,不再赘述。分析对象为这颗子树,对于这颗子树我们可以分为左右子树,(ki…kr-1) 和 (kr+1…kj), 把这两颗子树作为kr的左右子树,相当于原来的子树的每个节点的深度都增加1,同时考虑根节点kr的权值,那么选择r作为根节点的代价为w(i,j)。r可以在区间【i,j】之间进行变化,但是选择的代价都是w(i,j)。

  • 递归定义最优解的值(Recursively define the value of the optimal solution)

递归定义可以描述为,在ki…kj元素范围内,尝试所有的可能情况,寻找最优二叉搜索树,在暂时不考虑重复子问题的前提下,问题呈现出穷尽/穷举的特征。

对于任意根节点r,根节点位于【i,j】,定义f(i,j)为此节点r的带权路径和,采用数学语言可以描述问题,
f ( i , j ) = f ( i , r − 1 ) + f ( r + 1 , j ) + w ( i , j ) ; f(i,j)=f(i,r-1)+f(r+1,j)+w(i,j); f(i,j)=f(i,r1)+f(r+1,j)+w(i,j);
这就是状态转移方程,状态转移方程的递归过程实际上分支递减多叉树,第一层多叉树的分枝树为j-i+1, 随着递归的深入,多叉树的分枝数不断减少。最优解涉及到在整个区间上求最小值,得到最后的递归形式的最优解为,
f ( i , j ) = m i n { f ( i , r − 1 ) + f ( r + 1 , j ) + w ( i , j ) } ;   i ≤ r ≤ j f(i,j)=min\{f(i,r-1)+f(r+1,j)+w(i,j)\}; \ i≤r≤j f(i,j)=min{f(i,r1)+f(r+1,j)+w(i,j)}; irj

  • 求解最优解的值(Compute the value of the optimal solution)

如果采用递归形式,那么求解最优解的值的关键步骤就是定义递归的终止条件,也可以理解为递归的出口。递归出口存在两种形式:

​ - i>j,这种情况表明,遍历完左边的关键字后,仍然没有找到关键字的匹配,此情况下,直接返回0

​ - i==j,这种情况表明,找到了匹配的关键字,直接返回本关键字的频率值即可

再看一个具体的例子,鉴定有四个元素,每个元素出现的频次各不相同,要求构造出最优二叉搜索树,从前面得知,如果有四个元素,那么第一次分支就会出现4叉分支,由于分支比较复杂,我们分几张图加以阐述。

最优二叉查找树,算法,数据结构,动态规划

分枝1(Branch 1),分枝1的二叉搜索树的最小路径和为233,右边为二叉搜索树,橙色框内需要代表频率数组元素的下标。肢体的一提的是,每个分枝实际上由两部分组成,这两部分 分别代表二叉搜索树的左右子孩子。简单理解,每个分枝由两个孩子构成(可能存在节点没有孩子节点的情况)。

最优二叉查找树,算法,数据结构,动态规划

分枝2/分枝3,相同思路,分枝2和分枝3的带权路径和分别为251 和192。左右两边的橙色的二叉树分别对应其相应不同的二叉搜索树。

最优二叉查找树,算法,数据结构,动态规划

分枝4,分枝4的带权路径和为259,右边的橙色的树代表其带权路径的和。

最优二叉查找树,算法,数据结构,动态规划

综上,分枝3为本问题的最优二叉搜索树。

动态规划的特征之二就是,不同分支中会出现重叠子问题(overlapping subproblem),如果仔细观察分枝1和分枝4,就会发现F(1,2)子问题都包含再两个分枝当中,这是应用递归记忆的基础,如果没有重复子问题,那么递归记就失去其相应意义。

  • 构建具体的解

上述递归仅可以求出最优二叉搜索树的最小带权路径和,但是并无法构造相应的最优二叉搜索树,这就需要追加额外的数组root[n+2][n+2]来记录每个【i,j】区间中的根节点的选择root[i][j]=r。

  1. 代码实现

3.1 定义头文件

/**
 * @file optimal_binary_search_tree.h
 * @author your name (you@domain.com)
 * @brief 
 * @version 0.1
 * @date 2023-03-31
 * 
 * @copyright Copyright (c) 2023
 * 
 */
#ifndef OPTIMAL_BINARY_SEARCH_TREE_H
#define OPTIMAL_BINARY_SEARCH_TREE_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>

/**
 * @brief Create the optimal binary search tree on the sorted array
 * 
 * @param freq Frequency array list
 * @param i Search start point
 * @param j Search end point
 * @return int -Return weight of optinal_binary search tree weight
 */
int optimal_BST(int *freq,int i, int j);


/**
 * @brief Calculate the sum of frequency list
 * 
 * @param freq Frequency list
 * @param i Search start point
 * @param j Search end point
 * @return int -Return the sume from index=i to index=j
 */
int weight_sum(int *freq, int i, int j);



#endif

3.2 函数的实现

/**
 * @file optimal_binary_search_tree.c
 * @author your name (you@domain.com)
 * @brief 
 * @version 0.1
 * @date 2023-03-31
 * 
 * @copyright Copyright (c) 2023
 * 
 */

#ifndef OPTIMAL_BINARY_SEARCH_TREE_C
#define OPTIMAL_BINARY_SEARCH_TREE_C
#include "optimal_binary_search_tree.h"

int optimal_BST(int *freq, int i, int j)
{
    int r;
    int min_value;
    int left;
    int right;
    int c;

    if(i>j)
    {
        return 0;
    }
    if(i==j)
    {
        return freq[i];
    }
    min_value=INT_MAX;
    for (r = i; r <= j; r++) // int freq[] = {34,8,50,25};
    {
        left=optimal_BST(freq,i,r-1);
        right=optimal_BST(freq,r+1,j);
        c=left+right+weight_sum(freq,i,j);
        // int freq[] = {34,8,50,25};
        if(c<min_value) 
        {
            min_value=c;
        }
    }

    return min_value;
}

int weight_sum(int *freq, int i, int j)
{
    int k;
    int sum=0;

    for(k=i;k<=j;k++)
    {
        sum+=freq[k];
    }

    return sum;
}

#endif

3.3 测试函数

/**
 * @file optimal_binary_search_tree_main.c
 * @author your name (you@domain.com)
 * @brief 
 * @version 0.1
 * @date 2023-03-31
 * 
 * @copyright Copyright (c) 2023
 * 
 */
#ifndef OPTIMAL_BINARY_SEARCH_TREE_MAIN_C
#define OPTIMAL_BINARY_SEARCH_TREE_MAIN_C
#include "optimal_binary_search_tree.c"

int main(void)
{
    int freq[] = {34,8,50,25};
    int n=sizeof(freq)/sizeof(int);

    int min_value;

    min_value=optimal_BST(freq,0,n-1);

    printf("The miminum value is %d\n",min_value);

    getchar();

    return EXIT_SUCCESS;
}

#endif

  1. 小结

构建二叉搜索树的过程,采用和矩阵链相乘相同的思路,通过直接求解子问题[i,j],从而最终求解全局问题。这个过程中需要特别注意,由于解的结果仅为矩阵中的上三角或下三角,所以需要引入长度的概念,对i和j进行不同的限制,最终达到求解的目的。

参考资料:文章来源地址https://www.toymoban.com/news/detail-522828.html

  1. 《Introduction to algorithm, 4ed》
  2. Optimal Binary Search Tree | DP-24 - GeeksforGeeks

到了这里,关于最优二叉搜索树(Optimal Binary Search Tree)_20230401的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 数据结构第四天: Complete Binary Search Tree 【搜索二叉树,完全二叉树】

    数据结构第四天: Complete Binary Search Tree 【搜索二叉树,完全二叉树】

     这道题需要的操作时排序并且需要遍历,最重要的一点它是个完全二叉树,所以数组是最适合的 这道题我的思路来自于浙江大学课件7.0.2完全二叉树 这道题说白就是将输入的样例构造成一个完全搜索二叉树。因为完全线索二叉树的 根节点一定是是一个处于左右子树中间的那

    2024年02月06日
    浏览(13)
  • 数据结构英文习题解析-第五章 二叉搜索树Binary Search Tree

    数据结构英文习题解析-第五章 二叉搜索树Binary Search Tree

    前言:最近快到FDS考试了,po重刷了一下学校的题目,自己整理了一些解析orz 因为po在自己找解析和学习的过程中非常痛苦,所以在此共享一下我的题目和自己写的解题思路,欢迎各位指出错误~全章节预计会陆续更新,可在专栏查看~ HW5 1.In a binary search tree, the keys on the same

    2024年04月09日
    浏览(12)
  • 动态规划:最优二叉搜索树

    动态规划:最优二叉搜索树

    给定一个序列 有n个有序且各不相同的键, 集合 表示在K中成功的搜索的概率; 为n+1 个不同的哑键,表示所有在和 之间的值, 表示不成功的搜索的概率. 创建二叉搜索树, 使得其期望搜索花费最小。 如果一棵最优二叉搜索树T的子树T’含有键那么这个子树T’肯定是子问题键

    2024年01月20日
    浏览(14)
  • 最优二叉搜索树 C#实现

    最优二叉搜索树 C#实现

    上一篇博文搞半天挺烧脑,没搞清楚继续… 主要是练习动态规划算法。最关键的一个是这个最优二叉搜索树能干啥。我认为如果数据稳定,统计出概率来,用最优二叉树保存,以后搜索应该是效率比较高的。还有一个是通过一通研究这个算法,折磨半天自己,加深理解,动态

    2024年02月22日
    浏览(13)
  • 【动态规划】最优二叉搜索树——算法设计与分析

    【动态规划】最优二叉搜索树——算法设计与分析

    二叉搜索树或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉搜索树。 规定树根为第0层,圆结点为数

    2024年02月16日
    浏览(12)
  • 二叉查找树(binary search tree)(难度7)

    二叉查找树(binary search tree)(难度7)

    C++数据结构与算法实现(目录) 答案在此:二叉查找树(binary search tree)(答案) 写在前面 部分内容参《算法导论》 基本接口实现 1 删除 删除值为value的第一个节点 删除叶子节点1 删除叶子节点1 (3)删除叶子节点1 删除有两个孩子的节点z 分成下面几个步骤进行: 1 找到

    2024年02月10日
    浏览(8)
  • 《算法导论》15.5 最优二叉搜索树(含C++代码)

    《算法导论》15.5 最优二叉搜索树(含C++代码)

    给定一个n个不同的已排序的序列K=k1,k2, … kn(因此k1k2…kn),我们希望用这 些构造一棵二叉搜索树。对每个k,都有一个概率p,表示其搜索频率。有些要搜 索的值可能不在K中,因此我们还有n+1个“伪\\\"d0,d1,d2, …dn,表示不在K中的值。d 0 表示所有小

    2024年02月03日
    浏览(10)
  • 数据结构-哈夫曼树(最优二叉树)

    目录 一、引言 二、哈夫曼树的概念 三、哈夫曼树的构建 1. 构建步骤 2. 构建示例 四、哈夫曼编码 1. 编码规则 2. 编码示例 五、哈夫曼树的应用 1. 数据压缩 2. 文件加密 六、总结 在计算机科学中,数据结构是指计算机中数据组织、管理和存储的方式。数据结构是计算机科学的

    2024年02月07日
    浏览(10)
  • 【算法设计与分析】(三)动态规划_更新中:斐波那契、二项式系数、树的最大独立集、最长递增、公共子序列、编辑距离、Hischberg、最优二叉搜索树、交替拿硬币、石子合并、背包、乘电梯

    【算法设计与分析】(三)动态规划_更新中:斐波那契、二项式系数、树的最大独立集、最长递增、公共子序列、编辑距离、Hischberg、最优二叉搜索树、交替拿硬币、石子合并、背包、乘电梯

    分治 动态规划本篇 还差一堆 贪心 网络流 首先,怕误人子弟必须声明一下 本人很菜 (越复习越觉得完蛋了 作为一个科班研究生算法学成这样非常惭愧(跪 ,可能写的都不是很懂,很多内容打算背过去了。因为我发现好像真的有人看所以多提醒一句。。(大家就只食用目录

    2024年01月19日
    浏览(13)
  • 【数据结构与算法】哈夫曼编码(最优二叉树)实现

    【数据结构与算法】哈夫曼编码(最优二叉树)实现

    哈夫曼编码 等长编码:占的位置一样 变长编码(不等长编码):经常使用的编码比较短,不常用的比较短 最优:总长度最短 最优的要求:占用空间尽可能短,不占用多余空间,且不能有二义性 这里给出哈夫曼二叉树的实现: HuffmanTree.h: 测试数据(主函数): 运行结果截图

    2024年02月16日
    浏览(13)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包