/*递归最简单的形式是将规模为n的问题分解成一个或多个较小规模(n-1,n/2,n/3)的子问题,子问题
拥有和原问题相同的结构,求解子问题的解并组合起来,就是原问题的解.
有三种基本形式
1.归纳法(尾递归)
2.无重叠子问题
3.允许空间来换时间的重叠子问题
在这里,先开始归纳法的应用(尾递归)*/
#include <iostream>
using namespace std;
/*递归选择排序
要求 : 将无序数组按从小到大排序
选择排序概念 : 每次遍历找出当前队列中的最小数,并放在当前队列开头,移动一位,继续查找
递归选择 : A[1..n]->A[2..n]->...->A[n](递归基础)
问题 : 为什么递归基础是A[n],而不是A[1],即A[1..n]->A[1..n-1]->...->A[1](如何缩小规模,包括方向之类)
回答 : 主要是考虑插入时数组移位的情况,从哪里开始比较(从左到右或从右到左),待插入的数字最好放在开始比较的一侧,
如当前数组规模为m,插入的位置为i,则需要移位操作i和比较次数i.(如果放在另一侧,则有移位操作m-i和比较次数i)
如果考虑到插入的位置i是均匀分布的话,则m-i和i的平均次数是相同的,即放在左右两侧没有区别.
但是很明显的是i的值普遍偏小(为什么),因此要把待插入的值放在数组开始比较的一侧.
延伸问题 : 一个待插入的数字a(随机数)和一个有序的数组A[1...m](从小到大),从"左"开始比较,找到待插入的位置i,
请问i<m/2(位于左侧)的概率是多少,i>m/2的概率是多少?如果产生A[1...m+1],再插入一个随机数b,概率又是多少?
猜测 : 继续插入的位置i会偏小,在左侧的概率大.也有可能概率一样.
*/
void SelectionSortRec(int *a,int n,int i)//a[]表示无序数组,i表示第i个元素,数组上是a[i-1],默认a[i...n-1]为有序数组
{
if (i==n)return;//递归基础
SelectionSortRec(a,n,i+1);//a[i...n]为有序数组
int temp=a[i-1];
int k = i;//开始比较的坐标
while(k <= n-1 && a[k] < temp ) {//比较并移位,界限为k <= n-1,放在前面
a[k-1] = a[k];
k++;
}
//可以改进,因为a[k-1] =temp; 在k=n 的时候为a[n-1] = temp;
/*if (k == n )
{
a[n-1] = temp;
}
else
{
a[k-1] = temp;
}*/
a[k-1] = temp;
}
//书本方法sort(1)表示a[1...n]有序
void Sort(int *a,int n,int i)//a是数组,i表示待插入的数为a[i-1],默认a[i...n-1]为有序
{
if(i==n)return;
//int temp=a[i-1];
int k=i-1;//当前最小的坐标
for (int j = i; j <= n-1 ; ++j)
{
if (a[j] < a[k])
{
k=j;
}
}
if (k == i-1)return;
//交换
int temp = a[k];
a[k] = a[i-1];
a[i-1] = temp;
Sort(a,n,i+1);
}
/*递归插入排序
目标 : 无序数组转化为有序数组(从小到大)
插入排序 : 每次默认前面的数字是有序的,从末尾开始比较,小于则数字后移,直到找到大于的数字后插入,再次循环
递归插入 : A[1...n]->A[1..n-1]->...->A[1](递归基础)
问题 : 为什么递归基础是A[1]?
回答 : 同上,从数组哪侧开始比较,则待插入的数字最好在那一侧.
*/
void InsertionSortRec(int *a,int i)//a[]表示无序数组,i表示待插入的数字位置a[i-1],默认a[0..i-2]为有序
{
//递归基础
if (i==1)return;
InsertionSortRec(a,i-1);
int temp = a[i-1];//待插入值放在temp中
int k = i-2;//开始比较的坐标
while(k >= 0 && a[k] > temp ) {//比较并移位,界限为k >= 0,但是会出现越界行为a[-1],调试过程中出现a[-1]=-8123423,不可应将k >= 0 放在前面
a[k+1] = a[k];
k--;
}
//理由同上,改进
/*if (k < 0 )
{
a[0] = temp;
}
else
{
a[k+1] = temp;
}*/
a[k+1] = temp;
}
//测试
int main(int argc, char const *argv[])
{
int a[]={1,3,4,6,7,8,9,0,2,5};
Sort(a,10,1);
for (int i = 0; i < 10; ++i)
{
cout<<a[i]<<" ";
}
system("pause");
return 0;
}