交换排序的基本思想:
每次比较无序表L[0...n-1]
中相邻两个元素大小,若为逆序则交换
一般常见的交换排序有两个,一个冒泡排序(非常简单),一个是快速排序(内部排序平均效率最好的排序算法)
冒泡排序的基本思想:
-
从前往后,每次比较无序表
L[0...n-1]
中相邻两个元素大小,若为逆序则交换 -
以结果为非递减序列为例,每次从前往后对1.中操作进行一轮,则会有一个无序表中的最大值到达最终位置上,因此只需要执行执行n-1次操作1.,并且某次执行若未发生元素交换则表明表已经有序排序完毕
于是有如下实现
void bubble_Sort(int A[], int length)
{
for (int i = 1; i < length; ++i)
{
int flag = 0;
for (int j = 0; j < length - i; ++j) // 升序下每趟排序待排序序列中的最大的值会在最终位置上,故j < length - i
{
if (A[j] > A[j + 1])
{
int swap_val = A[j];
A[j] = A[j + 1];
A[j + 1] = swap_val;
flag = 1;
}
}
if (!flag) // 未发生交换则已经排序完毕
return;
}
}
快速排序的基本思想:
-
对表
L[0...n-1]
,每次选择一个表中一个元素作为枢轴(pivot),然后将比pivot小的元素置于pivot元素在表最终位置的左边(以非递减的排序结果为例),比pivot大的元素置于pivot元素在表最终位置的右边(这是快速排序的精髓) -
经过1.后,记
pivot
最终的索引为lo
,表被划分为L[0...i-1]
和``L[i+1...n-1],对这两个无序表递归执行1.,直到递归到无序表长为小于等于1,则此时有序,完成排序
对于1.,常用的实现方式是选择表头元素作为枢轴,并设lo = 表头元素的索引
,hi = 表位元素的索引
然后从hi
开始,如果hi
所指元素小于lo
,将这个元素移动到lo
所指向的位置,反之hi
递减
对于lo
的操作类似,只是和hi
的操作相反即可,并且让hi
与lo
的移动交替进行,当hi == lo
时这个位置就是pivot的最终位置
于是我们有如下实现
// cannot be called by user
int _partition(int A[], int lo, int hi)
{
int pivot = A[lo];
while (lo < hi)
{
while (lo < hi && A[hi] >= pivot) // 不能采用严格不等号,也就是说相等也移动,否则死循环
--hi;
A[lo] = A[hi];
while (lo < hi && A[lo] <= pivot)
++lo;
A[hi] = A[lo];
}
A[lo] = pivot;
return lo;
}
void quick_Sort(int A[], int length) //这个函数建议按教材来实现,我这个可读性稍差
{
if (length <= 1) // 终止条件
return;
int pivot = _partition(A, 0, length - 1);
quick_Sort(A, pivot);
quick_Sort(A + pivot + 1, length - pivot - 1);
}