最优二叉查找树-optimal-BST--C++实现

算法参考《算法导论》第15章--动态规划

//最优二叉查找树
#include <cstdio>
#include <cstring>
#include <limits>
class optimalBST{
	private:
		float *p, *q;
		int n;
		float **e;//(n+2)*(n+1)//e[1..n+1, 0..n] 
		float **w;//(n+2)*(n+1)//w[1..n+1, 0..n]
		int **root;//(n+1)*(n+1),0 row and 0 col are not used
	public:
		optimalBST(float pp[], float qq[], int nn){
			n = nn;
			p = new float[n + 1];
			q = new float[n + 1];
			memcpy(p, pp, (n + 1) * sizeof(pp));//sizeof(pp)==sizeof(float)
			memcpy(q, qq, (n + 1) * sizeof(qq));
			e = new float*[n + 2];
			w = new float*[n + 2];
			root = new int*[n + 1];
			for(int i = 0; i <= n + 1; i++){//此处是n+1--之前写成n,导致段错误
				e[i] = new float[n + 1];
				w[i] = new float[n + 1];
			}
			for(int i = 0; i <= n; i++){
				root[i] = new int[n + 1];
			}
		}
		~optimalBST(){//不知道这么写析构函数对不对,不会有内存泄漏或者重复释放的问题吧?
			delete []p;
			delete []q;
			for(int i = 0; i <= n + 1; i++){//此处是n+1--之前写成n,导致段错误
				delete []e[i];
				delete []w[i];
			}
			for(int i = 0; i <= n; i++){
				delete []root[i];
			}
			delete []e;
			delete []w;
			delete []root;

		}
		void calBST(){//核心部分,算法见算法导论第15章
			for(int i = 1; i <= n + 1; i++){
				e[i][i - 1] = w[i][i - 1] = q[i - 1];
			}
			for(int l = 1; l <= n; l++){
				for(int i = 1; i <= n - l + 1; i++){
					int j = i + l - 1;
					e[i][j] = std::numeric_limits<float>::max();
					w[i][j] = w[i][j - 1] + p[j] + q[j];
					for(int r = i; r <= j; r++){
						float 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;
						}
					}
				}
			}
		}
		void constructOptimalBST(){//练习15.5-1的算法
			int r = root[1][n];
			printf("k(%d) is root\n", r);
			printBST(1, r - 1, 0);//0代表左子树
			printBST(r + 1, n, 1);//1代表又子树
		}
		void printBST(int i, int j, int flag)//练习15.5-1的算法
		{
			if(j == i - 1){
				if(flag == 0){
					printf("d(%d)is k(%d)'s left child\n", i - 1, j + 1);
				}else{
					printf("d(%d)is k(%d)'s right child\n", i - 1, i - 1);
				}
			}else if(j >= i){
				int r = root[i][j];
				if(flag == 0){
					printf("k(%d)is k(%d)'s left child\n", r, j + 1);
				}else{
					printf("k(%d)is k(%d)'s right child\n", r, i - 1);
				}
				printBST(i, r - 1, 0);
				printBST(r + 1, j, 1);
			}
		}
		void printBST2(int i, int j)//括号表示法:parent(left_subtree, right_subtree)
		{
			if(j == i - 1){
				printf("d_%d", i - 1);
			}else if(j >= i){
				int r = root[i][j];
				printf("k_%d(", r);
				printBST2(i, r - 1);
				printf(",");
				printBST2(r + 1, j);
				printf(")");
			}
		}
		void printE()//e[1..n+1][0..n],打印e矩阵,格式同算法导论
		{
			for(int l = n; l >= 0; l--){
				for(int i = 1; i <= n - l + 1; i++){
					int j = i + l - 1;//[i..j] has l elements
					printf("%f,", e[i][j]);
				}
				printf("\n");
			}
		}
		void printRoot()//打印root矩阵,格式同算法导论
		{
			for(int l = n; l >= 1; l--){
				for(int i = 1; i <= n - l + 1; i++){
					int j = i + l - 1;//[i..j] has l elements
					printf("%d,", root[i][j]);
				}
				printf("\n");
			}
		}

};
int main()
{
	int n = 7;
	float p[7 + 1] = {0, 0.04, .06, .08, .02, .10, .12, .14};//练习15.5-2的数据
	float q[7 + 1] = {.06, .06, .06, .06, .05, .05, .05, .05};
	optimalBST bst(p, q, n);
	bst.calBST();
	bst.constructOptimalBST();
	bst.printE();
	bst.printRoot();
	bst.printBST2(1, n);
	printf("\n");
	return 0;
}

  

posted @ 2012-11-27 14:55  ttang  阅读(943)  评论(0编辑  收藏  举报