递归选择和插入排序

/*递归最简单的形式是将规模为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;
 }
posted @ 2016-08-30 08:31  jiangge3  阅读(396)  评论(0)    收藏  举报