要把选择排序想像成一个人机械地一张一张地排一幅扑克牌的过程。一张一张抓,确保手里的牌都是有序的,抓进来的牌插到合适的位置。
插入排序在动态过程中,会将整个数组分成“已排序部分“与“未排序部分两个部分”。
int a[] = {8,3,1,5,2,1};
① 8是有序的,3,1,5,2,1无序,无序的第一个元素3,去找要插入的位置,变成{3,8,1,5,2,1}
② 第三个元素要找插入的位置,应该是找到第0个位置,3、8各后移一个位置,1插入到3移动后留下的位置。变成{1,3,8,5,2,1}
如何用计算机的机械逻辑思维描述这一过程?
设未排序的部分的第一个位置的下标值是i,v = a[i](暂存,前一个位置后移时会被替换),前一个元素的下标值j=i-1,i--移动下标位置,v[j](动态值,因为循环中的v--)与v(在一次循环中固定)比较,挨个比较,如果v[j]>v且j>=0,则v[j]后移一个位置,也就是v[j+1]=v[j],最后在空出的位置插入:a[j+1] = v;
代码如下:
int i,j,v;v=a[i];j=i-1;while(a[j]>v && j>=0){ a[j+1] = a[j];//后移 j--; //移动下标位置}a[j+1] =v; //插入
一个循环完成了一个元素的插入,外面再套一个循环就可以完成整个数组的排序。
int i,j,v;for(i =1; iv && j>=0) { a[j+1] = a[j]; j--; } a[j+1] =v;}
再封装到函数:
void insert(int a[], int n){ int i,j,v; for(i =1; iv && j>=0) { a[j+1] = a[j]; j--; } a[j+1] =v; }}
我们阅读双重循环时,也要从内循环开始去读。
整个程序:
#include using namespace std;void output(int a[], int n){ for(int i=0; iv && j>=0) { a[j+1] = a[j]; j--; } a[j+1] =v; output(a,n); }}void main(){ int a[] = {8,3,1,5,2,1}; int n=sizeof(a)/sizeof(a[0]); output(a,n); insert(a,n); cin.get();}
/* 输出:
8 3 1 5 2 1
3 8 1 5 2 1
1 3 8 5 2 1
1 3 5 8 2 1
1 2 3 5 8 1
1 1 2 3 5 8
*/
选择排序也插入排序也有一定的相似性。
选择排序在动态过程中,也会将整个数组分成“已排序部分“与“未排序部分两个部分”。
也可以用抓牌来类比,就像一堆牌,选择最小,然后在剩下的无序的牌中再选择最小,手上的牌也是有序的。
内循环(一次选牌过程)可以描述为:
int i; // 无序组中第一个元素的下标值int minj,j;for(j = i; j-End-