快速排序算法原理与实现
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了快速排序算法原理与实现相关的知识,希望对你有一定的参考价值。
谁帮我说明一下,网上和书上写的文字没看明白。
这位匿名回答的大哥谢谢你了,但是我不想看网上那种回答,这个我都看了很多帖了,我想找个真正明白的给我讲讲。
没有人会呀?郁闷!
快速排序的基本思想就是从一个数组中任意挑选一个元素(通常来说会选择最左边的元素)作为中轴元素,将剩下的元素以中轴元素作为比较的标准,将小于等于中轴元素的放到中轴元素的左边,将大于中轴元素的放到中轴元素的右边。
然后以当前中轴元素的位置为界,将左半部分子数组和右半部分子数组看成两个新的数组,重复上述操作,直到子数组的元素个数小于等于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。
参考资料:快速排序算法_百度百科
参考技术A基本原理
从序列中任选一个数作为“基准”;所有小于“基准”的数,都挪到“基准”的左边;所有大于等于“基准”的数,都挪到“基准”的右边。
在这次移动结束之后,该“基准”就处于两个序列的中间位置,不再参与后续的排序;针对“基准”左边和右边的两个子序列,不断重复上述步骤,直到所有子序列只剩下一个数为止。
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,直至找到为止。
参考资料:百度百科 快速排序法
参考技术B快速排序算法的原理与实现:
快速排序与归并排序已有,也使用分治思想。下面介绍下对一个典型的子数组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年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
参考链接:百度百科-快速排序算法
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、持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
参考资料:百度百科-快速排序
参考技术D快速排序的原理:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
假设要排序的数组是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写入数组中间空位。然后递归地对外部更小的部分,循环地对其他部分进行排序。
参考资料来源:百度百科—快速排序算法
JavaScript算法(归并排序与快速排序)
归并排序与快速排序这两个算法放在一起,也是因为时间复杂度都是对数级别的。
目前看过的资料,归并排序看《学习JavaScript数据结构与算法》介绍的归并排序吧,快速排序直接看百度百科,讲的不错。通过这两份资料弄明白实现原理之后,最后看《学习JavaScript数据结构与算法》一书里的JS实现代码。
和之前的一样,嗯,《学习JavaScript数据结构与算法》这本书里都有现成ES5代码,就不在这儿写了,关键是弄清楚原理,然后JS代码每天写两遍,就OK了。ES6的代码周五之前补上。
目前着急把数据结构与算法给攻下了,这块知识占用了很长时间了,计划12月25号完成。春节前把JS设计模式搞定,成为一名合格的中级前端工程师。
以上是关于快速排序算法原理与实现的主要内容,如果未能解决你的问题,请参考以下文章