排序概念:把不规则的一推事物,按关键字的递增或递减进行排序。
排序稳定性:如果排序的文件中,有相同的关键字,则排序后的这些相同的关键字的相对次序是否改变。
排序方法分类:内部排序(只在内存中),外部排序(内存和外存皆有)。
排序算法性能评价:时间复杂度和空间复杂度。
插入排序:把一个关键字取出,与有序区进行比较后,插入指定位置,在其后的关键字移位,如扑克牌的排序。
直接插入排序:把要排序的关键字当成哨兵,用此哨兵与前面的数进行比较,达成要求后,插入,并向后移位,再把哨兵移动正确位置。
void InsertSort(int a[]){
int i,j; //i为数组遍历变量,j为换位变量
for(i=2;i<a.length;i++){
a[0] = a[i]; //a[0]为哨兵
for(j = i - 1; a[0] < a[j] ; j--){
a[j+1] = a[j]; //向后移动一位
}
a[j+1] = a[0]; //插入正确位置
}
}
示例: 对 3 4 1 2 进行递增排序
第一步:( 3,4已经是有序,所以忽视)把循环遍历到1, 提取1为哨兵,赋值于a[0]。
第二步:用1跟前面的数先跟4比较,比其小,则4向后移动一位,所以现在是 3 4 4 2. 再按同样方法比较3 所以现在是 3 3 4 2.
第三部,由于最后一次j–又运行了一次,所以现在我们要插入的位置实际上是上一次j的值,所以把哨兵赋值给a[j+1]。执行完后,现在是1 3 4 2.
按上述方法执行多一次,就能得出 1 2 3 4 (读者自己思考一下)。
希尔排序:以一个变量t来定組排序(组中的排序为直接插入排序),每次以t逐步减少的方法进行,直到t=1则排序结束。实则为分组化的直接插入排序,以直接插入排序的思想,既能得出。
void ShellPass(int a[],int t){
int i,j;
for(i=1+t;i<a.length;i++){
a[0]=a[i];
for(j=i-t;j>0&&a[0]<a[j];j=j-t){
a[j+t]=a[j];
}
a[j+t]=a[0];
}
}
void ShellSort(int a[]){
int t=5; //t的值大于1即可
for(t;t>=1;t--){ //改变t的值且逐步改变希尔的分组。
ShellPass(a,t);
}
}
示例:与直接插入类似,只是为分组插入,最后汇总为一组再插入,在此不举例说明。
交换排序:两两关键字进行比较,按大或小的规律进行交换,依次执行,直到达成目标。
冒泡排序: 把一个关键字,由上向下,或由下向上的方式,把一个关键字,依递增或递减的方式排在头位。依次循环操作,得出结果,就像泡沫一样一次冒在前头。
void BubbleSort(int a[]){
int i,j,t;
for(i=0;i<a.length;i++){
for(j=0;j<a.length-1-i;j++){
if(a[j]>a[j+1]){
t=a[j+1];
a[j+1]=a[j];
a[j]=t;
}
}
}
}
示例:对2,1,5,3,0进行递增排序。
第一步:i为0,所以是2开始,j+1为1;所以比较的是 2 和 1,因为2大于1,所以2,1交换,为1,2接着,比较,2跟5,再比较5跟3,再比较5跟0,最后第一次i=0的循环结果为1,2,3,0,5;
第二步:i为1,所以是2开始,2,3比较,3,0,比较,3,5比较。结果为1,2,0,3,5;
接下来一次进行,可得出结果,0,1,2,3,5;
(因为i=0,开始,所以小于a.length。从上面可得出,每次交换的次数刚好是总数减去当前位置的值,所以是a.length-1-i)