我正在努力实施quicksort作为一些练习和自我审查。目前,这只是一个原始整数数组的简单实现。在让这个工作正常之后,我计划将其设为通用。
我在下面的内容中仍然有一个小小的错误,我无法追踪到。我最初编写它只是使用左索引作为枢轴,一切正常。然而,一旦我完成了它的编写并将其切换为使用随机支点,事情就不再适合了。我的测试数组变得几乎排序,但是一些元素仍然是它们应该存在的两到三个索引。
以下是我的一些测试用例,它们在执行此操作时表现出不正确的行为:
6, 5, 1, 3, 8, 4, 7, 9, 2
1, 2, 3, 4, 5
5, 4, 3, 2, 1
/**
* Sort an integer array using quicksort
*
* @param a Array to sort
*/
public static void quicksort(int[] a) {
partition(0, a.length - 1, a);
}
/**
* Partition a section of an integer array around a randomly selected pivot within that section
*
* @param left Lower-bound index of section (inclusive)
* @param right Upper-bound index of section (inclusive)
* @param a Array to perform partitioning within
*/
private static void partition(int left, int right, int[] a) {
// Exit if partition is only a single element
if (right - left < 1) { return; }
// Select a pivot at random
int pivot = ThreadLocalRandom.current().nextInt(left, right + 1);
// Move pivot to left-most position (get out of the way)
swap(left, pivot, a);
// Perform partitioning
int cur = left + 1;
for (int i = left + 1; i <= right; i++) {
if (a[i] < a[pivot]) {
swap(i, cur, a);
cur++;
}
}
// Put pivot back where it belongs
swap(left, cur - 1, a);
// Partition the two new partitions
partition(left, cur - 2, a);
partition(cur, right, a);
}
/**
* Swaps two elements in an array of integers
*
* @param i Index of first element to swap
* @param j Index of second element to swap
* @param a Integer array to perform swap on
*/
private static void swap(int i, int j, int[] a) {
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
答案 0 :(得分:1)
将我的评论转换为答案:
在代码的这一部分中,您将使用最左边的元素交换pivot元素:
// Select a pivot at random
int pivot = ThreadLocalRandom.current().nextInt(left, right + 1);
// Move pivot to left-most position (get out of the way)
swap(left, pivot, a);
但是,您实际上并未更改pivot元素的索引。这意味着在这个分区逻辑中,你正在查看数组中的错误索引:
for (int i = left + 1; i <= right; i++) {
if (a[i] < a[pivot]) {
swap(i, cur, a);
cur++;
}
}
答案 1 :(得分:0)
好的,尝试使用left而不是pivot。它将颠倒列表的种类。
if (a[i] > a[left]) {
swap(i, cur, a);
cur++;
}
您没有考虑更改。
我更习惯使用右侧的枢轴。我保持你的实施很小。我的问题是,首先必须是&gt;左边和快速分区(左,cur-1,a)可能是必要的。
交换位置也应该已经排序。您可以通过基于正确的方法对此进行说明。
partition(left, cur -1 , a);
partition(cur + 1, right, a);
您可以在Wikipedia
了解实施情况我的代码在编码地运行。
public class HelloWorld{
int[] a = null;
/**
* Sort an integer array using quicksort
*
* @param a Array to sort
*/
public void quicksort() {
partition(0, a.length - 1, a);
}
/**
* Partition a section of an integer array around a randomly selected pivot within that section
*
* @param left Lower-bound index of section (inclusive)
* @param right Upper-bound index of section (inclusive)
* @param a Array to perform partitioning within
*/
private void partition(int left, int right, int[] a) {
// Exit if partition is only a single element
if (right <= left || right - left == 0) { return; }
// Select a pivot at random
int pivot = left + new java.util.Random().nextInt(right - left);
pivot = right;
// Move pivot to left-most position (get out of the way)
swap(right, pivot, a);
// Perform partitioning
int cur = left;
for (int i = left; i < right; i++) {
if (a[i] <= a[right]) {
swap(i, cur, a);
cur++;
}
}
// Put pivot back where it belongs
swap(cur, right , a);
// Partition the two new partitions
partition(left, cur -1 , a);
partition(cur + 1, right, a);
}
/**
* Swaps two elements in an array of integers
*
* @param i Index of first element to swap
* @param j Index of second element to swap
* @param a Integer array to perform swap on
*/
private void swap(int i, int j, int[] a) {
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
public static void main(String []args){
int[] arr = new int[]{0,4,2,3,9,11,20,100,50,32,45,27,13,2,1,4,99,1,4};
HelloWorld hw = new HelloWorld();
hw.a = arr;
hw.quicksort();
for(int i = 0;i< arr.length;i++){
System.out.println(arr[i]);
}
}
}
以下是带左侧枢轴的代码。
public class HelloWorld{
int[] a = null;
/**
* Sort an integer array using quicksort
*
* @param a Array to sort
*/
public void quicksort() {
partition(0, a.length - 1, a);
}
/**
* Partition a section of an integer array around a randomly selected pivot within that section
*
* @param left Lower-bound index of section (inclusive)
* @param right Upper-bound index of section (inclusive)
* @param a Array to perform partitioning within
*/
private void partition(int left, int right, int[] a) {
// Exit if partition is only a single element
if (right <= left || right - left == 0) { return; }
// Select a pivot at random
int pivot = left + new java.util.Random().nextInt(right - left);
// Move pivot to left-most position (get out of the way)
swap(left, pivot, a);
// Perform partitioning
int cur = left + 1;
for (int i = left +1 ; i <= right; i++) {
if (a[i] < a[left]) {
swap(i, cur, a);
cur++;
}
}
// Put pivot back where it belongs
swap(cur - 1 , left , a);
// Partition the two new partitions
partition(left, cur - 2 , a);
partition(cur , right, a);
}
/**
* Swaps two elements in an array of integers
*
* @param i Index of first element to swap
* @param j Index of second element to swap
* @param a Integer array to perform swap on
*/
private void swap(int i, int j, int[] a) {
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
public static void main(String []args){
int[] arr = new int[]{6, 5, 1, 3, 8, 4, 7, 9, 2};
HelloWorld hw = new HelloWorld();
hw.a = arr;
hw.quicksort();
for(int i = 0;i< arr.length;i++){
System.out.println(arr[i]);
}
}
}