快速排序过程,快速排序
快速排序过程,快速排序详细介绍
本文目录一览: 快速排序
快速排序(Quicksort),计算机科学词汇,适用领域Pascal,c++等语言,是对冒泡排序算法的一种改进。
1、首先设定一个分界值,通过该分界值将数组分成左右两部分。
2、将大于或等于分界值的数据集中到数组右边,小于分界值的数据集中到数组的左边。此时,左边部分中各元素都小于分界值,而右边部分中各元素都大于或等于分界值。
3、然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理。
4、重复上述过程,可以看出,这是一个递归定义。通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。当左、右两个部分各数据排序完成后,整个数组的排序也就完成了。
排序演示
假设一开始序列{xi}是:5,3,7,6,4,1,0,2,9,10,8。
此时,ref=5,i=1,j=11,从后往前找,第一个比5小的数是x8=2,因此序列为:2,3,7,6,4,1,0,5,9,10,8。
此时i=1,j=8,从前往后找,第一个比5大的数是x3=7,因此序列为:2,3,5,6,4,1,0,7,9,10,8。
此时,i=3,j=8,从第8位往前找,第一个比5小的数是x7=0,因此:2,3,0,6,4,1,5,7,9,10,8。
此时,i=3,j=7,从第3位往后找,第一个比5大的数是x4=6,因此:2,3,0,5,4,1,6,7,9,10,8。
此时,i=4,j=7,从第7位往前找,第一个比5小的数是x6=1,因此:2,3,0,1,4,5,6,7,9,10,8。
此时,i=4,j=6,从第4位往后找,直到第6位才有比5大的数,这时,i=j=6,ref成为一条分界线,它之前的数都比它小,之后的数都比它大,对于前后两部分数,可以采用同样的方法来排序。
快速排序
基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列
快速排序算法通过多次比较和交换来实现排序,其排序流程如下:
(1)首先设定一个分界值,通过该分界值将数组分成左右两部分。
(2)将大于或等于分界值的数据集中到数组右边,小于分界值的数据集中到数组的左边。此时,左边部分中各元素都小于或等于分界值,而右边部分中各元素都大于或等于分界值。
(3)然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理
(4)重复上述过程,可以看出,这是一个递归定义。通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。当左、右两个部分各数据排序完成后,整个数组的排序也就完成了。
下面通过一个例子介绍快速排序算法的思想,假设要对数组a[10]={6,1,2,7,9,3,4,5,10,8}进行排序,首先要在数组中选择一个数作为基准值,这个数可以随意选择,在这里,我们选择数组的第一个元素a[0]=6作为基准值,接下来,我们需要把数组中小于6的数放在左边,大于6的数放在右边,怎么实现呢?
我们设置两个“哨兵”,记为“哨兵i”和“哨兵j”,他们分别指向数组的第一个元素和最后一个元素,即i=0,j=9。首先哨兵j开始出动,哨兵j一步一步地向左挪动(即j–),直到找到一个小于6的数停下来。接下来哨兵i再一步一步向右挪动(即i++),直到找到一个数大于6的数停下来。
最后哨兵j停在了数字5面前,哨兵i停在了数字7面前。此时就需要交换i和j指向的元素的值。
交换之后的数组变为a[10]={6,1,2,5,9,3,4,7,10,8}:
第一次交换至此结束。接下来,由于哨兵i和哨兵j还没有相遇,于是哨兵j继续向前,发现比6小的4之后停下;哨兵i继续向前,发现比6大的9之后停下,两者再进行交换。交换之后的数组变为a[10]={6,1,2,5,4,3,9,7,10,8}。
第二次交换至此结束。接下来,哨兵j继续向前,发小比6小的3停下来;哨兵i继续向前,发现i==j了!!!于是,这一轮的探测就要结束了,此时交换a[i]与基准的值,数组a就以6为分界线,分成了小于6和大于6的左右两部分:a[10]={3,1,2,5,4,6,9,7,10,8}。
至此,第一轮快速排序完全结束,接下来,对于6左边的半部分3,1,2,5,4,执行以上过程;对于6右边的半部分9,7,10,8,执行以上过程,直到不可拆分出新的子序列为止。最终将会得到这样的序列:1 2 3 4 5 6 7 8 9 10,到此,排序完全结束。
快速排序的一次划分算法从两头交替搜索,直到low和hight重合,因此其时间复杂度是O(n);而整个快速排序算法的时间复杂度与划分的趟数有关。
理想的情况是,每次划分所选择的中间数恰好将当前序列几乎等分,经过log 2 n趟划分,便可得到长度为1的子表。这样,整个算法的时间复杂度为O(nlog 2 n)。
最坏的情况是,每次所选的中间数是当前序列中的最大或最小元素,这使得每次划分所得的子表中一个为空表,另一子表的长度为原表的长度-1。这样,长度为n的数据表的快速排序需要经过n趟划分,使得整个排序算法的时间复杂度为O(n 2 )。
为改善最坏情况下的时间性能,可采用其他方法选取中间数。通常采用“三者值取中”方法,即比较H->r[low].key、H->r[high].key与H->r[(low+high)/2].key,取三者中关键字为中值的元素为中间数。
可以证明,快速排序的平均时间复杂度也是O(nlog 2 n)。因此,该排序方法被认为是目前最好的一种内部排序方法
45,80,55,40,42,85快速排序第一次划分的结果 要过程越详细越好
快速排序过程即为如下三个步骤:
1.
选定序列中的一个元素,作为枢轴
2.
用该枢纽划分序列,使得位于枢轴左侧的序列都比枢纽小,位于枢轴右侧的数都比枢纽大
3.
对划分所得的序列重复1,2步,直到序列不可再分。
所以由上面的三个步骤可知:
1.快速排序每次都会将序列一分为二
2.划分完序列之后即确定了枢轴在最终有序序列所处的位置
快速排序第一次划分的结果,受到枢轴选择的影响,假设选择序列的第一个元素作为枢轴。
则枢轴为数字45,小于45的数将位于其左边,大于45的数将位于其右边,所以序列为:
(42,40)45(55,80,85)
1.
左右集合的内容在枢轴选定是即被确定
2.
左右集合中元素的次序收到具体的元素移动算法的影响,按照严版数据结构书中的移动方式其序列如上面所示。其步骤如下:
首先从右找到第一个比45小的元素42与45交换得到序列(42,80,55,40,45,85)
接着从左往右找到第一个比45大的元素80与45交换得到序列(42,45,55,40,80,85)
重复这个过程依次得到序列(42,40,55,45,80,85)、(42,40,45,55,80,85)即最终序列
注:这个过程移动过程并非是一定的,采用不同的元素移动算法可以得到不同的左右顺序序列。
快速排序是按照什么顺序进行排序的?
每趟排序需要一个辅助空间,辅助空间和趟数有关,最好情况是log2 n ,最差的情况是n。
快速排序由C. A. R. Hoare在1960年提出。
它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
扩展资料
一趟快速排序的算法是:
1、设置两个变量i、j,排序开始的时候:i=0,j=N-1;
2、以第一个数组元素作为关键数据,赋值给key,即key=A[0];
3、从j开始向前搜索,即由后开始向前搜索(j--),找到第一个小于key的值A[j],将A[j]和A[i]的值交换;
4、从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]和A[j]的值交换;
5、重复第3、4步,直到i=j; (3,4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[i]不大于key的时候改变j、i的值,使得j=j-1,i=i+1,直至找到为止。
找到符合条件的值,进行交换的时候i, j指针位置不变。另外,i==j这一过程一定正好是i+或j-完成的时候,此时令循环结束)。
参考资料来源:百度百科-快速排序算法
快速排序,看了解释还是不会,求通俗点的
我刚看了一下啊哈算法中的快速排序
为什么我推演的结果都没有答案。
具体思想是,选中最左边为基准数,即66.然后设置一个哨兵从右边开始,寻找比66小的数,接着设置另一个哨兵,再从左边找比66大的书,交换双方位置,如果最后两边的哨兵相遇,就和基准数交换。下面开始推演:
例子:66 13 51 76 81 26 57 69 23
右边开始:找到了23,左边找到了76,交换:66 13 51 23 81 26 57 69 76
右边开始:找到了57,左边找到了81,交换:66 13 51 23 57 26 81 69 76
右边开始:找到了26,左边在26与哨兵相遇,交换基准数:26 13 51 23 57 66 81 69 76.
然后没有答案啊。。。。
我好迷啊。
快速排序简单的说就是选择一个基准,将比起大的数放在一边,小的数放到另一边。对这个数的两边再递归上述方法。
如本题
66 13 51 76 81 26 57 69 23,以66为基准,升序排序的话,比66小的放左边,比66大的放右边, 类似这种情况 13 。。。 66。。。69
具体快速排序的规则一般如下:
从右边开始查找比66小的数,找到的时候先等一下,再从左边开始找比66大的数,将这两个数借助66互换一下位置,继续这个过程直到两次查找过程碰头。
例子中:
66 13 51 76 81 26 57 69 23
从右边找到23比66小,互换
23 13 51 76 81 26 57 69 66
从左边找到76比66大,互换
23 13 51 66 81 26 57 69 76
继续从右边找到57比66小,互换
23 13 51 57 81 26 66 69 76
从左边查找,81比66大,互换
23 13 51 57 66 26 81 69 76
从右边开始查找26比66小,互换
23 13 51 57 26 66 81 69 76
从左边开始查找,发现已经跟右边查找碰头了,结束,第一堂排序结束
下面排序C语言的排序快速代码,参考一下
void sort(int *a, int left, int right){ if(left >= right)/*如果左边索引大于或者等于右边的索引就代表已经整理完成一个组了*/ { return ; } int i = left; int j = right; int key = a[left]; while(i < j) /*控制在当组内寻找一遍*/ { while(i < j && key <= a[j]) /*而寻找结束的条件就是,1,找到一个小于或者大于key的数(大于或小于取决于你想升 序还是降序)2,没有符合条件1的,并且i与j的大小没有反转*/ { j--;/*向前寻找*/ } a[i] = a[j]; /*找到一个这样的数后就把它赋给前面的被拿走的i的值(如果第一次循环且key是 a[left],那么就是给key)*/ while(i < j && key >= a[i]) /*这是i在当组内向前寻找,同上,不过注意与key的大小关系停止循环和上面相反, 因为排序思想是把数往两边扔,所以左右两边的数大小与key的关系相反*/ { i++; } a[j] = a[i]; } a[i] = key;/*当在当组内找完一遍以后就把中间数key回归*/ sort(a, left, i - 1);/*最后用同样的方式对分出来的左边的小组进行同上的做法*/ sort(a, i + 1, right);/*用同样的方式对分出来的右边的小组进行同上的做法*/ /*当然最后可能会出现很多分左右,直到每一组的i = j 为止*/}
对关键字序列(15,22,10+13+30,16,12,17)按从小到大进行快速排序写出排序过程+?
快速排序是一种常用的排序算法,它使用分治的策略将序列划分为较小的子序列,然后递归地对子序列进行排序。下面是将关键字序列 (15, 22, 10, 13, 30, 16, 12, 17) 按从小到大进行快速排序的过程:
1. 选择枢轴元素:从序列中选择一个枢轴元素,可以是任意一个元素。为了简单起见,我们选择序列的第一个元素作为枢轴元素。
枢轴元素:15
2. 分区过程:将序列中的其他元素根据与枢轴元素的大小关系分成两个子序列,小于枢轴的放在左边,大于枢轴的放在右边。
分区后的序列:(10, 13, 12) 15 (22, 30, 16, 17)
3. 递归排序:对左右两个子序列分别进行递归排序。
左子序列:(10, 13, 12)
右子序列:(22, 30, 16, 17)
4. 重复步骤 1~3,直到子序列的长度为 1 或 0。
对左子序列进行排序:
- 枢轴元素:10
- 分区后的序列:10 (13, 12)
- 对右子序列进行排序:
- 枢轴元素:13
- 分区后的序列:12 13
对右子序列进行排序:
- 枢轴元素:22
- 分区后的序列:(16, 17) 22 30
- 对左子序列进行排序:
- 枢轴元素:16
- 分区后的序列:16 (17)
- 对右子序列进行排序:
- 枢轴元素:17
- 分区后的序列:17
对右子序列进行排序:
- 枢轴元素:30
- 分区后的序列:30
5. 合并子序列:将排序后的左子序列、枢轴元素和右子序列按顺序合并起来。
排序结果:(10, 12, 13, 15, 16, 17, 22, 30)
最终的排序结果是 (10, 12, 13, 15, 16, 17, 22, 30),按从小到大排列。
快速排序的过程?
快速排序的概念很简单就是把序列分成三部分。一个中点,中点的左边都比中点“小”,右边都比中点“大”
然后再分别对左右两边进行相同的处理。可以想象这样会把序列不断切分。而当序列小于三个元素的时候,这么处理的结果就是从小到大排列。
这部分很简单,关键是怎么分那三部分。一般是这么做,换个序列...
8
4
2
1
7
首先取正中的元素,这里是2
然后再左边找比2大的,第一个8就是
再从右边找比2小的,是1
我们交换8和1
1
4
2
8
7
然后继续,1之后比2大的是4
但是8之后已经没有比2小的了,我们只能把2和4交换,同时记录中点的位置(因为2挪地方了)
1
2
4
8
7
然后2左边只有1个元素不用再处理了
右边的4
8
7我们以8为中点。
按照刚才的方法这里需要把8和7交换
4
7
8
8右边没了,处理4
7,就不说了,而且这个本身顺序也没问题,拼起来就是
(1)
2
((4
7)
8)
使用qsort
qsort(指向字符串的指针,多少元素,每个元素的大小(字节),比较函数);
要自己练习下就知道啦
首先要排的是第一个数a,目的是:a前的数比a小,a后的数比a大
49 38 65 97 76 13 27
第一次:27 38 65 97 76 13 49 (49和27比)
第二次:27 38 65 97 76 13 49 (49和38比)
第三次:27 38 49 97 76 13 65 (49和65比)
第四次:27 38 13 97 76 49 65 (49和13比)
第五次:27 38 13 49 76 97 65 (49和97比)
第六次:27 38 13 49 76 97 65 (49和76比)
始终拿无序序列的第一个数与其他数进行比较,49;
49在序列的左侧时与从右侧起第一个没有和它比较过的数比,小于49则和49调换位置,大于49的位置不变;49在右侧时方法类似;
(27 38 13)49(76 97 65)这样得到两组长度较短的无序数,非别排序
用27和38,13比较
用76和97,65比较
如何用java实现快速排序,简答讲解下原理
快速排序思想:
通过对数据元素集合Rn 进行一趟排序划分出独立的两个部分。其中一个部分的关键字比另一部分的关键字小。然后再分别对两个部分的关键字进行一趟排序,直到独立的元素只有一个,此时整个元素集合有序。
快速排序的过程,对一个元素集合R[ low ... high ] ,首先取一个数(一般是R[low] )做参照 , 以R[low]为基准重新排列所有的元素。
所有比R[low]小的放前面,所有比R[low] 大的放后面,然后以R[low]为分界,对R[low ... high] 划分为两个子集和,再做划分。直到low >= high 。
比如:对R={37, 40, 38, 42, 461, 5, 7, 9, 12}进行一趟快速排序的过程如下(注:下面描述的内容中元素下表从 0 开始):
开始选取基准 base = 37,初始位置下表 low = 0 , high = 8 , 从high=8,开始如果R[8] < base , 将high位置中的内容写入到R[low]中, 将high位置空出来, low = low +1 ;
从low开始探测,由于low=1 , R[low] > base ,所以将R[low]写入到R[high] , high = high -1 ;
检测到low < high ,所以第一趟快速排序仍需继续:
此时low=1,high=7,因为 R[high] < base ,所以将 R[high] 写入到到R[low]中,low = low + 1;
从low开始探测,low = 2 , R[low] >base ,所以讲R[low]写入到R[high],high=high-1;
继续检测到 low 小于high
此时low=2,high=6,同理R[high] < base ,将R[high] 写入到R[low]中,low=low+1;
从low继续探测,low = 3 , high=6 , R[low] > base , 将R[low]写入到R[high]中,high = high-1;
继续探测到low小于high
此时low=3,high=5,同理R[high] < base,将R[high]写入到R[low]中,low = low +1;
从low继续探测,low = 4,high=5,由于R[low] > base , 将R[low]写入到R[high]中,high = high -1 ;
此时探测到low == high == 4 ;该位置即是base所在的位置,将base写入到该位置中.
然后再对子序列Rs1 = {12,9,7,5} 和 Rs2={461,42,38,40}做一趟快速排序,直到Rsi中只有一个元素,或没有元素。
快速排序的Java实现:
private static boolean isEmpty(int[] n) {
return n == null || n.length == 0;
}
// ///////////////////////////////////////////////////
/**
* 快速排序算法思想——挖坑填数方法:
*
* @param n 待排序的数组
*/
public static void quickSort(int[] n) {
if (isEmpty(n))
return;
quickSort(n, 0, n.length - 1);
}
public static void quickSort(int[] n, int l, int h) {
if (isEmpty(n))
return;
if (l < h) {
int pivot = partion(n, l, h);
quickSort(n, l, pivot - 1);
quickSort(n, pivot + 1, h);
}
}
private static int partion(int[] n, int start, int end) {
int tmp = n[start];
while (start < end) {
while (n[end] >= tmp && start < end)
end--;
if (start < end) {
n[start++] = n[end];
}
while (n[start] < tmp && start < end)
start++;
if (start < end) {
n[end--] = n[start];
}
}
n[start] = tmp;
return start;
}
在代码中有这样一个函数:
public static void quickSortSwap(int[] n, int l, int h)
该函数可以实现,元素集合中特定的 l 到 h 位置间的数据元素进行排序。
49 38 65 97 13 27 49快速排序过程,简图
以49为基准,取出49,两个指针,前指针指向38,后指针指向最后一个49
首先移动后指针,找到27<49,将27放在 0 位置,后指针前移
再根据前指针查找,65>49,将65放在原27的位置
现在结果是 27,38, ,97,76,13,65,49
继续用后指针查找,13<49,放在空位中,后指针前移,
结果是 27,38,13,97,76, ,65,49
继续前指针查找,97>49,放在空位,变成27,38,13, ,76,97,65,49
然后前后指针都指向76,结束,将49放入空位中,得到27,38,13,49,76,97,65,49