我试图实现就地快速排序,最后一个元素作为我的支点。下面附上我的代码
public static void main(String[] args){
int[] input = {3,2,4,6,10,1,9,7,5};
quickSort(input, 0, input.length-1);
}
public static void swap(int[] array, int i, int j) {
int tmp = array[i];
array[i] = array[j];
array[j] = tmp;
}
public static int partition(int arr[], int left, int right) {
int pivot = arr[right];
int high = right-1;
while(left < high){
while(arr[left] < pivot){
left++;
}
while(arr[high] > pivot){
high--;
}
swap(arr,left, high);
left++;
high--;
}
swap(arr, left, pivot);
System.out.println(Arrays.toString(arr));
return left;
}
public static void quickSort(int arr[], int left, int right) {
int index = partition(arr, left, right);
quickSort(arr, left, index - 1);
quickSort(arr, index, right);
}
出于某种原因,我的代码给了我一个IndexOutOfBounds异常,它不能准确地对数组排序。我不知道为什么会出现这个错误。
如果我理解正确,我们应该把最后一个元素作为我们的轴心。然后,我们将左指针向右迭代,直到找到一个大于枢轴的元素。之后,我们从右侧(继续向左移动)执行相同的操作,直到找到一个小于轴的元素。然后我们交换这些元素,继续做同样的事情。
最后,当左/右指针相同时,我们用枢轴交换中心值。
这是正确的思考方式吗?如果是,我的代码有哪些错误?任何帮助都将不胜感激
在假设最终数组元素是最小元素的情况下跟踪这段代码。调整高的循环会不断地递减高,因为彼此的数组元素比枢轴大,所以最终高的会从数组的前面掉下来,导致你的越界访问。
要解决此问题,请在该循环中添加另一个复选框,以确保您没有出现左高交叉。然后,您可能需要添加一些额外的逻辑,以便将其作为特例处理。
有几个错误:
>
向左添加
检查
arr[高]
swap(arr,左,枢轴)
是错误的。您应该使用位置(而不是值)与轴交换左侧。它应该是
swap(arr、左、右)
。
您应该选中左侧的
修复这些错误时,代码应如下所示:
public static void main(String[] args){
int[] input = {3,2,4,6,10,1,9,7,5};
quickSort(input, 0, input.length-1);
}
public static void swap(int[] array, int i, int j) {
int tmp = array[i];
array[i] = array[j];
array[j] = tmp;
}
public static int partition(int arr[], int left, int right) {
int pivot = arr[right];
int high = right;
while(left < high){
while(left < high && arr[left] < pivot){
left++;
}
while(left < high && arr[high] >= pivot){
high--;
}
swap(arr,left, high);
}
swap(arr, left, right);
System.out.println( Arrays.toString(arr));
return left;
}
public static void quickSort(int arr[], int left, int right) {
if( left < right)
{
int index = partition(arr, left, right);
quickSort(arr, left, index - 1);
quickSort(arr, index, right);
}
}
尝试使用Hoare分区方案实现快速排序,但我遇到了一个问题,即无论数组大小如何,更改pivot的索引都会导致溢出。代码: 这个实现选择低索引(这里名为min)作为轴心元素,这样做很好。但是,将pivot元素更改为任何其他索引都会导致StackOverflow错误,而与正在排序的数组的大小无关。(错误参考第3行,其中调用了partition())我最好在(min,max)范围内随机选择pivot元素
因为最坏情况下的快速排序复杂度为O(n^2) 在递增顺序的情况下,当pivot选择第一个或最后一个元素时,它给出了正确的最坏情况复杂度O(n^2),因为树的一个子元素总是空的 但是当枢轴选择中间时,我感到困惑?它将树分成两半,使其复杂性O(n.logn) 假设10 20 30 40 50 60 70枢轴=40 (10 20 30 ) 40 (50 60 70) 左侧枢轴20,右侧枢轴60 (10)
我在一些地方读到,如果我们不选择第一个或最后一个元素作为轴心,我们应该在分区开始之前首先将其与第一个或最后一个位置交换。所以我尝试了一个例子,我用这个算法得到了正确的分区https://www.cs.auckland.ac.nz/software/AlgAnim/qsort1a.html 此分区方法使用左指针和右指针。它将左指针移向中心,直到找到大于轴的图元。然后将右指针移向中心,直到找到一个小于
返回一个数组中除了最后一个元素以外的所有元素。 使用 arr.slice(0,-1) 返回排除了最后一个元素的数组。 const initial = arr => arr.slice(0, -1); initial([1, 2, 3]); // [1,2]
我正在读关于快速排序的书,看不同的实现,我正试着去想一些事情。 在这个实现中(当然可以),枢轴被选为中间元素,然后左右指针相应地向右和向左移动,将元素交换到围绕枢轴的分区中。 我正在尝试数组[4,3,2,6,8,1,0]。 在第一个分区上,pivot为6,并且所有左侧元素都已小于6,因此左指针将停止在pivot处。在右侧,我们将0与6交换,然后1与8交换,因此在第一次迭代结束时,数组将如下所示:
快速排序是由东尼·霍尔所发展的一种排序算法。在平均状况下,排序 n 个项目要 Ο(nlogn) 次比较。在最坏状况下则需要 Ο(n2) 次比较,但这种状况并不常见。事实上,快速排序通常明显比其他 Ο(nlogn) 算法更快,因为它的内部循环(inner loop)可以在大部分的架构上很有效率地被实现出来。 快速排序使用分治法(Divide and conquer)策略来把一个串行(list)分为两