首页 > 编程知识 正文

排序算法快速排序的时间复杂度分析公式,各种排序算法时间复杂度

时间:2023-05-04 23:35:30 阅读:253289 作者:4612

快速排序的思想是在数组[p,r]中选择一个分区点q,将数组一分为2,同时将小于分区点的数值的放到分区点左侧[p,q-1],大于分区点的数值的放到分区点右侧[q+1,r],重复这个过程。

快速排序也是用到了分治思想和递归实现方式,这一点跟归并排序是一样的,但是快速排序的实现跟归并是完全不一样的。

归并排序是先分解再合并,从下到上解决问题。

快速排序是从上到下进行分区实现排序。俯视这个过程像是层次不同的拼图一般,完整组合成有序序列。

/** * 快速排序 * @param arr * @param n */ public static void quickSort(int[] arr,int n){ quickSort(arr,0,n-1); } /** * 根据分区点,递归继续分解子分区 * @param arr * @param p * @param r */ public static void quickSort(int[] arr,int p,int r){ if(p>=r){ return; } int q = partition(arr,p,r); quickSort(arr,p,q-1); quickSort(arr,q+1, r); } /** * 快排分区 *随机生成[p,r]区间内pivot,将比pivot大的放在其右侧,比pivot小的放在其左侧 * @param arr * @param p * @param r */ public static int partition(int[] arr,int p,int r){ int pivot = arr[r]; int i=p; for (int j = p; j < r; j++) { //当前元素比分区点小,则交换当前元素arr[j]到arr[i],也就是将小的移动到左侧,大的移动到右侧,而这个大小也是相对于分区点来说的,将来分区点会放到中间位置 if(arr[j] < pivot){ int temp = arr[j]; arr[j] = arr[i]; arr[i] = temp; //交换完位置(每确定完一个小元素后)以后,移动i指针到下一位(这个位置也是为下一个小元素准备的),只要arr[j]比分区点小,就将其交换到指针i的位置,并将i后移 i++; } } //迭代完成后,所有相对于pivot小的元素都被移动到靠左的位置(i指针动态指向的位置),所有相对于pivot大的元素都被移动到右侧,但是还是需要pivot将大小区间分割开 int temp = arr[i]; arr[i]=arr[r]; arr[r]=temp; return i; }

用一张图片解读下代码,这里描述的分区过程,将大于pivot的放在左边,将小于pivot的放在右边:

 

快速排序是原地排序算法吗?

快速排序是原地排序算法,不需要额外存储空间。内部元素交换完成排序。

快速排序是稳定排序算法吗?

6,8,7,6,3,5,9,4,在经过第一次分区操作之后,两个6的顺序会变,所以快速排序不是稳定排序算法。

快速排序算法的时间复杂度是多少?

因为快速排序跟归并排序一样都是采用的分治思想使用递归实现,所以归并排序的时间复杂度计算公式也一样适用,前提是每次快速排序选择的pivot都可以将数组正好一分为二。

T(1) = C;   n=1 时,只需要常量级的执行时间,所以表示为 C。
T(n) = 2*T(n/2) + n; n>1
 

但是,这种情况很难实现。极端情况下一个数组已经是有序,如果pivot每次都选择数组最后一个,那每次分区得到的两个子区间都是不均等的。大约需要n次分区才能完成整个快排。所以这种非常坏的情况下时间复杂度就从极好情况下的O(nlogn)退化成O(n^2).那么平均时间复杂度呢?这里可以说大部分情况下可以做到O(nlogn),极端情况下才会退化O(n^2),但是这个是可以用很多办法去避免的。

 

 

 

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。