我个人比较常用的就是这三种了
选择排序
这是最容易理解的一类排序了,他的原理是每次都从数组中寻找一个最小的数放在最前面。依次类推。如图
由于5个元素每一个都要选取和一次比较,所以有5个元素就要循环5次。
上代码
#include<stdio.h>
int main()
{
int arr[5] = { 55, 33, 64, 37, 89 };
for (int i = 0; i < 5; i++)//五个元素,循环五次
{
for (int j = i; j < 5; j++)//第一次把第一个元素的排好,第二次排第二个........
{
if (arr[i] > arr[j])//总是把最小的放前面
{
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
}
for (int i = 0; i < 5; i++)
{
printf("%3d", arr[i]);
}
return 0;
}
冒泡排序
跟选择排序有所不同,冒泡排序每循环一次就会把最后一位数排好。其原理是每次都比较相邻的两数,依次向后,可以把大数逐渐向后移动。注意,由于最后面的数已经排好,后一次循环不需要再比较最后一个数,所以每次循环的比较次数都比上次少一个。如图。

选择排序和冒泡排序的差别其实不大,我自己常常写着写着就分不清是选择排序还是冒泡排序了。但实际性能而言,冒泡排序的数据移动量实际更大。
#include<stdio.h>
int main()
{
int arr[5] = { 55, 33, 64, 37, 89 };
for (int i = 4; i >=0; i--)//扫描4次,每一次都把最后一位数排好
{
for (int j = 0; j < i; j++)//由于最后一位已经排好,所以到i就不用再循环了
{
if (arr[j] > arr[j+1])//比较相邻的两数
{
int tmp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = tmp;
}
}
}
for (int i = 0; i < 5; i++)
printf("%3d", arr[i]);
return 0;
}插入排序
相较于前两种,插入排序在数据大部分已经拍好的情况下会非常有效率。他的原理是拿出数据与前面所有的逐个比较,在合适的位置插入。如果数据很多,而且很杂,就不建议用插入排序了。因为当数据找到很合适的位置后,后面所有的数据都要后移一位,这样的排序方法只适合少而比较有序的数据,如图

难的就是这个后移,代码中更换了变量,不好理解。
#include<stdio.h>
int main()
{
int arr[5] = { 55, 33, 64, 37, 89 };
int tmp = 0;
for (int i = 0; i < 5; i++)
{
int tmp = arr[i];//取出的需要插入的数
for (int j = 0; j < i; j++)//前面的顺序已经排好,开始判断、插入
{
if (arr[j] > arr[i])//说明找到要插入的点了(arr[j])
{
int k = i;//循环出口
while (k >=1)//从arr[j]把后面所有的都后移一位(数字要从后往前)
{
arr[k] = arr[k - 1];
k--;
}
arr[j] = tmp;//把取出的数放到正确的位置上
}
}
}
for (int i = 0; i < 5; i++)
{
printf("%3d", arr[i]);
}
return 0;
}快速排序
公认的排序最优解。他的原理是先找一个虚拟的中间值K,然后将小于中间值的数全部交换放在左边,大于中间值的数全部放在右边。分为一下几个步骤:
1、先取中间值tmp为第一个数arr[0]
2、定义int j=strlen(arr)-1;从右到左寻找arr[j]<tmp,定义int i=0;从左到右寻找arr[i]>tmp,注意:j必须率先出发,因为和中间值交换位置的时候不能换成比中间值更大的数。
3、若i<j,则i、j互换,然后继续向前循环,直到i==j,若i==j,则说明已经大致排序完成,交换中间值和arr[i]的位置,用递归分别对左右两边继续排序。

本章代码出现问题,请看拙作(修正版快速排序):
排序虽然简单,但纸上读来终觉浅,要避免代码中的小问题,还是得自己敲一敲才行。
希望与诸君共勉。