数据结构之快速排序
2014-10-23 23:55
274 查看
小目录
1.冒泡排序
2.快速排序
1.冒泡排序
冒泡排序我想可能是学习C语言接触的第一个排序算法了,相信每一本C语言的数组的章节都会介绍这个排序算法的。下面我们就从一个类冒泡排序算法来一步步优化这个算法。
冒泡排序的基本思想:它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。
下面给出一个类冒泡排序的程序,注意这不是冒泡排序,但其过程是有冒泡排序的特点的。
这里给出调用到的swap函数,后面不会再提示:
可以看到这里并不是相邻两个元素的比较交换,接下来我们来看看常见的冒泡排序算法:
从两个程序可以看出来,冒泡在比较的过程中不仅仅把最小的(或者最大的元素)往上冒泡了,还把相关的元素的也往上冒泡了,这样在无形中就减少下一次的移动次数。
性能分析:若是反序的,需要进行
趟排序。每趟排序要进行
次关键字的比较(1≤i≤n-1),且每次比较都必须移动记录三次来达到交换记录位置。在这种情况下,比较和移动次数均达到最大值:
冒泡排序的最坏时间复杂度为
。综上,因此冒泡排序总的平均时间复杂度为
,空间复杂度为O(n)。冒泡排序是稳定的排序算法,因为在相邻两元素比较时只有小于或是大于才交换。
改进冒泡排序:
再次感受到感受到前人的牛逼,但是有点优化的规律是这样的:要充分利用前面已经进行的比较来减少当前所需进行的比较(还记得KMP算法吗)。这里所谓的改进的冒泡算法就是当待排序列部分有序时,比如 序列2 ,1,3,4,5,6在调整一次后为1,2,3,4,5,6这时候如果还按照上面的冒泡算法还需要进行后面的比较,这不是浪费吗!比如,现在再次进行调整(注意这里从后面扫描),则发现一路往上都没有需要交换的,这是不是代表着有序了,如果存在无序必然存在交换,于是我们想到用一个标志来记录是否发生了交换。实现程序如下:
2.快速排序
快速排序是对冒泡的一种改进,它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
这里的基准预设为的第一个元素
csdn这玩意不知道怎么了,老是自动给图片加水印把内容挡住了,以后再补图吧。
性能分析:快速排序的最坏情况下的时间复杂度为O(n的平方)但是其平均时间复杂度为O(nlogn),这是前面介绍的冒泡和插入排序所不具备的。所以快速排序被认为是目前性能最好的内部排序算法。该排序算法为不稳定排序算法。
最后附上源码地址:GitHub
1.冒泡排序
2.快速排序
1.冒泡排序
冒泡排序我想可能是学习C语言接触的第一个排序算法了,相信每一本C语言的数组的章节都会介绍这个排序算法的。下面我们就从一个类冒泡排序算法来一步步优化这个算法。
冒泡排序的基本思想:它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。
下面给出一个类冒泡排序的程序,注意这不是冒泡排序,但其过程是有冒泡排序的特点的。
/* * @description:类冒泡排序 */ void BubbleSort_1(SqList *L) { int i,j; //注意这里没有等于 for(i = 1; i < (*L).length ; i++) { for(j = i + 1; j <= (*L).length; j++) if((*L).r[i].key > (*L).r[j].key) swap(L,i,j); } }
这里给出调用到的swap函数,后面不会再提示:
/* * @description:用于交换要节点元素位置 */ void swap(SqList *L,int i,int j) { ElemType temp; temp = (*L).r[i]; (*L).r[i] = (*L).r[j]; (*L).r[j] = temp; }
可以看到这里并不是相邻两个元素的比较交换,接下来我们来看看常见的冒泡排序算法:
/* * @description:冒泡排序,相邻两元素比较 * @more:这个相对于上面的优化在于冒泡在 冒泡的过程也把相关的元素的位置 上升了 */ void BubbleSort_2(SqList *L) { int i,j; for(i = 1; i < (*L).length ; i++) { for(j = (*L).length - 1; j >= i; j-- ) //注意这里的不同 if((*L).r[j].key > (*L).r[j + 1].key) swap(L,j + 1,j); } }
从两个程序可以看出来,冒泡在比较的过程中不仅仅把最小的(或者最大的元素)往上冒泡了,还把相关的元素的也往上冒泡了,这样在无形中就减少下一次的移动次数。
性能分析:若是反序的,需要进行
趟排序。每趟排序要进行
次关键字的比较(1≤i≤n-1),且每次比较都必须移动记录三次来达到交换记录位置。在这种情况下,比较和移动次数均达到最大值:
冒泡排序的最坏时间复杂度为
。综上,因此冒泡排序总的平均时间复杂度为
,空间复杂度为O(n)。冒泡排序是稳定的排序算法,因为在相邻两元素比较时只有小于或是大于才交换。
改进冒泡排序:
再次感受到感受到前人的牛逼,但是有点优化的规律是这样的:要充分利用前面已经进行的比较来减少当前所需进行的比较(还记得KMP算法吗)。这里所谓的改进的冒泡算法就是当待排序列部分有序时,比如 序列2 ,1,3,4,5,6在调整一次后为1,2,3,4,5,6这时候如果还按照上面的冒泡算法还需要进行后面的比较,这不是浪费吗!比如,现在再次进行调整(注意这里从后面扫描),则发现一路往上都没有需要交换的,这是不是代表着有序了,如果存在无序必然存在交换,于是我们想到用一个标志来记录是否发生了交换。实现程序如下:
/* * @description:优化之后的冒泡排序 * @more:这是顺序比较的,在部分有序的情况下体现效果 在最坏的情况下和上面的冒泡排序是一样的 */ void BubbleSort_3(SqList *L) { int i,j,flag; flag = 1; for(i = 1; i < (*L).length && flag; i++) { flag = 0; for(j = (*L).length - 1; j >= i; j--) { if((*L).r[j].key > (*L).r[j + 1].key) { swap(L,j + 1,j); flag = 1; } } } }性能分析:优化后的算法只是在序列部分有序时才体现效果,其时间复杂度依然是O(n的平方),为稳定排序算法。
2.快速排序
快速排序是对冒泡的一种改进,它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
/* * @descrption:快速排序具体交换操作,函数最后返回最后的基准的位置 * @more:基本思想:设置一个基准,从high一直往前找,找到第一个比 基准值小,交换他们两;接着从low一直往后找,找到第一个 比基准大的,交换他们两 这里的基准预设为的第一个元素 */ int Partition(SqList *L,int low,int high) { KeyType pivkey; //使用第0个空位来暂存基准值 (*L).r[0] = (*L).r[low]; pivkey = (*L).r[low].key; //用当前的顺序表的第一个元素关键词作为基准值 while(low < high) { //一直往前找 while(low < high && (*L).r[high].key >= pivkey) high--; //找到直接复制 (*L).r[low] = (*L).r[high]; //一直往后找 while(low < high && (*L).r[low].key < pivkey) low++; (*L).r[high] = (*L).r[low]; } (*L).r[low] = (*L).r[0]; return low; } /* * @description:递归排序 */ void QSort(SqList *L,int low,int high) { int pivloc; if(low < high) { pivloc = Partition(L,low,high); QSort(L,low,pivloc - 1); QSort(L,pivloc + 1,high); } } /* * @description:快速排序 * @more:快速排序是目前认为最好的一种内部排序方法 */ void QuickSort(SqList *L) { QSort(L,1,(*L).length); }可以看出来算法设置一个基准,从high一直往前找,找到第一个比基准值小,交换他们两;接着从low一直往后找,找到第一个比基准大的,交换他们两
这里的基准预设为的第一个元素
csdn这玩意不知道怎么了,老是自动给图片加水印把内容挡住了,以后再补图吧。
性能分析:快速排序的最坏情况下的时间复杂度为O(n的平方)但是其平均时间复杂度为O(nlogn),这是前面介绍的冒泡和插入排序所不具备的。所以快速排序被认为是目前性能最好的内部排序算法。该排序算法为不稳定排序算法。
最后附上源码地址:GitHub
相关文章推荐
- java数据结构之排序(交换排序(冒泡泡排序、快速排序))
- 数据结构之快速排序(C语言)
- 数据结构与算法——冒泡排序、选择排序和快速排序
- 数据结构-快速排序
- 数据结构之交换排序之快速排序(参考整理严蔚敏数据结构)
- 数据结构——快速排序原理及算法Java实现
- 数据结构之快速排序
- 数据结构与算法-快速排序
- 再看数据结构之——快速排序
- 数据结构之快速排序
- 数据结构之快速排序
- 数据结构与算法之一快速排序
- 数据结构之-快速排序
- 【数据结构与算法】内部排序之四:归并排序和快速排序(含完整源码)
- [数据结构]快速排序
- 数据结构(Java 快速排序模拟)本代码重在学习数据结构思路,代码完整性欠缺,请见谅
- 数据结构与算法之快速排序
- 【数据结构与算法】排序算法——快速排序
- [数据结构]栈的插入,归并以及快速排序
- 数据结构基础(4) --快速排序