最优二叉搜索树

在这里插入图片描述

在这里插入图片描述原问题是给出各个节点和各个节点的被查找概率,然后构造一棵各个节点平均被查找比较次数最小的树,则该问题可以用动态规划来解决

#include<bits/stdc++.h>
using namespace std;
const int M = 100;
double C[M][M], W[M][M], p[M], q[M];
int S[M][M];
int n, i, j, k;
void Optimal_BST()
{
	for (i=1;i<=n;i++)
	{
		C[i][i - 1] = 0.0;
		W[i][i - 1] = q[i - 1];
	}
	for (int t=1;t<=n;t++)
	{
		for (i = 1; i <= n - t + 1; i++)
		{
			j = i + t - 1;
			W[i][j] = W[i][j - 1] + p[j] + q[j];
			C[i][j] = C[i][i - 1] + C[i + 1][j];
			S[i][j] = i;
			// 选取i+1到j之间的某个下标的关键字作为i到j的根,如果组成的期望值最小
			// 则k为i到j的根结点
			for (k = i + 1; k < j; k++)
			{
				double tmp = C[i][k - 1] + C[k + 1][j];
				if (tmp<C[i][j] && fabs(tmp - C[i][j])>1E-6)
				{
					C[i][j] = tmp;
					S[i][j] = k;		// 记录i到j结点的树根
				}
			}
			C[i][j] += W[i][j];
		}
	}
}
void Construct_Optimal_BST(int i,int j,bool flag)
{
	if (flag == 0)
	{
		cout << "S" << S[i][j] << "是根" << endl;
		flag = 1;
	}
	int k = S[i][j];
	// 如果左子树是叶子
	if (k - 1 < i)
	{
		cout << "e" << k - 1 << "is the left child of " << "S" << k << endl;
	}
	else
	{
		cout << "S" << S[i][k - 1] << " is the left child of" << "S" << k << endl;
		Construct_Optimal_BST(i, k - 1, 1);
	}
	// 如果右子树是叶子
	if (k>=j)
	{
		cout << "e" << j << " is the right child of " << "S" << k << endl;
	}
	else
	{
		cout << "S" << S[k + 1][j] << " is the right child of " << "S" << k << endl;
		Construct_Optimal_BST(k + 1, j, 1);
	}
}
int main()
{
	cout << "请输入关键字的个数:" << endl;
	cin >> n;
	cout << "请依次输入关键字的频率:" << endl;
	for (i = 1; i <= n; i++)
	{
		cin >> p[i];
	}
	cout << "请依次输入每个虚结点的搜索频率:" << endl;
	for (i = 0; i <= n; i++)
	{
		cin >> q[i];
	}
	Optimal_BST();
	cout << "最小的搜索成本是" << C[1][n] << endl;
	cout << "最优二叉搜索树为:" << endl;
	Construct_Optimal_BST(1, n, 0);
	system("pause");
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值