数据结构:递归 算法分析
2007-05-21 13:29
232 查看
使用递归的四个法则:
1.基准情形(Base case):必须总有某种基准情形,它无须递归就能解出.
2.不断推进(Making progress):对于那些需要递归求解的情形,每一次递归调用都必须要使求解状况朝接近基准的情形的方向推进.
3.设计法则:假设所有的递归调用都能运行.
4.合成效益法则:在求解一个问题的同一实例时,切勿在不同的递归调用中做重复性的工作.
关于算法运行时间的几个法则:
法则1-For 循环:
一次For循环的运行时间至多是该For循环内语句(包括测试)的运行时间乘迭代的次数.
example 01 O(N):
for(int i=0;i<n;i++)
printf("%d",i);
法则2-嵌套的For循环:
从里向外分析这些循环,在一组嵌套循环内部的一条语句的运行时间为该语句的运行时间乘以该组所有的for循环的大小的乘积.
example 02 O(N2):
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
printf("%d",j)
法则3-顺序语句:
将各个语句的运行时间求和即可(这意味着,其中最大的值就是所得的运行时间)
example 03 O(N2)
for(i=0;i<n;i++)
a[i]=i;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
a[i]+=a[j]+1
法则4-IF ELSE语句:
一个IF/ELSE语句的运行时间从不超过判断再加上S1和S2中运行时间长者的总的运行时间.
if(Condition )
S1
else
S2
两个递归的漂亮应用:
1. 最大子序列和问题:O(NlogN)
static int MaxSubSum(const int a[],int Left,int Right)
{
int MaxLeftSum,MaxRightSum;
int MaxLeftBorderSum,MaxRightBorderSum;
int LeftBorderSum,RightBorderSum;
int Center,i;
//Base case
if(Left == Right)
if(a[left]>0)
return a[left];
else
return 0;
Center = (Left + Right)/2;
MaxLeftSum = MaxSubSum(a[],Left,Center);
MaxRightSum = MaxSubSum(a[],Center+1,Right);
MaxLeftBorderSum = 0; LeftBorderSum =0;
for(i=Center;i>=Left;i--)
{
LeftBorderSum +=a[i];
if(LeftBorderSum >MaxLeftBorderSum)
MaxLeftBorderSum = LeftBorderSum;
}
MaxRightBorderSum = 0;RightBorderSum =0;
for(i=Center+1;i<=Right;i++)
{
RightBorderSum +=a[i];
if(RightBorderSum>MaxRightBorderSum)
MaxRightBorderSum = RightBorderSum;
}
return Max3(MaxRightSum,MaxLeftSum,MaxLeftBorderSum+MaxRightBorderSum);
}
int MaxSubsqeenceSum(const int a[],int n)
{
return MaxSubSum(a,0,n-1);
}
2. 幂运算:O(logN)
long int Pow(long int x,int n)
{
//Base case
if(n=0)
return 1;
if(n=1)
return n;
if(IsEven(N))
return Pow(x*x,n/2);
else
return Pow(x,n-1)*x;
}
两个经典算法:
1.二分查找:O(logN)
int BinarySearch(const ElementType a[],Element x,int n)
{
int low,mid,high;
low =0;high = n-1;
while(low<=high)
{
mid=(high-low)/2;
if(a[mid] > x)
low = mid+1;
else
if(a[mid]<x)
high = mid-1;
else
return mid;
}
return -1;
}
2.欧几德时算法,求两个数的最多公因数Gcd: O(logN)
int Gcd(int m,int n)
{
int rem;
while(n>0)
{
rem = m%n;
m=n;
n=rem;
}
4000
return m;
}
1.基准情形(Base case):必须总有某种基准情形,它无须递归就能解出.
2.不断推进(Making progress):对于那些需要递归求解的情形,每一次递归调用都必须要使求解状况朝接近基准的情形的方向推进.
3.设计法则:假设所有的递归调用都能运行.
4.合成效益法则:在求解一个问题的同一实例时,切勿在不同的递归调用中做重复性的工作.
关于算法运行时间的几个法则:
法则1-For 循环:
一次For循环的运行时间至多是该For循环内语句(包括测试)的运行时间乘迭代的次数.
example 01 O(N):
for(int i=0;i<n;i++)
printf("%d",i);
法则2-嵌套的For循环:
从里向外分析这些循环,在一组嵌套循环内部的一条语句的运行时间为该语句的运行时间乘以该组所有的for循环的大小的乘积.
example 02 O(N2):
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
printf("%d",j)
法则3-顺序语句:
将各个语句的运行时间求和即可(这意味着,其中最大的值就是所得的运行时间)
example 03 O(N2)
for(i=0;i<n;i++)
a[i]=i;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
a[i]+=a[j]+1
法则4-IF ELSE语句:
一个IF/ELSE语句的运行时间从不超过判断再加上S1和S2中运行时间长者的总的运行时间.
if(Condition )
S1
else
S2
两个递归的漂亮应用:
1. 最大子序列和问题:O(NlogN)
static int MaxSubSum(const int a[],int Left,int Right)
{
int MaxLeftSum,MaxRightSum;
int MaxLeftBorderSum,MaxRightBorderSum;
int LeftBorderSum,RightBorderSum;
int Center,i;
//Base case
if(Left == Right)
if(a[left]>0)
return a[left];
else
return 0;
Center = (Left + Right)/2;
MaxLeftSum = MaxSubSum(a[],Left,Center);
MaxRightSum = MaxSubSum(a[],Center+1,Right);
MaxLeftBorderSum = 0; LeftBorderSum =0;
for(i=Center;i>=Left;i--)
{
LeftBorderSum +=a[i];
if(LeftBorderSum >MaxLeftBorderSum)
MaxLeftBorderSum = LeftBorderSum;
}
MaxRightBorderSum = 0;RightBorderSum =0;
for(i=Center+1;i<=Right;i++)
{
RightBorderSum +=a[i];
if(RightBorderSum>MaxRightBorderSum)
MaxRightBorderSum = RightBorderSum;
}
return Max3(MaxRightSum,MaxLeftSum,MaxLeftBorderSum+MaxRightBorderSum);
}
int MaxSubsqeenceSum(const int a[],int n)
{
return MaxSubSum(a,0,n-1);
}
2. 幂运算:O(logN)
long int Pow(long int x,int n)
{
//Base case
if(n=0)
return 1;
if(n=1)
return n;
if(IsEven(N))
return Pow(x*x,n/2);
else
return Pow(x,n-1)*x;
}
两个经典算法:
1.二分查找:O(logN)
int BinarySearch(const ElementType a[],Element x,int n)
{
int low,mid,high;
low =0;high = n-1;
while(low<=high)
{
mid=(high-low)/2;
if(a[mid] > x)
low = mid+1;
else
if(a[mid]<x)
high = mid-1;
else
return mid;
}
return -1;
}
2.欧几德时算法,求两个数的最多公因数Gcd: O(logN)
int Gcd(int m,int n)
{
int rem;
while(n>0)
{
rem = m%n;
m=n;
n=rem;
}
4000
return m;
}
相关文章推荐
- 汉诺塔问题递归算法分析:
- Weiss的数据结构与算法分析(C++版)源码编译说明
- 【数据结构和算法分析】循环链表及约瑟夫问题
- 【数据结构和算法分析】栈与逆波兰式
- [置顶] 【数据结构】算法时间复杂度分析
- 算法分析之递归
- 数据结构和算法分析习题解答之一——引言
- 【算法数据结构Java实现】递归的简单剖析及时间复杂度计算
- 算法与数据结构-------递归查找最大元素
- 常用算法的递归实现问题分析(针对《数据结构与程序设计》by Robert.L.Kruse)
- 算法设计课程总结1~2(渐进分析记号,复杂性比较,递归,分治)
- 数据结构&算法——递归
- 算法,数据结构分析
- Hanoi Tower汉诺塔问题函数递归算法分析及相应python代码
- [Java算法分析与设计]二叉树非递归实现遍历
- MP3解码算法分析——MP3帧头(Frame Header)数据结构描述
- 常用的算法和数据结构分析(查找和排序)
- 数据结构习题分析:已知由一个线性链表表示的线性表中含有三类字符的数据元素,是编写算法将该线性表分割为三个循环链表,其中每个。。。。。
- 学好数据结构和算法 —— 复杂度分析
- 算法与数据结构基础系列(一): 链表的常见问题分析及实现