```````````````````````````````````````````````````````````````````````````````````````````````1. 快速排序Quick sort
注意: 被替换的位置要空出来。留给其他。
快速排序是对冒泡排序的一种改进。它的基本思想是:通过一躺排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一不部分的所有数据都要小,然后再按次方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
假设要排序的数组是A[1]……A[N],首先任意选取一个数据(通常选用第一个数据)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一躺快速排序。一躺快速排序的算法是:
1)、设置两个变量I、J,排序开始的时候I:=1,J:=N;
2)以第一个数组元素作为关键数据,赋值给X,即X:=A[1];
3)、从J开始向前搜索,即由后开始向前搜索(J:=J-1),找到第一个小于X的值,两者交换;
4)、从I开始向后搜索,即由前开始向后搜索(I:=I+1),找到第一个大于X的值,两者交换;
5)、重复第3、4步,直到I=J;
例如:待排序的数组A的值分别是:(初始关键数据X:=49)
A[1] A[2] A[3] A[4] A[5] A[6] A[7]:
49 38 65 97 76 13 27
进行第一次交换后: 27 38 65 97 76 13 49
( 按照算法的第三步从后面开始找
进行第二次交换后: 27 38 49 97 76 13 65
( 按照算法的第四步从前面开始找>X的值,65>49,两者交换,此时I:=3 )
进行第三次交换后: 27 38 13 97 76 49 65
( 按照算法的第五步将又一次执行算法的第三步从后开始找
进行第四次交换后: 27 38 13 49 76 97 65
( 按照算法的第四步从前面开始找大于X的值,97>49,两者交换,此时J:=4 )
此时再执行第三不的时候就发现I=J,从而结束一躺快速排序,那么经过一躺快速排序之后的结果是:27 38 13 49 76 97 65,即所以大于49的数全部在49的后面,所以小于49的数全部在49的前面。
快速排序就是递归调用此过程——在以49为中点分割这个数据序列,分别对前面一部分和后面一部分进行类似的快速排序,从而完成全部数据序列的快速排序,最后把此数据序列变成一个有序的序列,根据这种思想对于上述数组A的快速排序的全过程如图6所示:
初始状态 {49 38 65 97 76 13 27}
进行一次快速排序之后划分为 {27 38 13} 49 {76 97 65}
#include <stdio.h>
void fast_sort(int *num, int n)
{
int low, hight;
int key;
int index;
if (n <= 1)
return;
n = n - 1;
index = 0;
low = 1;
hight = n;
key = num[0];
while (low < hight)
{
while (num[hight] > key)
hight--;
num[index] = num[hight];
index = hight;
hight--;
while (num[low] < key)
low++;
num[index] = num[low];
index = low;
low++;
}
num[index] = key;
fast_sort(num, index);
fast_sort(num + index + 1, n - index);
}
int main(void)
{
int num[] = {49, 38, 65, 97, 76, 13, 27};
fast_sort(num, 7);
int i;
for (i = 0; i < 7; ++i)
printf("%d ", num[i]);
printf("\n");
return 0;
}
2.经典排序算法 - 桶排序Bucket sort
经典排序算法 - 桶排序Bucket sort
补充说明三点
1,桶排序是稳定的
2,桶排序是常见排序里最快的一种,比快排还要快…大多数情况下
3,桶排序非常快,但是同时也非常耗空间,基本上是最耗空间的一种排序算法
我自己的理解哈,可能与网上说的有一些出入,大体都是同样的原理
无序数组有个要求,就是成员隶属于固定(有限的)的区间,如范围为[0-9](考试分数为1-100等)
例如待排数字[6 2 4 1 5 9]
准备10个空桶,最大数个空桶
[6 2 4 1 5 9] 待排数组
[0 0 0 0 0 0 0 0 0 0] 空桶
[0 1 2 3 4 5 6 7 8 9] 桶编号(实际不存在)
1,顺序从待排数组中取出数字,首先6被取出,然后把6入6号桶,这个过程类似这样:空桶[ 待排数组[ 0 ] ] = 待排数组[ 0 ]
[6 2 4 1 5 9] 待排数组
[0 0 0 0 0 0 6 0 0 0] 空桶
[0 1 2 3 4 5 6 7 8 9] 桶编号(实际不存在)
2,顺序从待排数组中取出下一个数字,此时2被取出,将其放入2号桶,是几就放几号桶
[6 2 4 1 5 9] 待排数组
[0 0 2 0 0 0 6 0 0 0] 空桶
[0 1 2 3 4 5 6 7 8 9] 桶编号(实际不存在)
3,4,5,6省略,过程一样,全部入桶后变成下边这样
[6 2 4 1 5 9] 待排数组
[0 1 2 0 4 5 6 0 0 9] 空桶
[0 1 2 3 4 5 6 7 8 9] 桶编号(实际不存在)
0表示空桶,跳过,顺序取出即可:1 2 4 5 6 9
#include <stdio.h>
void bucket_sort(int *a, int n)
{
int num[10];
int i;
for (i = 0; i < 10; ++i)
num[i] = 0;
for(i = 0; i < n; ++i)
num[a[i]] = 1;
for (i = 0; i < 10; ++i)
{
if (num[i])
printf("%d ", i);
}
printf("\n");
}
int main(void)
{
int num[] = {6, 2, 4, 1, 5, 9};
bucket_sort(num, 6);
return 0;
}
3.插入排序
包括: 直接插入排序,二分插入排序(又称折半插入排序),链表插入排序, 希尔排序(又称缩小增量排序)。基本思想
将n个元素的数列分为已有序和无序两个部分,如下所示: {,{a2,a3,a4,…,an}} {{a1⑴,a2⑴},{a3⑴,a4⑴ …,an⑴}} … {{a1(n-1),a2(n-1) ,…},{an(n-1)}} 每次处理就是将无序数列的第一个元素与有序数列的元素从后往前逐个进行比较,找出插入位置,将该元素插入到有序数列的合适位置中。
#include <stdio.h>
void insert_sort(int *num, int n)
{
int save[n];
int i;
int k;
int j;
save[0] = num[0];
for (i = 1; i < n; ++i)
{
k = 0;
while ((k < i) && (save[k] < num[i]))
k++;
for (j = i; j > k; --j)
save[j] = save[j - 1];
save[j] = num[i];
}
for (i = 0; i < n; ++i)
printf("%d ", save[i]);
printf("\n");
}
int main(void)
{
int num[] = {49, 27};
insert_sort(num, 2);
return 0;
}
4.经典排序算法 - 基数排序Radix sort
原理类似桶排序,这里总是需要10个桶,多次使用
首先以个位数的值进行装桶,即个位数为1则放入1号桶,为9则放入9号桶,暂时忽视十位数
例如
待排序数组[62,14,59,88,16]简单点五个数字
分配10个桶,桶编号为0-9,以个位数数字为桶编号依次入桶,变成下边这样
| 0 | 0 | 62 | 0 | 14 | 0 | 16 | 0 | 88 | 59 |
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |桶编号
将桶里的数字顺序取出来,
输出结果:[62,14,16,88,59]
再次入桶,不过这次以十位数的数字为准,进入相应的桶,变成下边这样:
由于前边做了个位数的排序,所以当十位数相等时,个位数字是由小到大的顺序入桶的,就是说,入完桶还是有序
| 0 | 14,16 | 0 | 0 | 0 | 59 | 62 | 0 | 88 | 0 |
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |桶编号
因为没有大过100的数字,没有百位数,所以到这排序完毕,顺序取出即可
最后输出结果:[14,16,59,62,88]
5.经典排序算法 - 鸽巢排序Pigeonhole sort
原理类似桶排序,同样需要一个很大的鸽巢[桶排序里管这个叫桶,名字无所谓了]
鸽巢其实就是数组啦,数组的索引位置就表示值,该索引位置的值表示出现次数,如果全部为1次或0次那就是桶排序
例如
var pigeonHole = new int[100];
pigeonHole[0]的值表示0的出现次数...
pigeonHole[1]的值表示1的出现次数...
pigeonHole[2]的值表示2的出现次数...
举例
var pigeonHole = new int[10];//10个位置
var A = new int[] { 6, 6, 2, 2, 2, 4, 1, 1, 1, 5, 5, 5, 5, 9 };//待排序数组
foreach (var item in A)
{
pigeonHole[item]++;//如pigeonHole[6]++会执行两次,结果为2
}
鸽巢索引:0 1 2 3 4 5 6 7 8 9
索引次数:0 3 3 0 1 4 2 0 0 1
//顺序输出
for (int i = 0; i < pigeonHole.Length; i++)//索引i就是值
{
//pigeonHole[i]处的值是数字i出现的次数
//如6出现了两次,那么pigeonHole[6] = 2
//0没出现,那么pigeonHole[0] = 0,表示待排数组里没有这个值:0
for (int j = 0; j < pigeonHole[i]; j++)//i出现就次就输出几个
{
Console.WriteLine(i);//1,1,1,2,2,2,4,5,5,5,5,6,6,9
}
}
#include <stdio.h>
void pigeonhole_sort(int *num, int n)
{
int save[10];
int i;
for (i = 0; i < 10; ++i)
save[i] = 0;
for(i = 0; i < n; ++i)
save[num[i]]++;
for(i = 0; i < 10; ++i)
while (save[i]--)
printf("%d ", i);
printf("\n");
}
int main(void)
{
int num[] = {6, 6, 2, 2, 2, 4, 1, 1, 1, 5, 5, 5, 5, 9};
pigeonhole_sort(num, sizeof(num)/sizeof(num[0]));
return 0;
}
6.经典排序算法 - 归并排序Merge sort
原理,把原始数组分成若干子数组,对每一个子数组进行排序,
继续把子数组与子数组合并,合并后仍然有序,直到全部合并完,形成有序的数组
举例
无序数组[6 2 4 1 5 9]
先看一下每个步骤下的状态,完了再看合并细节
第一步 [6 2 4 1 5 9]原始状态
第二步 [2 6] [1 4] [5 9]两两合并排序,排序细节后边介绍
第三步 [1 2 4 6] [5 9]继续两组两组合并
第四步 [1 2 4 5 6 9]合并完毕,排序完毕
输出结果[1 2 4 5 6 9]
合并细节
详细介绍第二步到第三步的过程,其余类似
第二步:[2 6] [1 4] [5 9]
两两合并,其实仅合并[2 6] [1 4],所以[5 9]不管它,
原始状态
第一个数组[2 6]
第二个数组[1 4]
--------------------
第三个数组[...]
第1步,顺序从第一,第二个数组里取出一个数字:2和1
比较大小后将小的放入第三个数组,此时变成下边这样
第一个数组[2 6]
第二个数组[4]
--------------------
第三个数组[1]
第2步,继续刚才的步骤,顺序从第一,第二个数组里取数据,2和4,
同样的比较大小后将小的放入第三个数组,此时状态如下
第一个数组[6]
第二个数组[4]
--------------------
第三个数组[1 2]
第3步,再重复前边的步骤变成,将较小的4放入第三个数组后变成如下状态
第一个数组[6]
第二个数组[...]
--------------------
第三个数组[1 2 4]
第4步,最后将6放入,排序完毕
第一个数组[...]
第二个数组[...]
--------------------
第三个数组[1 2 4 6]
[ 1 2 4 6 ]与[ 5 9 ]的合并过程与上边一样,不再分解
#include <stdio.h>
void div_sort(int *num, int n)
{
int k;
int i, j;
int save[n];
int index = 0;
i = j = 0;
if (n <= 1)
return;
k = (n + 1) / 2;
div_sort(num, k);
div_sort(num + k, n - k);
while (i < k && j < (n-k))
save[index++] = (num[i] < num[j+k] ? num[i++] : num[j++ + k]);
while (i < k)
save[index++] = num[i++];
while (j < n - k)
save[index++] = num[j++ + k];
for(i = 0; i < n; ++i)
num[i] = save[i];
}
int main(void)
{
int num[] = {49, 38, 65, 97, 76, 13, 27};
div_sort(num, 7);
return 0;
}
7.经典排序算法 - 冒泡排序Bubble sort
原理是临近的数字两两进行比较,按照从小到大或者从大到小的顺序进行交换,
这样一趟过去后,最大或最小的数字被交换到了最后一位,
然后再从头开始进行两两比较交换,直到倒数第二位时结束,其余类似看例子
例子为从小到大排序,
原始待排序数组| 6 | 2 | 4 | 1 | 5 | 9 |
第一趟排序(外循环)
第一次两两比较6 > 2交换(内循环)
交换前状态| 6 | 2 | 4 | 1 | 5 | 9 |
交换后状态| 2 | 6 | 4 | 1 | 5 | 9 |
第二次两两比较,6 > 4交换
交换前状态| 2 | 6 | 4 | 1 | 5 | 9 |
交换后状态| 2 | 4 | 6 | 1 | 5 | 9 |
第三次两两比较,6 > 1交换
交换前状态| 2 | 4 | 6 | 1 | 5 | 9 |
交换后状态| 2 | 4 | 1 | 6 | 5 | 9 |
第四次两两比较,6 > 5交换
交换前状态| 2 | 4 | 1 | 6 | 5 | 9 |
交换后状态| 2 | 4 | 1 | 5 | 6 | 9 |
第五次两两比较,6 < 9不交换
交换前状态| 2 | 4 | 1 | 5 | 6 | 9 |
交换后状态| 2 | 4 | 1 | 5 | 6 | 9 |
第二趟排序(外循环)
第一次两两比较2 < 4不交换
交换前状态| 2 | 4 | 1 | 5 | 6 | 9 |
交换后状态| 2 | 4 | 1 | 5 | 6 | 9 |
第二次两两比较,4 > 1交换
交换前状态| 2 | 4 | 1 | 5 | 6 | 9 |
交换后状态| 2 | 1 | 4 | 5 | 6 | 9 |
第三次两两比较,4 < 5不交换
交换前状态| 2 | 1 | 4 | 5 | 6 | 9 |
交换后状态| 2 | 1 | 4 | 5 | 6 | 9 |
第四次两两比较,5 < 6不交换
交换前状态| 2 | 1 | 4 | 5 | 6 | 9 |
交换后状态| 2 | 1 | 4 | 5 | 6 | 9 |
第三趟排序(外循环)
第一次两两比较2 > 1交换
交换后状态| 2 | 1 | 4 | 5 | 6 | 9 |
交换后状态| 1 | 2 | 4 | 5 | 6 | 9 |
第二次两两比较,2 < 4不交换
交换后状态| 1 | 2 | 4 | 5 | 6 | 9 |
交换后状态| 1 | 2 | 4 | 5 | 6 | 9 |
第三次两两比较,4 < 5不交换
交换后状态| 1 | 2 | 4 | 5 | 6 | 9 |
交换后状态| 1 | 2 | 4 | 5 | 6 | 9 |
第四趟排序(外循环)无交换
第五趟排序(外循环)无交换
排序完毕,输出最终结果1 2 4 5 6 9
冒泡排序动画演示
#include <stdio.h>
inline void swap(int *a, int *b)
{
int temp;
temp = *a;
*a = *b;
*b = temp;
}
void bubble_sort(int *num, int n)
{
int i;
int j;
for (j = 0; j < n - 1; ++j)
for (i = 0; i < n - 1; ++i)
if (num[i] > num[i+1])
swap(&num[i], &num[i+1]);
for (i = 0; i < n; ++i)
printf("%d ", num[i]);
printf("\n");
}
int main(void)
{
int num[] = {49, 38, 65, 97, 76, 13, 27};
bubble_sort(num, 7);
return 0;
}
8. 经典排序算法 - 选择排序Selection sort
顾名思意,就是直接从待排序数组里选择一个最小(或最大)的数字,每次都拿一个最小数字出来,
顺序放入新数组,直到全部拿完
再简单点,对着一群数组说,你们谁最小出列,站到最后边
然后继续对剩余的无序数组说,你们谁最小出列,站到最后边
再继续刚才的操作,一直到最后一个,继续站到最后边,现在数组有序了,从小到大
举例
先说看每步的状态变化,后边介绍细节,现有无序数组[6 2 4 1 5 9]
第一趟找到最小数1,放到最前边(与首位数字交换)
交换前:| 6 | 2 | 4 | 1 | 5 | 9 |
交换后:| 1 | 2 | 4 | 6 | 5 | 9 |
第二趟找到余下数字[2 4 6 5 9]里的最小数2,与当前数组的首位数字进行交换,实际没有交换,本来就在首位
交换前:| 1 | 2 | 4 | 6 | 5 | 9 |
交换后:| 1 | 2 | 4 | 6 | 5 | 9 |
第三趟继续找到剩余[4 6 5 9]数字里的最小数4,实际没有交换,4待首位置无须交换
第四趟从剩余的[6 5 9]里找到最小数5,与首位数字6交换位置
交换前:| 1 | 2 | 4 | 6 | 5 | 9 |
交换后:| 1 | 2 | 4 | 5 | 6 | 9 |
第五趟从剩余的[6 9]里找到最小数6,发现它待在正确的位置,没有交换
排序完毕输出正确结果[1 2 4 5 6 9]
第一趟找到最小数1的细节
当前数组是| 6 | 2 | 4 | 1 | 5 | 9 |
先把6取出来,让它扮演最小数
当前最小数6与其它数一一进行比较,发现更小数就交换角色
当前最小数6与2比较,发现更小数,交换角色,此时最小数是2,接下来2与剩余数字比较
当前最小数2与4比较,不动
当前最小数2与1比较,发现更小数,交换角色,此时最小数是1,接下来1与剩余数字比较
当前最小数1与5比较,不动
当前最小数1与9比较,不动,到达末尾
当前最小数1与当前首位数字进行位置交换,如下所示
交换前:| 6 | 2 | 4 | 1 | 5 | 9 |
交换后:| 1 | 2 | 4 | 6 | 5 | 9 |
完成一趟排序,其余步骤类似
#include <stdio.h>
void select_sort(int *num, int n)
{
int i;
int j;
int temp;
for (i = 0; i < n - 1; ++i)
{
for (j = i + 1; j < n; ++j)
if (num[j] < num[i])
{
temp = num[j];
num[j] = num[i];
num[i] = temp;
}
}
for (i = 0; i < n; ++i)
printf("%d ", num[i]);
printf("\n");
}
int main(void)
{
int num[] = {6, 2, 4, 1, 5, 9, 12, 10, 6, 2, 1, 0, 4, 6};
select_sort(num, 14);
return 0;
}
9.经典排序算法 - 鸡尾酒排序Cocktail sort
鸡尾酒排序基于冒泡排序,双向循环
还是看例子吧,给定待排数组[2 3 4 5 1]
第一趟过去时的每一步
第一步迭代,2 < 3不换
[2 3 4 5 1]
第二步迭代,3 < 4不换
[2 3 4 5 1]
第三步迭代,4 < 5不换
[2 3 4 5 1]
第四步迭代,5 > 1交换
[2 3 4 1 5]
第一趟回来时的第一步,鸡尾酒一次到头后就回返回来,再到头后再过去,来回比,一个来回能排两个数字
第五步迭代,1 < 5不交换
[2 3 4 1 5]
第六步迭代,1 < 4交换
[2 3 1 4 5]
第七步迭代,1 < 3交换
[2 1 3 4 5]
第八步迭代,2 > 1交换
[1 2 3 4 5]
排序完毕,顺序输出结果即可得[ 1 2 3 4 5]
如何判断排序结束了?
假如一趟来回没有交换任何数字,则表示该数组已经有序了,可以设置了个变量表示有没有交换过
#include <stdio.h>
void swap(int *a, int *b)
{
int temp;
temp = *a;
*a = *b;
*b = temp;
}
void cocktail_sort(int *num, int n)
{
int change = 1;
int i;
int j;
while (change)
{
change = 0;
i = 0;
j = n - 1;
while (i < n - 1)
{
if (num[i] > num[i+1])
{
change = 1;
swap(&num[i], &num[i+1]);
}
++i;
}
if (!change)
break;
while (j > 0)
{
if (num[j] < num[j-1])
swap(&num[j], &num[j-1]);
--j;
}
}
for (i = 0; i < n; ++i)
printf("%d ", num[i]);
printf("\n");
}
int main(void)
{
int num[] = {2, 3, 4, 5, 1, 2, 2, 4, 5, 6, 2, 1, 0, 7, 9, 5, 3};
cocktail_sort(num, 17);
return 0;
}
10.希尔排序Shell sort
首先要明确一下增量的取法:
第一次增量的取法为: d=count/2;
第二次增量的取法为: d=(count/2)/2;
最后一直到: d=1;
看上图观测的现象为:
d=3时:将40跟50比,因50大,不交换。
将20跟30比,因30大,不交换。
将80跟60比,因60小,交换。
d=2时:将40跟60比,不交换,拿60跟30比交换,此时交换后的30又比前面的40小,又要将40和30交换,如上图。
将20跟50比,不交换,继续将50跟80比,不交换。
d=1时:这时就是前面讲的插入排序了,不过此时的序列已经差不多有序了,所以给插入排序带来了很大的性能提高。
#include <stdio.h>
void swap(int *a, int *b)
{
int temp;
temp = *a;
*a = *b;
*b = temp;
}
void shell_sort(int *num, int n)
{
int k;
int i;
k = n >> 1;
while (k)
{
for (i = 0; i + k < n; ++i)
if (num[i] > num[i+k])
swap(&num[i], &num[i+k]);
if (k == 1)
break;
k = (k + 1) >> 1;
}
for (i = 0; i < n; ++i)
printf("%d ", num[i]);
printf("\n");
}
int main(void)
{
int num[] = {4, 2, 8, 5, 3, 6, 2, 1, 0, 5, 4, 8, 2, 1, 2, 5, 8, 9, 4, 7, 2};
shell_sort(num, 21);
return 0;
}
11经典排序算法 - 堆排序Heap sort
12经典排序算法 - 地精排序Gnome Sort
经典排序算法 - 地精排序Gnome Sort
号称最简单的排序算法,只有一层循环,默认情况下前进冒泡,一旦遇到冒泡的情况发生就往回冒,直到把这个数字放好为止
直接看它排序的过程,待排数组[6 2 4 1 5 9]
先设计一个标识i=0然后从头开始判断,什么时候(i < 6)不成立,什么时候排序结束,
所以,如何控制i的值是这个算法的关键
例如待排数组:
[6 2 4 1 5 9]
[0 1 2 3 4 5]
看一下具体的排序过程
[ i = 0 ]时啥也不干,先让i自增1,达到值为1才开始真正的比较
交换前[6 2 4 1 5 9][ i = 0]
交换后[6 2 4 1 5 9][ i = 1]
[ i = 1 ]比较6和2,发生交换,只要发生交换i就减1
交换前[6 2 4 1 5 9][ i = 1]
交换后[2 6 4 1 5 9][ i = 0]
[ i = 0 ]又成0了,啥也不干,自增变成1再说
交换前[2 6 4 1 5 9][ i = 0]
交换后[2 6 4 1 5 9][ i = 1]
[ i = 1 ]再比较2和6,不交换,只要不要换就自增1
交换前[2 6 4 1 5 9][ i = 1]
交换后[2 6 4 1 5 9][ i = 2]
[ i = 2 ]比较6和4,发生交换,只要交换就减1
交换前[2 6 4 1 5 9][ i = 2]
交换后[2 4 6 1 5 9][ i = 1]
[ i = 1 ]比较2和4,不交换,只要不交换就自增1
交换前[2 4 6 1 5 9][ i = 1]
交换后[2 4 6 1 5 9][ i = 2]
[ i = 2 ]比较4和6,不交换,只要不交换就自增1
交换前[2 4 6 1 5 9][ i = 2]
交换后[2 4 6 1 5 9][ i = 3]
[ i = 3 ]比较6和1,交换,只要交换就减1
交换前[2 4 6 1 5 9][ i = 3]
交换后[2 4 1 6 5 9][ i = 2]
[ i = 2 ]比较4和1,交换,只要交换就减1
交换前[2 4 1 6 5 9][ i = 2]
交换后[2 1 4 6 5 9][ i = 1]
[ i = 1 ]比较2和1,交换,只要交换就减1
交换前[2 1 4 6 5 9][ i = 1]
交换后[1 2 4 6 5 9][ i = 0]
[ i = 0 ]时啥也不干,先让i自增1,达到值为1才开始真正的比较
交换前[1 2 4 6 5 9][ i = 0]
交换后[1 2 4 6 5 9][ i = 1]
[ i = 1]比较1和2,不交换,只要不交换就自增1
[ i = 2]比较2和4,不交换,只要不交换就自增1
[ i = 3]比较4和6,不交换,只要不交换就自增1
[ i = 4]比较6和5,交换,只要交换就减1
交换前[1 2 4 6 5 9][ i = 4]
交换后[1 2 4 5 6 9][ i = 3]
[ i = 3]比较4和5,不交换,只要不交换就自增1
[ i = 4]比较5和6,不交换,只要不交换就自增1
[ i = 5]比较6和9,不交换,只要不交换就自增1
[ i = 6]表达式(i < n)不成立,排序结束,
顺序输出结果即可:[ 1 2 4 5 6 9]
#include <stdio.h>
void swap(int *a, int *b)
{
int temp;
temp = *a;
*a = *b;
*b = temp;
}
void gnome_sort(int *num, int n)
{
int i;
i = 0;
while (i < n)
{
if ((i == 0) || (num[i-1] <= num[i]))
i++;
if (num[i-1] > num[i])
{
swap(&num[i-1], &num[i]);
i--;
}
}
for (i = 0; i < n; ++i)
printf("%d ", num[i]);
printf("\n");
}
int main(void)
{
int num[] = {6, 2, 4, 1, 5, 9, 2, 4, 1, 7, 5, 8, 4, 0, 2, 5, 3, 2, 8 ,9};
gnome_sort(num, 20);
return 0;
}
13经典排序算法 - 奇偶排序Odd-even sort
又一个比较性质的排序,基本思路是奇数列排一趟序,偶数列排一趟序,再奇数排,再偶数排,直到全部有序
举例吧,
待排数组[6 2 4 1 5 9]
第一次比较奇数列,奇数列与它的邻居偶数列比较,如6和2比,4和1比,5和9比
[6 2 4 1 5 9]
交换后变成
[2 6 1 4 5 9]
第二次比较偶数列,即6和1比,5和5比
[2 6 1 4 5 9]
交换后变成
[2 1 6 4 5 9]
第三趟又是奇数列,选择的是2,6,5分别与它们的邻居列比较
[2 1 6 4 5 9]
交换后
[1 2 4 6 5 9]
第四趟偶数列
[1 2 4 6 5 9]
一次交换
[1 2 4 5 6 9]
#include <stdio.h>
void swap(int *a, int *b)
{
int temp;
temp = *a;
*a = *b;
*b = temp;
}
void odd_even_sort(int *num, int n)
{
int change = 1;
int i;
while (change)
{
i = 0;
change = 0;
while (i < n - 1)
{
if (num[i] > num[i+1])
{
swap(&num[i], &num[i+1]);
change = 1;
}
i += 2;
}
i = 1;
while (i < n - 1)
{
if (num[i] > num[i+1])
{
swap(&num[i], &num[i+1]);
change = 1;
}
i += 2;
}
}
for (i = 0; i < n; ++i)
printf("%d ", num[i]);
printf("\n");
}
int main(void)
{
int num[] = {6, 2, 4, 1, 5, 9, 2, 4, 6, 4, 5, 2, 8, 1, 0, 2, 3};
odd_even_sort(num, 17);
return 0;
}