谁帮我说明一下,网上和书上写的文字没看明白。
这位匿名回答的大哥谢谢你了,但是我不想看网上那种回答,这个我都看了很多帖了,我想找个真正明白的给我讲讲。
没有人会呀?郁闷!
- okok云
-
快速排序的基本思想就是从一个数组中任意挑选一个元素(通常来说会选择最左边的元素)作为中轴元素,将剩下的元素以中轴元素作为比较的标准,将小于等于中轴元素的放到中轴元素的左边,将大于中轴元素的放到中轴元素的右边。
然后以当前中轴元素的位置为界,将左半部分子数组和右半部分子数组看成两个新的数组,重复上述操作,直到子数组的元素个数小于等于1(因为一个元素的数组必定是有序的)。
以下的代码中会常常使用交换数组中两个元素值的Swap方法,其代码如下
public static void Swap(int[] A, int i, int j){
int tmp;
tmp = A[i];
A[i] = A[j];
A[j] = tmp;
扩展资料:
快速排序算法 的基本思想是:将所要进行排序的数分为左右两个部分,其中一部分的所有数据都比另外一 部分的数据小,然后将所分得的两部分数据进行同样的划分,重复执行以上的划分操作,直 到所有要进行排序的数据变为有序为止。
定义两个变量low和high,将low、high分别设置为要进行排序的序列的起始元素和最后一个元素的下标。第一次,low和high的取值分别为0和n-1,接下来的每次取值由划分得到的序列起始元素和最后一个元素的下标来决定。
定义一个变量key,接下来以key的取值为基准将数组A划分为左右两个部分,通 常,key值为要进行排序序列的第一个元素值。第一次的取值为A[0],以后毎次取值由要划 分序列的起始元素决定。
从high所指向的数组元素开始向左扫描,扫描的同时将下标为high的数组元素依次与划分基准值key进行比较操作,直到high不大于low或找到第一个小于基准值key的数组元素,然后将该值赋值给low所指向的数组元素,同时将low右移一个位置。
如果low依然小于high,那么由low所指向的数组元素开始向右扫描,扫描的同时将下标为low的数组元素值依次与划分的基准值key进行比较操作,直到low不小于high或找到第一个大于基准值key的数组元素,然后将该值赋给high所指向的数组元素,同时将high左移一个位置。
重复步骤(3) (4),直到low的植不小于high为止,这时成功划分后得到的左右两部分分别为A[low……pos-1]和A[pos+1……high],其中,pos下标所对应的数组元素的值就是进行划分的基准值key,所以在划分结束时还要将下标为pos的数组元素赋值 为 key。
参考资料:快速排序算法_百度百科
- 慧慧
-
基本原理
从序列中任选一个数作为“基准”;所有小于“基准”的数,都挪到“基准”的左边;所有大于等于“基准”的数,都挪到“基准”的右边。
在这次移动结束之后,该“基准”就处于两个序列的中间位置,不再参与后续的排序;针对“基准”左边和右边的两个子序列,不断重复上述步骤,直到所有子序列只剩下一个数为止。
1、选择“基准”,并将其从原始数组分离
先获取基准的索引值,再使用splice数组方法取出基准值。
Tips:该实例中, 基准的索引值 = parseInt(序列长度 / 2)。
Tips:splice方法会改变原始数组。例如,arr = [1, 2, 3]; 基准索引值为1,基准值为2,原始数组变为arr = [1, 3]。
2、遍历序列,拆分序列
与“基准”比较大小,并拆分为两个子序列,小于“基准”的数存储于leftArr数组当中,大于等于“基准”的数存储于rightArr数组当中。
Tips:当然,也可以将 小于等于“基准”的数存于leftArr,大于“基准”的数存于rightArr。
由于要遍历序列,将每一个数与“基准”进行大小比较,所以,需要借助for语句来实现
3、递归调用,遍历子序列并组合子序列的结果
定义一个函数,形参用于接收数组
function quickSort(arr) { };
实现递归调用遍历子序列,用concat数组方法组合子序列的结果。
4、判断子序列的长度
递归调用的过程中,子序列的长度等于1时,则停止递归调用,返回当前数组。
扩展资料
一趟快速排序的算法是:
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,直至找到为止。
参考资料:百度百科 快速排序法
- 再也不做稀饭了
-
快速排序算法的原理与实现:
快速排序与归并排序已有,也使用分治思想。下面介绍下对一个典型的子数组A[p..r]进行快速排序的三步分治过程:
分解:数组A[p..r]被划分为两个(可能为空)子数组A[p..q-1]和A[q+1..r],使得A[p..q-1]中的每一个元素都小于等于A[q],而A[q]也小于等于A[p..q-1]中的每个元素,其中,计算下标q也是划分过程的一部分。
解决:通过递归调用快速排序,对子数组A[p..q-1]和A[q+1..r]进行排序。
合并:因为子数组都是原址排序的,所以不需要合并操作:数组A[p..r]已经有序。
通俗点讲就是把数组根据一个参照值划分为两部分,左边部分小于等于参照值,右边部分大于等于参照值,然后再不断递归调用该方法,直到数组只有一个元素,就认为其是有序的.注意:划分过程,左边部分和右边部分可以是不均衡的。例如:
//将数组排序成满足数组左边比中间值小,右边比中间值大的方法
int partition(int arr[], int left, int right)
{
int i = left, j = right;
int tmp;
//定义参照值为数组的中间值
int pivot = arr[(left + right) / 2];
while (i <= j) {
//当arr[i]小于参照值时,符合左边小的原则,不需调换位置,直接跳过,直到找到不满足条件的A[i]时终止该循环
while (arr[i] < pivot)
i++;//当arr[j]大于参照值时,符合右边大的原则,不需调换位置,直接跳过,直到找到不满足条件的A[j]时终止该循环
while (arr[j] > pivot)
j--;//i小于j时,完成a[i]和a[j]的交换
if (i <= j) {
tmp = arr[i];arr[i] = arr[j];
arr[j] = tmp;
i++;
j--;
} };
//返回的i就是满足i左边的值比i小.i右边的值比i大
return i;
}void quickSort(int arr[], int left, int right) {
int index = partition(arr, left, right);
// System.out.println("index"+index);
if (left < index - 1){
quickSort(arr, left, index - 1);// System.out.println(Arrays.toString(arr));
}if (index < right){
quickSort(arr, index, right);// System.out.println(Arrays.toString(arr));
}
}@Test public void testQuickSort(){ int a[] = {222,5, 2, 4, 6, 1, 3, 11, 9, 10, 8, 7,0};
quickSort(a,0,a.length - 1);System.out.println("最终排序结果"+Arrays.toString(a));
}扩展资料:
快速排序(Quicksort)是对冒泡排序的一种改进。
快速排序由C. A. R. Hoare在1962年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
参考链接:百度百科-快速排序算法
- CarieVinne
-
1、快速排序算法的原理:
想必大家都学过和用过冒泡排序,这应该是大家成为程序员道路上学的第一个算法,那么我们的快速排序算法其实是在冒泡排序的基础上的一个改进,快速排序算法是利用一趟快速排序,一趟快排一般都是取第一个数作为准基数进行排序,将一串数据分成两个部分。第一部分都比准基数小,第二部分都比准基数大。
如:(-------第一部分------准基数------第二部分------),也就这样以准基数分成了两个部分,接下来这两个部分继续使用一趟快排(可以用递归的方法),以此类推,最后数据显示是从小到大的排列顺序。
2、快速排序步骤:
我们先建立一组数据:
(1)根据一趟快排的规则,我们先定下一个准基数,通常准基数都是数据的第一位也就是这里的数字12。
(2)然后一趟快排是先从下标6向左进行和准基数12的比较,比较完一个后,然后再从下标0向右进行和准基数12的比较。
(3)我们进行比较的规则和操作是:从下标6向左进行和准基数12的比较,只要遇到的数据小于准基数12的时候我们就将这个数和准基数12进行替换,然后再执行从下标0向右进行和准基数12的比较.
如:我们从下标6向左进行和准基数12的比较,20>12,不满足一趟快排的规则,寻找下一位,1<12,所以我们将下标0的值和下标5的值进行替换替换后的结果为:
(4)执行完上一步之后,我们再从下标0向右进行和准基数12的比较,这里的规则是只要遇到的数据大于准基数12的时候我们就将这个数和准基数12进行替换,和上面一步恰恰相反。
如:我们再从下标0向右进行和准基数12的比较,30>12,所以我们将下标1的值和下标5的值进行替换。
(5)从左到右查找和从右到左的查找,都是通过下标来查找的,只要它们两者下标不相遇就可以一直进行排序,直到相遇后第一次一趟快排结束,不过,总有一次会相遇的。好了,执行完上一步之后,基本的套路也就生成了,接下来继续执行(3),(4)步骤,直到排序完成。
第一趟排序完成的结果为:
从上面第一次一趟快排结果我们可以看出从准基数那里将数据分成的两个部分,前面那一部分,1,5,5,都比准基数要小,后面的16,30,20,则比准基数要大。但是这还不算完,我们明显的看到排序并非从小到大。所以说我们需要把这整一条数据分成1,5,5和16,30,20这两个条数据再次进行一趟快排(递归),以此类推,直到排出一条规矩的数据为止。
最后的结果为:
3、快速排序代码实现:
public class QuickSort {
public static void main(String[] args) {
int arr[] = {49、38、65、97、76、13、27、49};
quickSort(arr, 0, 7);
System.out.println(Arrays.toString(arr));
}
public static void quickSort(int[] arr, int left, int right) {
if (left < right) {
int mid = partion(arr, left, right);
quickSort(arr, 0, mid - 1);
quickSort(arr, mid + 1, right);
}
}
public static void swap(int[] arr, int l, int r) {
int tmp = arr[l];
arr[l] = arr[r];
arr[r] = tmp;
}
public static int partion(int[] arr, int left, int right) {
while (left < right) {
while (left < right && arr[left] <= arr[right]) {
right--;
}
if (left<right){
swap(arr, left, right);
}
while (left < right && arr[left] <= arr[right]) {
left++;
}
if (left<right){
swap(arr, left, right);
}
}
return left;
}
}扩展资料:
快速排序由冒泡排序演变而来,冒泡排序原理:
1、比较相邻的元素。如果第一个比第二个大,就交换他们两个。
2、对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
3、针对所有的元素重复以上的步骤,除了最后一个。
4、持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
参考资料:百度百科-快速排序
- 可乐
-
快速排序的原理:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
假设要排序的数组是A[1]……A[N],首先任意选取一个数据(通常选用第一个数据)作为关键数据,然后将所有比它的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一躺快速排序。一躺快速排序的算法是:
1)设置两个变量I、J,排序开始的时候I:=1,J:=N;
2)以第一个数组元素作为关键数据,赋值给X,即X:=A[1];
3)从J开始向前搜索,即由后开始向前搜索(J:=J-1),找到第一个小于X的值,两者交换;
4)从I开始向后搜索,即由前开始向后搜索(I:=I+1),找到第一个大于X的值,两者交换;
5)重复第3、4步,直到I=J。扩展资料
与普通快排不同的是,关键数据是一段buffer,首先将之前和之后的M/2个元素读入buffer并对该buffer中的这些元素进行排序,然后从被排序数组的开头(或者结尾)读入下一个元素,假如这个元素小于buffer中最小的元素,把它写到最开头的空位上;假如这个元素大于buffer中最大的元素,则写到最后的空位上。
否则把buffer中最大或者最小的元素写入数组,并把这个元素放在buffer里。保持最大值低于这些关键数据,最小值高于这些关键数据,从而避免对已经有序的中间的数据进行重排。完成后,数组的中间空位必然空出,把这个buffer写入数组中间空位。然后递归地对外部更小的部分,循环地对其他部分进行排序。
参考资料来源:百度百科—快速排序算法
- FinCloud
-
快速排序的基本原理就是每一次把一个值放到它应该的位置上,然后序列被分为两部分,这个数前一部分后一部分,再对这两部分分别进行快速排序即可。
如此递归下去,但是对于基本有序的数列,你就不要快排了,那样效率会很低。
扩展资料:
算法(Algorithm)是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制。也就是说,能够对一定规范的输入,在有限时间内获得所要求的输出。
如果一个算法有缺陷,或不适合于某个问题,执行这个算法将不会解决这个问题。不同的算法可能用不同的时间、空间或效率来完成同样的任务。一个算法的优劣可以用空间复杂度与时间复杂度来衡量。
算法中的指令描述的是一个计算,当其运行时能从一个初始状态和(可能为空的)初始输入开始,经过一系列有限而清晰定义的状态,最终产生输出并停止于一个终态。一个状态到另一个状态的转移不一定是确定的。随机化算法在内的一些算法,包含了一些随机输入。
形式化算法的概念部分源自尝试解决希尔伯特提出的判定问题,并在其后尝试定义有效计算性或者有效方法中成形。
这些尝试包括库尔特·哥德尔、Jacques Herbrand和斯蒂芬·科尔·克莱尼分别于1930年、1934年和1935年提出的递归函数,阿隆佐·邱奇于1936年提出的λ演算,1936年Emil Leon Post的Formulation 1和艾伦·图灵1937年提出的图灵机。即使在当前,依然常有直觉想法难以定义为形式化算法的情况。
参考资料:百度百科-算法
- 牛云
-
快速排序的原理:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小。
然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
假设要排序的数组是A[1]……A[N],首先任意选取一个数据(通常选用第一个数据)作为关键数据,然后将所有比它的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一躺快速排序。一躺快速排序的算法是:
1、设置两个变量I、J,排序开始的时候I:=1,J:=N;
2、以第一个数组元素作为关键数据,赋值给X,即X:=A[1];
3、从J开始向前搜索,即由后开始向前搜索(J:=J-1),找到第一个小于X的值,两者交换;
4、从I开始向后搜索,即由前开始向后搜索(I:=I+1),找到第一个大于X的值,两者交换;
5、重复第3、4步,直到I=J。
扩展资料:
设要排序的数组是A[0]……A[N-1],首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。
值得注意的是,快速排序不是一种稳定的排序算法,也就是说,多个相同的值的相对位置也许会在算法结束时产生变动。
一趟快速排序的算法是:
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指针位置不变。
参考资料:百度百科 快速排序法
- 我不懂运营
- 皮皮
- max笔记
-
1、设置两个变量I、J,排序开始的时候I:=1,J:=N;
2、以第一个数组元素作为关键数据,赋值给X,即X:=A[1];
3、从J开始向前搜索,即由后开始向前搜索(J:=J-1),找到第一个小于X的值,两者交换;
4、从I开始向后搜索,即由前开始向后搜索(I:=I+1),找到第一个大于X的值,两者交换;
5、重复第3、4步,直到I=J;
- snjk
-
快速排序的原理和实现(纯白话文口述)
你好,上面是我的博客,原理讲的非常透彻,望对你有用。
- cloud123
-
概述
快速排序是由东尼·霍尔所发展的一种排序算法。在平均状况下,排序 n 个项目要Ο(nlogn)次比较。事实上,快速排序通常明显比其他Ο(nlogn) 算法更快,因为它的内部循环(inner loop)可以在大部分的架构上很有效率地被实现出来,并且在大部分真实世界的数据,可以决定设计的选择,减少所需时间的二次方项之可能性。
快速排序,通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,然后分别对这两部分记录继续进行排序,以达到整个序列有序的目的。
形象图示:
步骤
选择一个基准元素,通常选择第一个元素或者最后一个元素
通过一趟排序将待排序的记录分割成独立的两部分,其中一部分记录的元素值均比基准元素值小。另一部分记录的元素值均比基准值大
此时基准元素在其排好序后的正确位置
然后分别对这两部分记录用同样的方法继续进行排序,直到整个序列有序。
实例
原始数据:
3 5 2 6 2
选择 3 作为基准
第一轮
?
1234567
从右往左找比3小的,2符合,将2和3对调2 5 2 6 3对调一次,查找的方向反向,从左向右找比3大的,5符合,对调2 3 2 6 5再从右往左找比3小的,2符合,对调2 2 3 6 5一轮结束
第二轮
?
12
对 [2 2] 采用同上的方式进行,得到2 2 3 6 5
第三轮
?
12
对 [6 5] 采用同上的方式进行,得到2 2 3 5 6
最终结果
2 2 3 5 6
代码实现(Java)
?
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
package com.coder4j.main.arithmetic.sorting; public class Quick { private static int mark = 0; /** * 辅助交换方法 * * @param array * @param a * @param b */ private static void swap(int[] array, int a, int b) { if (a != b) { int temp = array[a]; array[a] = array[b]; array[b] = temp; // 找到符合的,对调 System.out.println("对调" + array[a] + "与" + array[b] + ",得到"); for (int i : array) { System.out.print(i + " "); } System.out.println(); } } /** * 新一轮分隔 * * @param array * @param low * @param high * @return */ private static int partition(int array[], int low, int high) { int base = array[low]; mark++; System.out.println("正在进行第" + mark + "轮分隔,区域:" + low + "-" + high); while (low < high) { while (low < high && array[high] >= base) { high--; System.out.println("从右往左找比" + base + "小的,指针变动:" + low + "-" + high); } swap(array, low, high); while (low < high && array[low] <= base) { low++; System.out.println("从左往右找比" + base + "大的,指针变动:" + low + "-" + high); } swap(array, low, high); } return low; } /** * 对数组进行快速排序,递归调用 * * @param array * @param low * @param heigh * @return */ private static int[] quickSort(int[] array, int low, int heigh) { if (low < heigh) { int division = partition(array, low, heigh); quickSort(array, low, division - 1); quickSort(array, division + 1, heigh); } return array; } /** * 快排序 * * @param array * @return */ public static int[] sort(int[] array) { return quickSort(array, 0, array.length - 1); } public static void main(String[] args) { int[] array = { 3, 5, 2, 6, 2 }; int[] sorted = sort(array); System.out.println("最终结果"); for (int i : sorted) { System.out.print(i + " "); } } }
测试输出结果:
?
12345678910111213141516171819
全选复制放进笔记正在进行第1轮分隔,区域:0-4对调2与3,得到2 5 2 6 3从左往右找比3大的,指针变动:1-4对调3与5,得到2 3 2 6 5从右往左找比3小的,指针变动:1-3从右往左找比3小的,指针变动:1-2对调2与3,得到2 2 3 6 5从左往右找比3大的,指针变动:2-2正在进行第2轮分隔,区域:0-1从右往左找比2小的,指针变动:0-0正在进行第3轮分隔,区域:3-4对调5与6,得到2 2 3 5 6从左往右找比6大的,指针变动:4-4最终结果2 2 3 5 6
经测试,与实例中结果一致。