动态规划之最优二叉搜索树的结构 C++实现

本文介绍了一种利用动态规划确定最优二叉搜索树结构的方法,并提供了完整的C++实现代码。通过考虑节点的访问频率,计算期望搜索代价,找到最佳的二叉树结构。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

动态规划之最优二叉搜索树的结构 C++实现

原理

根据每个元素出现的频率,对应一个概率值,计算其整个二叉树的期望搜索代价,确定最优二叉树的结构。

源代码

#include <iostream>
#include <utility>
#include <vector>

using namespace std;

//Probability.
vector<double> temp_dblP = { 0.0,0.15,0.10,0.05,0.10,0.20 }, temp_dblQ = { 0.05,0.10,0.05,0.05,0.05,0.10 };

//Just Memoized of Optimal_BST
pair<vector<vector<double>>, vector<vector<int>>> 
Optimal_BST(const vector<double> &temp_dblP, const vector<double> &temp_dblQ, const size_t &temp_n) {
	vector<vector<double>> temp_VecE, temp_VecW;
	vector<vector<int>> temp_VecRoot;

	temp_VecE.resize(temp_n + 2);
	temp_VecW.resize(temp_n + 2);
	temp_VecRoot.resize(temp_n + 1);

	for(auto &i : temp_VecE) {
		i.resize(temp_n + 1);
	}
	for(auto &i : temp_VecW) {
		i.resize(temp_n + 1);
	}
	for(auto &i : temp_VecRoot) {
		i.resize(temp_n + 1);
	}

	for(auto i = 1; i <= temp_n + 1; ++i) {
		temp_VecE[i][i - 1] = temp_dblQ[i - 1];
		temp_VecW[i][i - 1] = temp_dblQ[i - 1];
	}

	for(auto l = 1; l <= temp_n; ++l) {
		for (auto i = 1; i <= temp_n - l + 1; ++i) {
			auto j = i + l - 1;
			temp_VecE[i][j] = DBL_MAX;
			temp_VecW[i][j] = temp_VecW[i][j - 1] + temp_dblP[j] + temp_dblQ[j];

			for (auto r = i; r <= j; ++r) {
				auto temp_t = temp_VecE[i][r - 1] + temp_VecE[r + 1][j] + temp_VecW[i][j];
				if(temp_t < temp_VecE[i][j]) {
					temp_VecE[i][j] = temp_t;
					temp_VecRoot[i][j] = r;
				}
			}
		}
	}

	return make_pair(temp_VecE, temp_VecRoot);
}

void Print_BST(vector<vector<int>> const &temp_VecRoot, size_t const &temp_i, size_t const &temp_j, size_t const &temp_r) {
	auto RootChild = 0;

	if(temp_i < temp_dblP.size() && temp_j < temp_dblP.size()) {
		RootChild = temp_VecRoot[temp_i][temp_j];
	}

	if (RootChild == temp_VecRoot[1][temp_dblP.size() - 1]) {
		cout << "k" << RootChild << " is root" << endl;
		Print_BST(temp_VecRoot, temp_i, RootChild - 1, RootChild);
		Print_BST(temp_VecRoot, RootChild + 1, temp_j, RootChild);

		return;
	}
	if (temp_j < temp_i - 1) { return; }
	if(temp_j == temp_i - 1) {
		if(temp_j < temp_r) {
			cout << "d" << temp_j << " is " << "k" << temp_r << "'s left child" << endl;
		}
		else {
			cout << "d" << temp_j << " is " << "k" << temp_r << "'s right child" << endl;
		}

		return;
	}
	if (RootChild < temp_r) {
		cout << "k" << RootChild << " is " << "k" << temp_r << "'s left child" << endl;
	}
	else {
		cout << "k" << RootChild << " is " << "k" << temp_r << "'s right child" << endl;
	}

	Print_BST(temp_VecRoot, temp_i, RootChild - 1, RootChild);
	Print_BST(temp_VecRoot, RootChild + 1, temp_j, RootChild);
}

