最优检索二叉树

最优检索二叉树

抛出问题:

在这里插入图片描述

在这里插入图片描述

算法的基本解决思路:

在这里插入图片描述

空隙:

所谓的空隙也就是查找的数值在二叉树的结点中是不存在的,指向的是附近结点的左右子树两边。
在这里插入图片描述在这里插入图片描述
在这里插入图片描述

检索数据的平均时间:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
对于工作量而言,结点的工作量就是等于其层数加1,因为二叉树是从0层开始的,对于空隙结点的工作量就是其层数。
在这里插入图片描述

小结:

在这里插入图片描述

最优二叉检索树的实现算法分析:

关键问题:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
例如我们选取BCD为子问题
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 注意m[]的含义,平均比较次数,也就是其工作量乘以对应概率

关于优化函数的递推方程

在这里,我们会选取一个节点作为当前子问题的根节点,将此子问题的第i个节点到k-1个结点连接在左子树,将k+1到j的节点连接在右子树,因此这样形成的子问题树,其节点的普遍的操作次数全部加一,也就是说这个加一的体现可以在概率上面,等同于说是平均操作次数就是其对应子问题节点的检索概率全部乘以1,等同于其概率本身。这也就是为什么要进行加上所有节点的检索概率的原因。

在这里插入图片描述
在这里插入图片描述

所以在这个时候,我们已经搞清楚了最优检索二叉树的子问题的划分以及其平均操作次数的计算方法,那么接下来我们进行子问题中k取值的确定,子问题中不同的k的取值,也就是子问题根节点的选定对于整体子树的平均检索时间是不相同的,也就是说在子问题中可能存在一个最优的k的取值情况。

在这里插入图片描述

关于k的取值的极端情况:

在这里插入图片描述

我们进行一个实例来计算平均计算次数。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZymGkZ70-1633842713368)(../../../../typora_images/java数据结构与算法/tree/image-20211010125030787.png)]

对于这个公式解读一下,这也运用了递归的思想,将大问题细小化,从最小的问题进行计算求解,逐个击破求解。

在这里插入图片描述

在这里是以k取二为根节点,也就是说以B为根节点,将B的前部分节点连接在左子树,也就是:
在这里插入图片描述

再将剩下的归为右子树

在这里插入图片描述
将余下的划分为:

在这里插入图片描述

在m[3,5]的里面又可以划分为一个子问题。

通过这样的动态规划,进行子问题的划分,我们可以很方便的计算出其平均查找次数:
42713370)(../../../../typora_images/java数据结构与算法/tree/image-20211010130641569.png)]

  • 这里的1是最高层公式里面的w[i,j]也就是整体的概率之和(节点的概率和空隙的概率)为1。

计算的结果和我们通过计算检索数据的平均时间的数值是一样的,也就是说,运用递推方程能够更合理快速的计算出其检索二叉树的效率,也就是检索的平均时间,平均查找次数。

复杂性估计:

在这里插入图片描述

总结:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QQJjWUsa-1633842713371)(../../../../typora_images/java数据结构与算法/tree/image-20211010130749633.png)]
取k=2仅仅是我们算法中进行最优值求解中的一个方向而已,之后也会进行k=3…5
的计算,然后再对相应的平均计算时间进行记录,最后将最优的k值从底层向上据记录下来,就求解出了最优解,

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
最优二叉搜索树,又称为哈夫曼树,是一种特殊的二叉树。它的特点是,对于任意一个节点,它的左子树都比它小,它的右子树都比它大,同时,整棵树的带权路径长度最小。以下是一个使用C语言实现最优二叉搜索树的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <limits.h> // 定义最大值 #define MAX 99999 // 定义节点结构体 typedef struct _node { int key; // 节点值 int weight; // 权重 struct _node *left; // 左子树指针 struct _node *right;// 右子树指针 } Node; // 打印二叉树 void printTree(Node *root, int space) { if (root == NULL) { return; } space += 5; printTree(root->right, space); printf("\n"); for (int i = 5; i < space; i++) { printf(" "); } printf("%d\n", root->key); printTree(root->left, space); } // 构造最优二叉搜索树 void constructOptimalBST(int keys[], int weights[], int n) { Node *root[n+1]; int cost[n+1][n+1]; int sum[n+1]; for (int i = 0; i < n; i++) { // 初始化叶子节点 root[i] = (Node *)malloc(sizeof(Node)); root[i]->key = keys[i]; root[i]->weight = weights[i]; root[i]->left = NULL; root[i]->right = NULL; // 初始化cost数组和sum数组 cost[i][i] = weights[i]; sum[i] = weights[i]; for (int j = i+1; j < n; j++) { cost[i][j] = MAX; } } sum[n] = 0; cost[n][n] = 0; for (int len = 2; len <= n; len++) { for (int i = 0; i <= n-len; i++) { int j = i + len - 1; for (int k = i; k <= j; k++) { int c = ((k > i) ? cost[i][k-1] : 0) + ((k < j) ? cost[k+1][j] : 0) + sum[j+1] - sum[i]; if (c < cost[i][j]) { cost[i][j] = c; root[i][j] = (Node *)malloc(sizeof(Node)); root[i][j]->key = keys[k]; root[i][j]->weight = weights[k]; root[i][j]->left = (k > i) ? root[i][k-1] : NULL; root[i][j]->right = (k < j) ? root[k+1][j] : NULL; } } } } printf("最优二叉搜索树的代价为:%d\n", cost[0][n-1]); printf("最优二叉搜索树的结构如下:\n"); printTree(root[0][n-1], 0); } int main() { int keys[] = {10, 12, 20, 30}; int weights[] = {34, 8, 50, 10}; int n = sizeof(keys) / sizeof(keys[0]); constructOptimalBST(keys, weights, n); return 0; } ``` 以上代码使用动态规划的方法构造最优二叉搜索树,时间复杂度为O(n^3),空间复杂度为O(n^2)。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值