常用算法设计技巧
2013-11-05 14:00
375 查看
1.贪心算法
实例:Dijkstra算法,Prim算法,Kruskal算法,调度(最小化平均完成时间),哈夫曼编码,装箱算法
哈夫曼编码采用最小堆实现时,运行时间为O(C log C),采用简单链表为O(C^2)。在ASCII字符集的情况下,C足够小,这使得二次时间可以接受,这样的应用中实际上所有的运行时间都将花费在读进输入文件和写出压缩文件所需要的磁盘I/O上。
2.分治算法
实例:最大子序列和,平面几何最近点,树递归遍历,归并排序,快速排序,快速选择
分治算法的运行时间方程可归结为 : T(N)=aT(N/b)+Θ(N^k)。
最近点问题可将点集按照x坐标和y坐标排序,将点集按x分为两半,PL和PR,分别计算dL、dR和dC,dC时间为O(N),因此总时间为O(NlogN)。
整数相乘(两个八位整数X,Y)常规是O(N^2)。
有4次相乘
,将问题缩小为(N/2)。四次相乘可以减少为3次:
由此,T(N)=3T(N/2)+O(N)=O(N^1.59)。
矩阵乘法常规为Ω(N^3),代码如下。
可采用Strassen方法降阶。
3.动态规划
实例:用表代替递归,矩阵乘法的顺序安排,最优二叉查找树,有向图中所有点对最短路径(稠密图)
将递归算法重新写成非递归算法,可以把子问题的答案系统地记录在一个表中,利用这种方法的一种技巧称为动态规划。
计算fibonacci数列的递归和动态规划代码:
最优二叉查找树公式如下O(N^3),可优化为O(N^2):
所有点对最短路径(稠密图)公式O(N^3):
,
代码:
4.随机化算法
实例:跳跃表,随机素性测试
生成随机数的代码:
跳跃表:以O(logN)期望支持查找和插入。
素性测试:随机化方法极快,偶尔会出现错误的判断,但这种机会非常小,足可忽略。
5.回溯算法
实例:公路收费点重建问题(O(N^2 * logN)),博弈(极大极小策略,α-β裁剪)
实例:Dijkstra算法,Prim算法,Kruskal算法,调度(最小化平均完成时间),哈夫曼编码,装箱算法
哈夫曼编码采用最小堆实现时,运行时间为O(C log C),采用简单链表为O(C^2)。在ASCII字符集的情况下,C足够小,这使得二次时间可以接受,这样的应用中实际上所有的运行时间都将花费在读进输入文件和写出压缩文件所需要的磁盘I/O上。
2.分治算法
实例:最大子序列和,平面几何最近点,树递归遍历,归并排序,快速排序,快速选择
分治算法的运行时间方程可归结为 : T(N)=aT(N/b)+Θ(N^k)。
最近点问题可将点集按照x坐标和y坐标排序,将点集按x分为两半,PL和PR,分别计算dL、dR和dC,dC时间为O(N),因此总时间为O(NlogN)。
整数相乘(两个八位整数X,Y)常规是O(N^2)。
有4次相乘
,将问题缩小为(N/2)。四次相乘可以减少为3次:
由此,T(N)=3T(N/2)+O(N)=O(N^1.59)。
矩阵乘法常规为Ω(N^3),代码如下。
matrix<int> operator*(const matrix<int>& a,const matrix<int>& b) { int n=a.numrows(); matrix<int> c(n,n); int i; for(i=0;i<n;i++) for(int j=0;j<n;j++) c[i][j]=0; for(i=0;i<n;i++) for(int j=0;j<n;j++) for(int k=0;k<n;k++) c[i][j]+=a[i][k]*b[k][j]; return c; }
可采用Strassen方法降阶。
3.动态规划
实例:用表代替递归,矩阵乘法的顺序安排,最优二叉查找树,有向图中所有点对最短路径(稠密图)
将递归算法重新写成非递归算法,可以把子问题的答案系统地记录在一个表中,利用这种方法的一种技巧称为动态规划。
计算fibonacci数列的递归和动态规划代码:
int fib(int n) { if(n<=1) return 1; else return fib(n-1)+fib(n-2); } int fibonacci(int n) { if(n<=1) return 1; int last=1; int nextToLast=1; int answer=1; for(int i=2;i<=n;i++) { answer=last+nextToLast; nextToLast=last; last=answer; } return answer; }
最优二叉查找树公式如下O(N^3),可优化为O(N^2):
所有点对最短路径(稠密图)公式O(N^3):
,
代码:
void allPairs(matrix<int>& a,matrix<int>& d,matrix<int>& path) { int n=a.numrows(); //initialize d and path for(int i=0;i<n;i++) for(int j=0;j<n;j++) { d[i][j]=a[i][j]; path[i][j]=-1; } for(int k=0;k<n;k++) //consider each vertex as an intermediate for(int i=0;i<n;i++) for(int j=0;j<n;j++) if(d[i][k]+d[k][j]<d[i][j]) { //update shortest path d[i][j]=d[i][k]+d[k][j]; path[i][j]=k; } }
4.随机化算法
实例:跳跃表,随机素性测试
生成随机数的代码:
static const int A=48271; static const int M=2147483647;//2^31-1 static const int Q=M/A; static const int R=M%A; class Random { public: explicit Random(int initialValue=1); int randomInt(); double random0_1(); int randomInt(int low,int high); private: int state; }; //Construct with initialValue for state Random::Random(int initialValue) { if(initialValue<0) initialValue+=M; state=initialValue; if(state==0) state=1; } //period M-1 int Random::randomInt() { int tmpState=A*(state%Q)-R*(state/Q); if(tmpState>=0) state=tmpState; else state=tmpState+M; return state; } double Random::random0_1() { return (double)randomInt()/M; } int Random::randomInt(int low,int high) { if(low>high) return -1; return randomInt()%(high-low+1)+low; }
跳跃表:以O(logN)期望支持查找和插入。
素性测试:随机化方法极快,偶尔会出现错误的判断,但这种机会非常小,足可忽略。
5.回溯算法
实例:公路收费点重建问题(O(N^2 * logN)),博弈(极大极小策略,α-β裁剪)
相关文章推荐
- 常用算法设计方法
- 算法设计技巧与分析
- (算法设计技巧与分析)LinearSearch
- 20个常用Expression Blend设计开发技巧 (1)
- 设计技巧1:策略模式 Strategy 把整个算法替换掉
- 40种网站设计常用技巧
- 40种网站设计常用技巧(转)
- (算法设计技巧与分析)LCS
- 一些常用的算法技巧总结
- 算法设计之五大常用算法设计方法总结
- 40种网站设计常用技巧
- 常用算法设计方法之动态规划法
- 网页设计常用的一些技巧
- 40种网站设计常用技巧
- 关于数据库索引设计的几个常用算法
- 40种网站设计常用技巧
- 算法设计技巧:dovetailing
- 常用算法设计方法
- 40种网站设计常用技巧
- 40种网站设计常用技巧