关于排序方法,常见的排序方法有快速排序、冒泡排序、选择排序、插入排序、归并排序,此外还有堆排序、桶排序、基数排序、基数排序。
1.快速排序
快排的操作过程是随便选取一个关键字(一般选取第一个),让所有关键字和它进行比较一次,小的放在左边,大的放 在它右边,然后递归地对左边和右边进行排序。
快速排序有个特点,待排序列越接近无序,算法效率越高,也就是在基本有序的情况下时间复杂度为O(n^2)
,最好的情况下复杂度为O(nlog2n)
,平均复杂度为O(nlog2n)
,从所有内排序来看,快排是所有内排序中平均复杂度最好的,空间复杂度也为O(nlog2n )
。
void quick_sort1(int s[],int l, int r){
int i=l;
int j=r;
int x=s[i];//第一个坑
if(i>=j) return ;
while (i!=j) {
//从右向左找小于x的数来填s[i];
while (i<j&&s[j]>=x) {
j--;
}
s[i]=s[j];
//从左向右找大于或等于x的数来填s[j];
while (i<j&&s[i]<x) {
i++;
}
s[j]=s[i];
}
s[i]=x;
quick_sort1(s, l, i-1);
quick_sort1(s, i+1, j);
}
2.冒泡排序
冒泡排序的基本思想是重复的进行整个数列的排序,一次比较两个元素(两两排序),如果它们顺序不符合就交换,重复这样直到数列没有再需要交换的数为止(结束条件)。
时间复杂度为O(n^2 )
,若待排序为顺序,也就是不需要交换元素,但是需要扫描,所以还是需要O(n)
的时间复杂度,平均情况下时间复杂度为O(n^2)
。
void Bubble_sort(int s[],int len){
int i,j,flag;
for (i=len-1; i>=1; i--) {
flag=1;
for (j=i-1; j>=0; j--) {
if (s[i]<s[j]) {
swap(s[i], s[j]);
flag=0;
}
}
if (1==flag) {//表示已经排序完成
break;
}
}
}
3.插入排序(折半插入)
插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据,算法适用于少量数据的排序,时间复杂度为O(n^2)
。
void HalfInsert_sort(int s[], int len){
int temp, low, high, i, j, mid;
for (i=1; i<len; ++i)
{
temp = s[i];
low = 0;
high = i - 1;
while (high >= low)
{
mid = (low + high) / 2;
if (temp < s[mid])
{
high = mid - 1;
}
else
{
low = mid + 1;
}
}
for (j=i-1; j>=low; --j)
{
s[j+1] = s[j];
}
s[low] = temp;
}
}
4.选择排序
选择排序是一种简单直观的排序算法。首先在未排序序列中找到最小元素,存放到排序序列的起始位置,然后再从剩余未排序元素中继续寻找最小元素,最后放到排序序列末尾(目前已被排序的序列)。
void Select_sort(int s[], int len){
int i,j,min;
for (i=0; i<len-1; i++) {
min=i;
for (j=i+1; j<len; j++) {
if (s[min]>s[j]) {
min=j;//把值最小的下标记下来
}
}
if (min!=i) {
swap(s[i], s[min]);
}
}
}
总结
个人常用以上四种排序,作简单分析:
-
插入排序不适合对于数据量比较大的排序应用。量级小于千,那么插入排序还是一个不错的选择。
-
快速排序和折半插入排序有异曲同工之妙,差别在于折半插入排序插入的序列自身是个有序序列,选取中间关键字时两边已经有序,而快速排序在于它不一定是有序的。
-
快速排序(Quicksort)是对冒泡排序的一种改进。通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。