int main() {
	auto temp_pair = Optimal_BST(temp_dblP, temp_dblQ, temp_dblP.size() - 1);

	for(auto &i : temp_pair.first) {
		for(auto &j : i) {
			cout << j << " ";
		}
		cout << endl;
	}

	cout << endl;

	for (auto &i : temp_pair.second) {
		for (auto &j : i) {
			cout << j << " ";
		}
		cout << endl;
	}

	cout << endl;

	Print_BST(temp_pair.second, 1, temp_dblP.size() - 1, 0);

	return 0;
}
### 动态规划实现最优二叉搜索树 动态规划是一种解决复杂问题的有效方法,通过将其分解为更小的子问题来逐步求解。对于构建最优二叉搜索树(OBST),其目标是最小化平均搜索成本。以下是基于动态程序设计的算法实现及其解释。 #### 算法述 为了找到一棵具有最小预期搜索代价的二叉搜索树,可以采用动态规划技术。该过程涉及计算不同节点作为根时的成本,并选择使总成本最低的那个配置[^1]。 #### 关键念 - **n**: 节点总数。 - **p[i]**: 第 i 个关键字 ki 的查找概率。 - **q[i]**: 在区间 (ki, ki+1) 中找不到任何关键字的概率。 - **e[i][j]**: 表示从第 i 到 j 构建 OBST 所需期望成本。 - **w[i][j]**: 子链表 {Ki,...Kj} 上所有 p q 值之。 #### C++ 示例代码 下面提供了一个简单的 C++ 版本的实现: ```cpp #include <iostream> #include <vector> using namespace std; void printSolution(int root[][], int n){ cout << "Roots of the optimal BST:" << endl; for (int i=0; i<=n; ++i) cout << root[i][n] << ' '; } // Function to get optimum cost and construct tree. double optCost(vector<double> &p, vector<double> &q, int n){ // Initialize tables e[][] and w[][] double e[n+2][n+1]; double w[n+2][n+1]; // Root table will store roots of subtrees optimized over different ranges. int root[n+1][n+1]; for (int i=0;i<=n;i++) { e[i][i-1]=q[i]; w[i][i-1]=q[i]; } for (int l=1;l<=n;l++){ for (int i=0;i<=n-l;i++){ int j=i+l; e[i][j]=INFINITY; w[i][j]=w[i][j-1]+p[j]+q[j]; for (int r=i;r<j;r++){ double t=e[i][r-1]+e[r+1][j]+w[i][j]; if(t<e[i][j]){ e[i][j]=t; root[i][j]=r; } } } } return e[0][n]; } int main(){ int keys[]={10,12,20}; double p[]= {0.35,0.25,0.4}; // probabilities of searching each key double q[]= {0.05,0.1,0.05,0.1}; // probabilities when not found between or outside int n=sizeof(keys)/sizeof(keys[0]); printf("Expected Cost is %.6f\n",optCost(p,q,n)); } ``` 此代码片段展示了如何利用给定的关键字集合以及它们对应的访问频率来创建一颗最优二叉搜索树[^3]。 #### JavaScript 实现 同样地,在 JavaScript 中也可以实现这一逻辑: ```javascript function buildObst(p, q, n) { let e = Array.from({ length: n + 2 }, () => new Array(n + 1).fill(0)); let w = Array.from({ length: n + 2 }, () => new Array(n + 1).fill(0)); let root = Array.from({ length: n + 1 }, () => new Array(n + 1).fill(0)); for(let i = 0; i <= n; i++) { e[i][i - 1] = q[i]; w[i][i - 1] = q[i]; } for(let L = 1; L <= n; L++) { for(let i = 0; i <= n - L; i++) { let j = i + L; e[i][j] = Infinity; w[i][j] = w[i][j - 1] + p[j] + q[j]; for(let r = i; r < j; r++) { let temp = e[i][r - 1] + e[r + 1][j] + w[i][j]; if(temp < e[i][j]) { e[i][j] = temp; root[i][j] = r; } } } } console.log('The expected search cost:', e[0][n]); function printTree(i,j){ if(j<i) return ''; else{ const k=root[i][j]; return '('+printTree(i,k-1)+','+ String.fromCharCode(k+'A'.charCodeAt()-1)+ ','+printTree(k+1,j)+')'; } } console.log(printTree(0,n)); } let p=[null,.3,.3,.4]; let q=[.2,null,.2,.2,.1]; buildObst(p,q,3); ``` 上述脚本实现了相同的动态规划策略用于寻找最佳结构并打印出来[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值