以选择排序为例
选择排序的思路就是找最小排在最前面。
问题分析:
设f(a,n,i+1)用于对a(i…n-1)元素序列(共n-i-1个元素)进行简单选择排序,是“大问题”。
f(a,n,i+1)用于对a[i+1…n-1]元素序列(共n-i-1个元素)进行简单选择排序,是“小问题”。
当i=n-1时所有元素有序,算法结束。
递归模型:
当i=n-1; f(a,n,i)=不做任何事情,算法结束
否则 f(a,n,i)=通过简单比较挑选a[i…n-1]中最小元素a[k]放在a[i]的位置;f(a,n,i+1)
选择排序递归实现:
#include<stdio.h>
void swap(int &x,int &y)
{
int t = x;
x = y;
y = t;
}
//a:待排序的整型数组
//n:a中元素的数量
//i:参与选择排序的起始元素的下标
//算法作用:对a[i],a[i+1],...,a[n-1]这些元素进行选择排序
void SelextSort(int a[], int n, int i)
{
int j,k;
if(i == n - 1)//即待排序的元素只有a[n-1]1个元素,无需排序,为递归出口
return;
k = i;//默认a[i]是a[i...n-1]中最小的元素
for(int j = i + 1;j < n;j ++)//循环遍历a[]中从a[i]后一个开始的所有数据
{
if(a[j] < a[k])//如果找到一个比a[i]小的数据,说明a[i]不是最小的
k = j;//更新k的值
}
//至此,a[i...n-1]中最小元素的下标已求出,为k
if(k != i)//如果最小元素不是a[i]
swap(a[i],a[k]); //将a[k]换到a[i]的位置
SelextSort(a, n, i + 1); //递归体,待排序的元素减少1个
//问题规模减1
}
void display(int a[],int n)
{
for(int i = 0; i < n; i++)
printf("%d ",a[i]);
printf("\n");
}
int main()
{
int a[10]= {3,1,2,7,4,5,8,6,9,10};
printf("排序前:");
display(a,10);
SelextSort(a,10,0);
printf("排序后:");
display(a,10);
}
以冒泡排序为例
对于给定的含有n个元素的数组a,采用冒泡排序方法对其按元素值递增排序。
冒泡排序的思路是通过比较,一趟比较把最小的浮动到最前面,每一趟结束就确定一个数的位置。
问题分析
设f(a,n,i)用于对a[i…n-1]元素序列(共n-i个元素)进行冒泡排序,是“大问题”。
f(a,n,i+1)用于对a[i+1…n-1]元素序列(共n-i-1个元素)进行冒泡排序,是"小问题"。
当i=n-1时所有元素有序,算法结束。
递归模型
当 i=n-1 f(a,n,i)=不做任何事情,算法结束
否则 f(a,n,i)=对于a[i…n-1]元素序列,从a[n-1]开始进行相邻元素比较;若相邻两元素反序则将两者交换;若没有反序则返回,否则执行f(a,n,i+1)
冒泡排序递归实现:
#include<stdio.h>
void swap(int &x,int &y)
{
int t = x;
x = y;
y = t;
}
//a:待排序的整型数组
//n:a中元素的数量
//i:参与冒泡排序的起始元素的下标
//算法作用:对a[i],a[i+1],...,a[n-1]这些元素进行冒泡排序(从小到大)
void BubbleSort(int a[], int n, int i)
{
int j;
bool exchange;//用于记录一趟冒泡排序中是否发生过元素交换
if(i == n - 1)//如果待排序元素只有a[n-1]1个,无需排序,为递归出口
return;
exchange=false;
for(j = n - 1; j > i; j --)//从后往前,让小元素往前移动
{
if(a[j] < a[j - 1])
{
swap(a[j],a[j-1]);
exchange=true;//标记已经发生过交换
}
}
if(exchange==false)//如果在上面的循环中没有交换元素,说明顺序已经对了,排序提前完成
return;
BubbleSort(a, n, i+1);//递归体,待排序的元素减少到a[i+1...n-1]
//问题规模减1
}
void display(int a[],int n)
{
for(int i = 0; i < n; i++)
printf("%d ",a[i]);
printf("\n");
}
int main()
{
int a[]= {1,3,2,7,6,4,5,9,8,10};
printf("排序前:");
display(a,10);
BubbleSort(a,10,0);
printf("排序后:");
display(a,10);
return 0;
}
求解n皇后问题
结果我们用一个*整型数组q[]*来保存,q[i]表示第i行的皇后摆在第几(q[i]的值)列。
C语言递归实现:
#include<stdio.h>
#include<stdlib.h>
#define N 20 //最多皇后个数
int q[N]; //存放各皇后所在的列号,即(i,q[i])为一个皇后位置
int count = 0; //累计解的个数
void dispasolution(int n)//输出n皇后问题的一个解
{
printf(" 第%d个解:",++count);
for(int i = 1; i <= n; i ++)
printf("(%d,%d)",i,q[i]);
printf("\n");
}
bool place(int i, int j) //猜测是(i,j)位置能否拜访皇后
{
if(i == 1)//第一个皇后总是可以放置的
return true;
int k = 1;
while(k < i) //k = 1~i-1是已放置了皇后的行
{
if(q[k] == j||abs(q[k]-j) == abs(i-k))//构成等腰三角形,两个皇后将在对角线上
return false;
k ++;
}
return true;
}
//i:要放置皇后的起始行
//n:要放置皇后的结束行
//算法作用:在n*n的棋盘上的第i行,第i+1行,...,第n行各放置一个皇后
//在任意第k行放置的皇后,都不能喝第1行,第二行,。。。,第k-1行
//所放置的皇后形成互相攻击的形态
void queen(int i, int n)
{
if(i > n) // n个皇后已经防止完毕,递归出口
dispasolution(n);//输出刚得到的解
else
{
for(int j = 1; j <= n; j ++)//在第i行上试探每一个列j
{
if(place(i, j) == true)//在第i行上找到一个合适位置(i,j)
{
q[i] = j;
queen(i + 1, n); //递归调用,在第i+1,i+2,...,n行各放置一个皇后
}
}
}
}
int main()
{
int n;//n为存放世纪皇后个数
printf("皇后问题(n<20) n=");
scanf("%d",&n);
if(n > 20)
{
printf("n值太大,不能求解\n");
}
else
{
printf("%d皇后问题求解如下 :\n",n);
queen(1, n);//放置1~n的皇后
}
return 0;
}