动态规划
来源:互联网 发布:淘宝网成交量 编辑:程序博客网 时间:2024/05/14 16:41
动态规划方法生成最优二叉查找树
转自:http://www.cnblogs.com/lpshou/archive/2012/04/26/2470914.html
1、概念引入
基于统计先验知识,我们可统计出一个数表(集合)中各元素的查找概率,理解为集合各元素的出现频率。比如中文输入法字库中各词条(单字、词组等)的先验概率,针对用户习惯可以自动调整词频——所谓动态调频、高频先现原则,以减少用户翻查次数。这就是最优二叉查找树问题:查找过程中键值比较次数最少,或者说希望用最少的键值比较次数找到每个关键码(键值)。为解决这样的问题,显然需要对集合的每个元素赋予一个特殊属性——查找概率。这样我们就需要构造一颗最优二叉查找树。
2、问题给出
n个键{a1,a2,a3......an},其相应的查找概率为{p1,p2,p3......pn}。构成最优BST,表示为T1n ,求这棵树的平均查找次数C[1, n](耗费最低)。换言之,如何构造这棵最优BST,使得
C[1, n] 最小。
3、分段方法
动态规划法策略是将问题分成多个阶段,逐段推进计算,后继实例解由其直接前趋实例解计算得到。对于最优BST问题,利用减一技术和最优性原则,如果前n-1个节点构成最优BST,加入一个节点an 后要求构成规模n的最优BST。按 n-1, n-2 , ... , 2, 1 递归,问题可解。自底向上计算:C[1, 2]→C[1, 3] →... →C[1, n]。为不失一般性用
C[i, j] 表示由{a1,a2,a3......an}构成的BST的耗费。其中1≤i ≤j ≤n。这棵树表示为Tij。从中选择一个键ak作根节点,它的左子树为Tik-1,右子树为Tk+1j。要求选择的k 使得整棵树的平均查找次数C[i, j]最小。左右子树递归执行此过程。(根的生成过程)
4、递推计算式
5、基本算法如下
6、具体实现代码(其中所有数据都存放在2.txt中,其内容为:
其中5表示有5个节点,其他数据表示各个节点出现的概率;
1 #include<stdio.h> 2 #include<stdlib.h> 3 #define max 9999 4 void OptimalBST(int,float*,float**,int**); 5 void OptimalBSTPrint(int,int,int**); 6 void main() 7 { 8 int i,num; 9 FILE *point;10 //所有数据均从2.txt中获取,2.txt中第一个数据表示节点个数;从第二个数据开始表示各个节点的概率11 point=fopen("2.txt","r");12 if(point==NULL)13 {14 printf("cannot open 2.txt.\n");15 exit(-1);16 }17 fscanf(point,"%d",&num);18 printf("%d\n",num);19 float *p=(float*)malloc(sizeof(float)*(num+1));20 for(i=1;i<num+1;i++)21 fscanf(point,"%f",&p[i]);22 //创建主表;23 float **c=(float**)malloc(sizeof(float*)*(num+2));24 for(i=0;i<num+2;i++)25 c[i]=(float*)malloc(sizeof(float)*(num+1));26 //创建根表;27 int **r=(int**)malloc(sizeof(int*)*(num+2));28 for(i=0;i<num+2;i++)29 r[i]=(int*)malloc(sizeof(int)*(num+1));30 //动态规划实现最优二叉查找树的期望代价求解。。31 OptimalBST(num,p,c,r);32 printf("该最优二叉查找树的期望代价为:%f \n",c[1][num]);33 //给出最优二叉查找树的中序遍历结果;34 printf("构造成的最优二叉查找树的中序遍历结果为:");35 OptimalBSTPrint(1,4,r);36 37 }38 void OptimalBST(int num,float*p,float**c,int**r)39 {40 int d,i,j,k,s,kmin;41 float temp,sum;42 for(i=1;i<num+1;i++)//主表和根表元素的初始化43 {44 45 c[i][i-1]=0;46 c[i][i]=p[i];47 r[i][i]=i;48 }49 c[num+1][num]=0;50 for(d=1;d<=num-1;d++)//加入节点序列51 {52 for(i=1;i<=num-d;i++)53 {54 j=i+d;55 temp=max;56 for(k=i;k<=j;k++)//找最优根57 {58 if(c[i][k-1]+c[k+1][j]<temp)59 {60 temp=c[i][k-1]+c[k+1][j];61 kmin=k;62 }63 }64 r[i][j]=kmin;//记录最优根65 sum=p[i];66 for(s=i+1;s<=j;s++)67 sum+=p[s];68 c[i][j]=temp+sum;69 }70 }71 }72 //采用递归方式实现最优根的输出,最优根都是保存在r[i][j]中的。。。73 void OptimalBSTPrint(int first,int last,int**r)74 {75 76 int k;77 if(first<=last)78 {79 k=r[first][last];80 printf("%d ",k);81 OptimalBSTPrint(first,k-1,r);82 OptimalBSTPrint(k+1,last,r);83 }84 }
7、最终运行结果:
8、参考文献:
(1)算法导论
(2)数据结构 严蔚敏
(3)网上下载的一个ppt(算法设计与分析,第八章)
另附:http://blog.sina.com.cn/s/blog_51cea4040100gk6v.html
动态规划求0-1背包问题
1.问题描述如下:
经过分析后算法如下:v(i,j)表示前j个物品中能够放入承重量为j的包中的最大价值。。。。
2.具体的代码实现如下:
其中2.txt中的具体数据为:
代码:
View Code
1 #include<stdio.h> 2 #include<stdlib.h> 3 void maxValue(int *,int *,int **,int,int); 4 int ziji(int *,int *,int *,int **,int,int); 5 int max(int,int); 6 void main() 7 { 8 int i,k,num,weight; 9 FILE *p;10 p=fopen("2.txt","r");11 if(p==NULL)12 {13 printf("文件打开失败!");14 exit(1);15 }16 fscanf(p,"%d%d",&num,&weight);17 int *w=(int*)malloc(sizeof(int)*num);18 int *v=(int*)malloc(sizeof(int)*num);19 int *path=(int*)malloc(sizeof(int)*num);20 int **vv=(int **)malloc(sizeof(int *)*(num+1));21 for(i=0;i<num+1;i++)22 vv[i]=(int *)malloc(sizeof(int)*(weight+1));23 for(i=1;i<=num;i++)24 fscanf(p,"%d",&w[i]);25 for(i=1;i<=num;i++)26 fscanf(p,"%d",&v[i]);27 28 /*printf("%d %d\n",num,weight);29 for(i=0;i<num;i++)30 printf("%d\n",w[i]);31 for(i=0;i<num;i++)32 printf("%d\n",v[i]);*/33 maxValue(w,v,vv,num,weight);34 printf("最终最大价值为: %d\n",vv[num][weight]);35 k=ziji(w,v,path,vv,num,weight);36 printf("最优子集为: \n");37 for(i=0;i<k;i++)38 printf("%d ",path[i]);39 }40 //求最终最大的价值41 void maxValue(int *w,int *v,int **vv,int num,int weight)42 { 43 int i,j,k;44 for(i=0;i<=num;i++)45 vv[i][0]=0;46 for(i=0;i<=weight;i++)47 vv[0][i]=0;48 for(i=1;i<=num;i++)49 for(j=1;j<=weight;j++)50 {51 if(j>=w[i])52 {53 k=j-w[i];54 vv[i][j]=max((v[i]+vv[i-1][k]),vv[i-1][j]);55 }56 else57 vv[i][j]=vv[i-1][j];//谢谢楼下的提醒,此处已更正。。58 }59 }60 //求最优子集61 int ziji(int *w,int *v,int *path,int **vv,int num,int weight)62 {63 int i,j=5,k=0;64 for(i=num;i>0;i--)65 {66 if(j>0)67 {68 if(vv[i][j]!=vv[i-1][j])69 {70 path[k++]=i;71 j=j-w[i];72 }73 }74 }75 return k;76 }77 int max(int x,int y)78 {79 if(x>y) return x;80 else return y;81 }
附:
另外附两幅网上找到的ppt,以便于理解,参考:http://wenku.baidu.com/view/b9e4f70416fc700abb68fce0.html
(1)最大价值v(4,5)
(2)回溯法找到最优子集
动态规划求数塔问题
问题描述如下:
具体解决方案如下:
{ 其中2.txt中保存的数据为:
}
1 #include<stdio.h> 2 #include<stdlib.h> 3 int m; 4 void dqta(int **data,int **d); 5 int max(int,int); 6 void fpath(int **data,int **d,int *path); 7 void main() 8 { 9 int i,j;10 FILE *p;11 p=fopen("2.txt","r");12 if(p==NULL)13 {14 printf("读取文件失败!\n");15 exit(1);16 }17 else18 fscanf(p,"%d",&m);19 //创建动态数组;20 int **data=(int **)malloc(sizeof(int *)*m);21 for(i=0;i<m;i++)22 data[i]=(int *)malloc(sizeof(int)*m);23 int **d=(int **)malloc(sizeof(int *)*m);24 for(i=0;i<m;i++)25 d[i]=(int *)malloc(sizeof(int)*m);26 27 int *path=(int *)malloc(sizeof(int)*m);28 //读取文件中的数据;29 for(i=0;i<m;i++)30 for(j=0;j<=i;j++)31 fscanf(p,"%d",&data[i][j]);32 dqta(data,d);33 printf("最大值为:%d\n",d[0][0]);34 fpath(data,d,path);35 printf("最终路径为:\n");36 for(i=0;i<m;i++)37 printf("%d\n",path[i]);38 }39 int max(int x,int y)40 {41 if(x>y)return x;42 else return y;43 }44 void dqta(int **data,int **d)45 {46 int i,j;47 for(j=0;j<m;j++)48 d[m-1][j]=data[m-1][j];49 for(i=m-2;i>=0;i--)50 for(j=0;j<=i;j++)51 d[i][j]=max(d[i+1][j],d[i+1][j+1])+data[i][j];52 }53 void fpath(int **data,int **d,int *path)54 {55 int i,j,b;56 path[0]=data[0][0];57 j=0;58 for(i=1;i<m;i++)59 {60 b=d[i-1][j]-data[i-1][j];61 if(b==d[i][j])62 {63 path[i]=data[i][j];64 }65 else66 {67 path[i]=data[i][j+1];68 j++;69 }70 }71 }
动态规划求有向无环图的单源最短路径
问题描述如下:
具体代码实现:
1 #include<stdlib.h> 2 #include<stdio.h> 3 #define x 9999 4 #define max 9999 5 int data[10][10]; 6 int dist[10];//记录最短路径为多少 7 int path[10];//记录最短路径 8 int kmin(int,int); 9 void fpath(int a[][10]);10 int froute(int a[][10]);11 void main()12 {13 int i,m;14 int a[10][10]={15 {x,4,2,3,x,x,x,x,x,x},16 {x,x,x,x,10,9,x,x,x,x},17 {x,x,x,x,6,7,10,x,x,x},18 {x,x,x,x,x,3,8,x,x,x},19 {x,x,x,x,x,x,x,4,8,x},20 {x,x,x,x,x,x,x,9,6,x},21 {x,x,x,x,x,x,x,5,4,x},22 {x,x,x,x,x,x,x,x,x,8},23 {x,x,x,x,x,x,x,x,x,4},24 {x,x,x,x,x,x,x,x,x,x}};25 26 /*for (i=0;i<10;i++)27 {28 for(j=0;j<10;j++)29 printf("%d ",a[i][j]);30 printf("\n");31 }*/32 fpath(a);33 printf("最短路径大小为: %d\n",dist[9]);34 35 m=froute(a);36 for(i=m-1;i>=0;i--)37 printf("最短路径经过: %d\n",path[i]);38 }39 void fpath(int a[][10])40 {41 int i,j,k;42 dist[0]=0;43 for(i=1;i<10;i++)44 {45 k=max;46 for(j=0;j<i;j++)47 {48 if(a[j][i]!=x)49 if((dist[j]+a[j][i])<k)50 k=dist[j]+a[j][i]; 51 }52 dist[i]=k;53 }54 }55 int froute(int a[][10])56 {57 int j,b,k=1,i=9;58 path[0]=10;59 while(i>0)60 {61 for(j=i-1;j>=0;j--)62 {63 if(a[j][i]!=x)64 {65 b=dist[i]-a[j][i];66 if(b==dist[j])67 {68 path[k++]=j+1;69 i=j;70 break;71 }72 }73 74 }75 }76 return k;77 }78 79 80
- 动态规划!!!动态规划!!!
- 动态规划
- 动态规划
- 动态规划
- 动态规划
- 动态规划
- 动态规划
- 动态规划
- 动态规划
- 动态规划
- 动态规划
- 动态规划
- 动态规划
- 动态规划
- 动态规划
- 动态规划
- 动态规划
- 动态规划
- Android-Watchdog
- 2011年企业架构的五个范畴
- 加载用户控件的一些方式(部分参考网络)
- MFC为窗口创建线程,以及线程与窗口间的通信
- Unicode Bidi 是一门学问
- 动态规划
- sql*plus 中输出格式控制技巧
- JAVA 比较两个日期相差的天数
- 四叉树与八叉树
- 网络管理系统、网管、network manage system、运维系统
- DevExpress控件汉化类
- Spring MVC 教程,快速入门,深入分析
- Runtime.getRuntime().exec()执行linuxshell脚本
- C++入门必用:C++ 程序设计教程资料集