前言:
眼前同学们对“算法复杂度为onlogn的排序方法”都比较注重,同学们都需要分析一些“算法复杂度为onlogn的排序方法”的相关内容。那么小编在网络上搜集了一些关于“算法复杂度为onlogn的排序方法””的相关文章,希望我们能喜欢,咱们快快来学习一下吧!快速排序(Quick Sort)是一种常用的排序算法,它的时间复杂度为O(nlogn),是在平均情况下具有良好性能的排序算法之一。
一、原理
快速排序算法采用了分治的思想,将一个大问题分解成若干个小问题来解决。其基本思路是选取一个基准元素,将数组分成两个子序列,其中一个子序列的所有元素都小于基准元素,另一个子序列的所有元素都大于或等于基准元素。然后再对这两个子序列进行递归操作,直到所有序列长度为1时排序完成。
快速排序的平均时间复杂度为O(nlogn),最坏情况下的时间复杂度为O(n^2),其中n为待排序的元素个数。快速排序对于大规模数据的排序效率比较高,是常用排序算法之一。
二、快速排序算法实现过程
快速排序的实现需要完成以下几步:
选择序列中的一个元素作为基准值(pivot),通常选择首个元素或末尾元素作为基准值;将低于基准元素的放到左边,高于或等于基准元素的放到右边。对基准值左右两侧的子序列分别重复上述步骤,直到所有元素均被排完序为止。
2.1 选择基准元素
选择基准元素是快速排序的第一步,其目的是将待排序数组分成两个子序列。最常用的方法是选取第一个元素作为基准元素。但是,如果待排序数组已经有序或近乎有序,那么选取第一个元素就会导致快速排序的时间复杂度变为O(n^2)。为了解决这个问题,可以采用随机化的方法来选择基准元素。
以下是选取第一个元素作为基准元素的代码实现:
public static int partition(int[] arr, int low, int high) { int pivot = arr[low]; //基准元素 while (low < high) { while (low < high && arr[high] >= pivot) { high--; } arr[low] = arr[high]; //将比基准元素小的移到低端 while (low < high && arr[low] <= pivot) { low++; } arr[high] = arr[low]; //将比基准元素大的移到高端 } arr[low] = pivot; //把基准元素放到最终位置 return low;}
以下是采用随机化方法选择基准元素的代码实现:
public static int partition(int[] arr, int low, int high) { int randomIndex = (int) (Math.random() * (high - low + 1)) + low; //随机选取一个位置 swap(arr, randomIndex, high); //交换基准元素和随机元素 int pivot = arr[high]; //基准元素 while (low < high) { while (low < high && arr[low] <= pivot) { low++; } arr[high] = arr[low]; //将比基准元素大的移到高端 while (low < high && arr[high] >= pivot) { high--; } arr[low] = arr[high]; //将比基准元素小的移到低端 } arr[high] = pivot; //把基准元素放到最终位置 return high;}private static void swap(int[] arr, int i, int j) { int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp;}2.2 将低于基准元素的放到左边,高于或等于基准元素的放到右边
这一步是快速排序的关键步骤,其代码实现如下:
public static void quickSort(int[] arr, int low, int high) { if (low < high) { int pivotIndex = partition(arr, low, high); quickSort(arr, low, pivotIndex - 1); //递归排序左半部分 quickSort(arr, pivotIndex + 1, high); //递归排序右半部分 }}
2.3 对基准值左右两侧的子序列分别重复上述步骤,直到所有元素均被排完序为止。
这一步是快速排序的递归过程,其代码实现如上文所示。
三、示例代码
下面是使用Java语言实现快速排序的示例代码:
import java.util.Arrays;public class QuickSort { public static void main(String[] args) { int[] arr = {32, 6, 17, 28, 10, 22, 43, 13, 48, 35}; System.out.println("Before sorting: " + Arrays.toString(arr)); quickSort(arr, 0, arr.length - 1); System.out.println("After sorting: " + Arrays.toString(arr)); } public static void quickSort(int[] arr, int low, int high) { if (low < high) { int pivotIndex = partition(arr, low, high); quickSort(arr, low, pivotIndex - 1); //递归排序左半部分 quickSort(arr, pivotIndex + 1, high); //递归排序右半部分 } } public static int partition(int[] arr, int low, int high) { int randomIndex = (int) (Math.random() * (high - low + 1)) + low; //随机选取一个位置 swap(arr, randomIndex, high); //交换基准元素和随机元素 int pivot = arr[high]; //基准元素 while (low < high) { while (low < high && arr[low] <= pivot) { low++; } arr[high] = arr[low]; //将比基准元素大的移到高端 while (low < high && arr[high] >= pivot) { high--; } arr[low] = arr[high]; //将比基准元素小的移到低端 } arr[high] = pivot; //把基准元素放到最终位置 return high; } private static void swap(int[] arr, int i, int j) { int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; }}四、动图效果演示
上面的动图效果的步骤,首先基准值取第一个元素32,然后逐一比较,把小于基准值的移到左侧,大于基准值的移到右侧。整个数组拆分成了P1、P2两个数组
接着对左侧的P1数组进行快速排序,基准值取第一个元素13,那么P1数组又被拆分成更小的左右两个数组P3、P4。
继续对上面拆分出来的P3数组快速排序,基准值取第一个元素10
左侧数组的长度已经是1,排序已经完成,开始对13的右边P4数组快速排序,基准值取第一个元素28,P4中没有比基准值28大的数字,所以只有左侧的P5数组
接着是28的左侧P5数组快速排序,基准值取第一个元素22,
结果数组长度已经是1,结束。
接着对32的右侧部分P2数组快速排序,基准值取第一个元素43
到这里,所有最小单位的数组都已经拆成了长度为1的数组,无法继续拆分,快速排序结束得到了最终的结果。