*递归函数的概念*
函数用自身给出定义的函数
分治法要素
(1)将一个规模较大的问题划分成规模小的相同子问题。
(2)求子问题的解(子问题独立),从而解决原问题的解。
以下是递归函数的实例
1。阶乘函数
阶乘函数可递归地定义为:
n!={1,n=0;n(n-1)! ,n>0}
递归函数的自变量n的定义域为非负整数,递归式的第一式给出了这个函数的初值,是非递归的定义。每个递归函数都必须是由非递归定义的初始值,否则无法计算。递归式的第二式使用较小的变量的函数值来表达较大的自变量的函数值的方式来定义n的阶乘。
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
2.Fibonacci数列
无穷数列1,1,2,3,5,8,13,21,34,.......................,称为Fibonacci数列。他可以递归的定义为:
F(n)={1,n=0,1; F(n-1)+F(n-2), n>1}
这是一个递归关系式,他说明当n>1时,这个数列的第n项的值是它前面两项之和,他用较小的自变量的函数值定义较大自变量的函数值,所以只需要连个初始值F(0)和F(1)。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
4.Hanoi问题
设a,b,c是三个塔座。开始时,在塔座a上有一叠共n个圆盘,这些圆盘自上而下,从大到小叠在一起,各圆盘从小到大编号为1,2,................n。
(1)每次只能移动1个圆盘
(2)任何时刻都不允许将较大的圆盘压在较小的圆盘之上。
(3)在满足以上规则的前提下,可将圆盘移至a,b,c中任何一塔座上。
解决方法:
当n=1时,将编号为1的圆盘从塔座上a直接移至b上。
当n>1时,需要借助塔座c作为辅助塔座,将n-1个较小的圆盘依照规则从塔座a移至塔座c,然后将剩下的最大圆盘从a移至b,最后设法将n-1个较小的圆盘依照规则从塔座c移至b。由此看出来,n个圆盘的移动问题可分为两次n-1个圆盘的移动问题,
算法:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
5.合并排序
合并排序算法是用分治策略实现对n个元素进行排序的算法,基本思想是分成大小大致相同的2个集合,分别对2个子集合进行排序,最终将排好序的子集合合并成为要求的排好序集合。
算法:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
6.快速排序
基本思想是:对于输入的子数组a[p:r],按照以下三个步骤进行排序:
(1)分解,以a[p]为基准元素将a[p:r]划分成3段a[p:q-1],a[q]和a[q+1:r],使得a[q-1:r]中任何元素小于等于a[q],a[q+1:r]中任何元素大于等于a[q]。下标q在划分过程中确定。
(2)递归求解,通过递归调用快速排序算法,分别对a[p:q-1]和a[q+1:r]进行排序。
(3)合并,由于对a[p:q-1]和a[q+1:r]的排序是就地进行排序的,所以在a[p:q-1]和a[q+1:r]都已排好的序后不需要执行任何计算,a[p:r]就已排好序。
算法:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
7.线性时间选择
划分基准:
(1)将n个输入元素划分为[n/5]个组,每组5个元素,只可能有一个组不是5个元素。用任意一种排序算法,将每组中的元素排好序,并取出每组的中位数,共[n/5]个。
(2)递归调用算法select来找出这[n/5]个元素的中位数,如果[n/5]是偶数,就找出他的两个中位数中较大的一个,以这个元素作为划分基准。
- 1
- 1
pravite static Compareabe select(int p,int r,int k)
//p是第一个元素,r是最后一个元素,k表示第k小
{
if(r-p<5)//至少5个元素
//用某个简单排序算法对数组a[p:r]排序
bubbleSort(p,r);//冒泡排序
return a[p+k-1];
}
//将a[p+5*i]至a[p+5*i+4]的第3小元素
//与a[p+i]交换位置
//找中位数的中位数,r-p-4即就是上面说的n=5。
for(int i=0;i<=(r-p-4)/5;i++)//控制分组
{
//s是首元素,t是最后一个元素
int s=p+5,
t=s+4;
for(int j=0;j<3;j++)
bubbleSort(s,t-j);
//p+2代表首元素,s+2代表中位数。
MyMath.swap(a,p+i,s+2);
}
Compareable x=select(p,p+(r-p-4)/5,(r-p+6)/10);
//找中位数
int i=partition(p,r,x);
j=i-p+1;
if(k<=j)
return select(p,i,k);
else return select(i+1,r,k-j);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
public static int binarySearch(int [] a,int x,int n)
{
//在a[0]<a[1]<..............<a[n-1]中搜索x
//找到x时返回其在数组中的位置,否则返回-1
int left=0;
int right=n-1;
while(left<right)
{
int middle=(left+right)/2;
if(x==a[middle])
return middle;
if(x>a[middle])
left=middle+1;
else right=middle-1;
}
return -1;//没有找到
}