快速排序[算法]

    科技2022-07-16  118

    快速排序是我们经常用到的一种排序算法,它相比与 冒泡排序,时间的复杂度更小,速度更快,排序采用了二分的思想。 快速排序的思想:从序列的两端开始“探测”,首先得找一个基准A(一般是从左边找),用两个变量i、j分别指向序列的最左边和最右边,然后先移动j,先从右往左找到一个比A小的数,然后再移动i,从左往右找一个大于A的数,然后交换他们,然后j继续向左挪动(如果基准是左边第一个的话,必须j先移动),找比基准小的数,找到后,i继续向右挪动,重复上述操作,直到i和j相遇了,此时,执行最后的步骤:将基准的数,和相遇位置下标下的值 交换。当然这只是第一轮的结束,然后第一轮结束后,序列被划分为两部分:比基准小的在左边,比基准大的在右边,然后继续对这两部分序列进行上述的排序操作,直到两边都排好顺序,这样快速排序才结束。 因为快速排序是不断地对序列划分,再排序的,因此需要利用递归来实现。 各种排序的算法的时间复杂度如图: 快速排序的具体操作步骤如下: 1:从左边随便找一个基数(为了方便,就找最左边的那个) 2:然后最左边的那个下标记作i ,最右边的记作j ,然后,从右边找到一个比 之前那个基数小的数, 记录那个数的下标,然后,从左边找到一个比之前 那个基数大的数,同样的,记录它的下标。 3:交换这两个数; 4:重复2,和3 操作,直到i==j ,然后让第一个数 和 第i个数 交换; 不断重复上述过程,直至最后 完成了两个数之间的排序,则排序完成。 具体实现代码如下:

    #include<iostream> #include<cstring> #include <set> #include <map> #include <ctime> #include <bitset> #include <sstream> #include <algorithm> #include<math.h> #include<stdio.h> #include<stdlib.h> #include<conio.h>//getch()的头文件 #include<vector> #include<queue> #include<stack> using namespace std; int a[100],n;//定义全局变量,这两个变量需要在子函数中使用 void quicksort(int left,int right) { int i,j,t,temp; if(left>=right) //快速排序的终止条件 return; temp=a[left]; //temp中存的就是基准数 i=left; j=right; while(i!=j||i<j) { //顺序很重要,要先从右往左找 while(a[j]>=temp && i<j) //i必须小于j j--; //再从左往右找 while(a[i]<=temp && i<j) //i必须小于j i++; //交换两个数在数组中的位置 if(i<j)//当i,j没有相遇时 { t=a[i]; a[i]=a[j]; a[j]=t; } } a[left]=a[i]; //i==j 或者 i>j的时候(最后两两比较 就会出现 i >j),交换位置 a[i]=temp; quicksort(left,i-1);//继续处理左边的,这里是一个递归的过程 quicksort(i+1,right);//继续处理右边的,这里是一个递归的过程 } int main() { int i,j,t; //读入数据 scanf("%d",&n); for(i=1;i<=n;i++) scanf("%d",&a[i]); quicksort(1,n); //快速排序调用 //输出排序后的结果 for(i=1;i<=n;i++) printf("%d ",a[i]); return 0; }

    注意:步骤2 必须要从右边开始找,否则会出错,为什么呢? 举个例子 比如 一组数 为 6 1 2 7 9 ,如果我们先从左边找,找一个比6大的数值,那么这个数值是7 然后,我们再从右边找一个比6小的数,因为 循环里的条件为:while(a[j]>=temp(基准数的值)&& i<j) j–; // 所以,如果从9开始找的话,那么,j最终会 停留在7上(此时 i==j ,不满足i<j ) 所以会跳出循环,执行循环外的代码:将基准数跟这个 i= = j的 位置的数值交换 ,最终第一轮排序后的结果是: 7 1 2 6 9 ,然后 就 不符合我们快速排序的要求:基准左边的数都比基准小,基准右边的数都比基准大。

    我们第一轮排序需要的结果是:2 1 6 7 9 这才能保证,6 左边的所有数字 都 比6小,然后 右边的数字都比6大,这才符合快速排序的思想与要求。 因此,快速排序 要先从右边开始找一个比基准大的数,当然,从右边找是因为基准一般是左边的第一个(如果基准在右边的话,当然可以反过来操作:即可以在左边找大的,右边找小的)

    转载请注明原文地址:https://blackberry.8miu.com/read-9097.html
    最新回复(0)