常用的基础排序算法及代码实现
排序是生活中经常面对的问题,而根据排序过程中借助的主要操作,我们把内排序分为:插入排序、交换排序、选择排序和归并排序。这些都是比较成熟的排序算法,我们学习这些排序算法主要目的是通过学习它们来提高我们编写算法的能力,以便于解决更多复杂和灵活的应用性问题。
冒泡排序( Bubble Sort )
基本思想: 两两比较相邻记录的关键字,如果反序则交换,直到没有反序的记录为止。
算法实现:
void bubbleSort(sqList *list)
{
int i, j;
int flag = TRUE;
for(i=1; i<list->length && flag; i++)
{
flag = FLASE;
for(j=list->length-1; j>=i; j--)
{
if(list->r[j] > list->r[j+1])
{
swap(list, j, j+1);
flag = TRUE; /*如果没有数据交换,说明已经有序,避免无意义的循环判断*/
}
}
}
}
简单选择排序( Simple Selection Sort )
基本思想: 通过 n-i 次关键字间的比较,从 n-i+1 个记录中选出关键字最小的记录,并和第 i 个记录交换之。
算法实现:
void selectSort(sqList *list)
{
int i, j, min;
for(i=1; i<list->length; i++)
{
min = i;
for(j=i+1; j<=list->length; j++)
{
if(list->r[min] > list->r[j])
min = j;
}
if(i != min)
swap(list, i, min);
}
}
直接插入排序( Strairht Insertion Sort )
基本思想: 将一个记录插入的已经排好序的有序表中,从而得到一个新的、记录数增 1 的有序表。
算法实现:
void insertSort(sqList *list)
{
int i, j;
for(i=2; i<=list->length; i++)
{
if(list->r[i] < list->r[i-1]) /*需要插入*/
{
list->r[0] = list->r[i]; /*设置哨兵*/
for(j=i-1; list->r[j]>list->r[0]; j--)
{
list->r[j+1] = list->r[j]; /*记录后移*/
}
list->r[j+1] = list->r[0]; /*插入到正确位置*/
}
}
}
希尔排序( Shell Sort )
基本原理: 将待排序的记录分割成若干子序列,使子序列记录个数较少,然后再这些子序列内分别进行直接插入排序,当整个序列都基本有序时,再对全体记录进行一次直接插入排序。其中分割策略是将相聚某个 “ 增量 ” 的记录组成一个子序列,以保证在子序列内分别进行直接插入排序后得到的结果是基本有序而不是局部有序。
而对于增量的选取,目前还是一个数学难题,迄今为止还没有一种最好的增量序列。另外由于记录是跳跃式的移动,希尔排序并不是一种稳定的排序算法。
快速排序( Quick Sort )
基本思想: 通过一趟排序将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分的记录小,则可分别对这两部分记录继续进行排序,以达到整个序列有序的目的。
算法实现:
void quickSort(sqList *list)
{
qsort(list, 1, list->length);
}
void qsort(sqList *list, int low, int high)
{
int pivot;
if(low < high)
{
pivot = partition(list, low, high); /*一分为二,算出枢纽值*/
qsort(list, low, pivot-1); /*对低子表递归排序*/
qsort(list, pivot+1, high); /*对高子表递归排序*/
}
}
int partition(sqList *list, int low, int high)
{
int pivotkey;
pivotkey = list->r[low]; /*用字表的第一个记录作枢纽值*/
while(low < high) /*从表的两端交替向中间扫描*/
{
while(low<high && list->r[high] >= pivotkey)
high--;
swap(list, low, high); /*将比枢纽值小的记录交换到低端*/
while(low<high && list->r[low] <= pivotkey)
low--;
swap(list, low, high); /*将比枢纽值大的记录交换到高端*/
}
return low; /*返回枢纽值所在位置*/
}
快速排序优化:
1 . 优化选取枢纽值:三数取中。
2 . 优化不必要的交换
3 . 优化小数组的排序方案
4 . 优化递归操作