数据结构复习笔记01_排序算法_交换排序

来源:互联网 发布:风控模型算法 编辑:程序博客网 时间:2024/05/16 05:55

基于交换的排序方法主要有①冒泡排序和②快速排序。文章默认排序算法是升序

一、冒泡排序

基本思想:两两比较和交换,每次冒出一个关键字最大的记录。一般有两层循环,一般用两层for循环,外层循环只是指定这一趟已经有i个已冒出的数字(从而指定内层遍历的终点),内层循环j是遍历元素、比较、交换,直到n-i,循环结束条件是有一趟内层循环未发生交换,则证明有序。

eg:

原始序列:12, 34, 20, 15, 9, 25, 27, 13

第一趟: 12 34 20 15 9 25 27 13

             12 20 34 15 9 25 27 13 

             12 20 15 349 25 27 13

             12 20 15 9 34 25 27 13

             ……

             12 20 15 9 25 27 13 34

第二趟: 12 15 9 20 25 13 27 24

第三趟: 12 9 15 20 13 25 27 34

第四趟: 9 12 15 13 20 25 27 34

第五趟: 9 12 13 15 20 25 27 34

第六趟: 9 12 13 15 20 25 27 34

代码:

//冒泡void BubbleSort(double R[], int length){for (int i = 1; i < length; ++i){bool swap = false;for (int j = 0; j < length - i; ++j){if (R[j] > R[j + 1])    //比较、交换{int temp = R[j];R[j] = R[j + 1];R[j + 1] = temp;swap = true;}}if (!swap) break;    //没发生交换说明有序,结束排序}}

二、改进的冒泡排序(然并卵)

冒泡过程中如果后面的记录未发生交换,则证明后面的序列已经有序,常规冒泡还是会进行比较到结束位置。因此每次记录最后的交换位置,作为下次的比较终点。

eg:23 15 14 25 28 30

       15 14 23 25 28 30      //红色为最后交换时 j 的值

代码:

//改进的冒泡//记录每一躺最后交换的j作为下一次冒泡的终点void BubbleSortEx(double R[], int length){int i = length - 1;while (i > 1){int lastIndex = 0;for (int j = 0; j < i; ++j){if (R[j] > R[j + 1]){int temp = R[j];R[j] = R[j + 1];R[j + 1] = temp;lastIndex = j;}}i = lastIndex;}}
实际提升效果有限,只有对特殊情况才有很好的效果。
性能方面,空间复杂度有一个临时变量作为交换空间,o(1)。

时间复杂度,最好情况,正序,比较n-1次,交换0次。最坏情况,逆序o(n^2),平均o(n^2)。是一种稳定排序

三、快速排序

基本思想是以某个记录的关键字作为基准(划分元),将整个序列划分成两组,左边的记录关键字小于等于划分元,右边的大于等于划分元,而划分元所处的位置就是它最终排序好的位置。一般选取当前记录的第一个记录作为划分元,然后利用递归思想快排左右的子记录,这种思想和二叉树遍历很相似,递归遍历他们的子树。


代码:

//快排一次,返回划分元最终位置int QuickPartition(double R[], int low, int high){//以左端为划分元double value = R[low];while (low < high){int temp = 0;while (low < high && R[high] >= value) --high;    //high左移R[low] = R[high];    //比划分元小的值复制到左边,这里直接赋值不必担心覆盖,因为“被覆盖的值”已经保存在valuewhile (low < high && R[low] <= value) ++low;    //low右移R[high] = R[low];    //比划分元大的值复制到右边}R[low] = value;    //i为划分元最终位置return low;}//对顺序表R[l...h]快排void QuickSort(double R[], int low, int high){if (low < high){int p = QuickPartition(R, low, high);QuickSort(R, low, p - 1);QuickSort(R, p + 1, high);}    //像极了二叉树先序遍历}
性能方面,从空间复杂度来看,递归调用的层数与n个结点二叉树的深度相同,因此最好情况o(logn),最差o(n)。

时间复杂度一次划分需要o(n),最好o(nlogn),最坏情况有序或基本有序,退化为冒泡,o(n^2)。快排不是稳定排序


原创粉丝点击