我这里有我的快速排序课程
package week4;
class QuickSort<T extends Comparable<? super T>> {
public void display(T[] array) {
int index;
for (index = 0; index < array.length - 1; index++)
System.out.print(array[index] + ", ");
System.out.println(array[index]);
}
private void swap(T[] a, int i, int j) {
T temp = a[i];
a[i] = a[j];
a[j] = temp;
display(a);
}
public void order(T[] a, int i, int j) {
if (a[i].compareTo(a[j]) > 0)
swap(a, i, j);
}
public void sortFirstMiddleLast(T[] a, int first, int mid, int last) {
order(a, first, mid); // make a[first] <= a[mid]
order(a, mid, last); // make a[mid] <= a[last]
order(a, first, mid); // make a[first] <= a[mid]
}
public int partition(T[] arr, int first, int last) {
int mid = (first + last) / 2;
sortFirstMiddleLast(arr, first, mid, last);
swap(arr, mid, last - 1);
int pivotIndex = last - 1;
T pivot = arr[pivotIndex];
int indexFromLeft = first + 1;
int indexFromRight = last - 2;
boolean done = false;
while (!done) {
while (arr[indexFromLeft].compareTo(pivot) < 0)
indexFromLeft++;
while (arr[indexFromRight].compareTo(pivot) > 0)
indexFromRight--;
if (indexFromLeft < indexFromRight) {
swap(arr, indexFromLeft, indexFromRight);
indexFromLeft++;
indexFromRight--;
} else
done = true;
}
// place pivot between Smaller and Larger subarrays
swap(arr, pivotIndex, indexFromLeft);
pivotIndex = indexFromLeft;
// Smaller = a[first pivotIndex-1]
// Pivot = a[pivotIndex]
// Larger = a[pivotIndex + 1..the last]
return pivotIndex;
}
}
public class Project1B {
public static void main(String args[]) {
QuickSort<Integer> ob = new QuickSort<Integer>();
Integer[] arr = { 10, 7, 8, 9, 1, 5 };
int n = arr.length;
ob.partition(arr, 0, n - 1);
System.out.println("sorted array");
ob.display(arr);
}
}
我的输出是这个..:
8、7、10、9、1、5
8、7、5、9、1、10
5,7,8,8,9,1,10
5,7,1,9,9,8,10
5,7,1,8,9,10
排序数组
5,7,1,8,9,10
我的问题是枢轴由于某种原因而没有排序,我不确定为什么...我尝试调试并尝试使用google,但是我很难弄清楚它... < / p>
答案 0 :(得分:1)
这似乎是快速排序算法的某种混淆实现。
首先,我不知道使用sortFirstMiddleLast
方法的意义。我们当然不能说调用此方法后,三个数字在数组中的正确位置。例如,如果这三个数字恰好是数组中的三个最大数字,会发生什么?它也不是快速排序算法的一部分。我会摆脱这种方法。
接着,我们在交换元素时必须包括数组的第一个和最后一个元素,以确保它们位于轴的右侧。因此,替换行
swap(arr, mid, last - 1);
int pivotIndex = last - 1;
T pivot = arr[pivotIndex];
int indexFromLeft = first + 1;
int indexFromRight = last - 2;
使用
swap(arr, mid, last);
int pivotIndex = last;
T pivot = arr[pivotIndex];
int indexFromLeft = first;
int indexFromRight = last - 1;
接下来,我们需要看一下这两个while
循环:
while (arr[indexFromLeft].compareTo(pivot) < 0)
indexFromLeft++;
while (arr[indexFromRight].compareTo(pivot) > 0)
indexFromRight--;
保证第一个循环在要排序的范围内以indexFromLeft
结尾,因为在某个点arr[indexFromLeft]
将是一个大于或等于枢轴的数字。如果枢轴碰巧是最大数量,则包括枢轴本身,因为将枢轴放在我们正在排序的子数组的末尾。
另一方面,如果arr[indexFromRight]
小于(或等于)枢轴,则第二个循环将终止。但是,如果枢轴本身是要排序的范围内的最小数字,则indexFromRight
将偏离该范围。实际上,如果支点恰好是整个数组中的最小数,则没有什么可以阻止此循环
从数组的开头掉落并抛出ArrayIndexOutOfBoundsException。
我们可以通过添加防止indexFromRight
超出我们要排序范围的条件来避免这种情况:
while (indexFromRight > first && arr[indexFromRight].compareTo(pivot) > 0)
indexFromRight--;
最后,您的代码似乎忽略了快速排序算法工作原理的一个关键方面:它是递归的。一旦将透视图放置在正确的位置,您就必须递归地对其两侧的两个子数组进行排序。为此:
声明partition
返回void
而不是int
,然后删除行return pivotIndex;
。您对返回值不做任何事情,所以我们最好也不要使用它。
在partition
方法的末尾添加以下几行,以对子数组进行递归排序:
partition(arr, first, pivotIndex - 1);
partition(arr, pivotIndex + 1, last);
将以下行添加到partition
的开头:
if (first >= last) { return; }
如果first == last
,则表示您正在对一个1元素数组或子数组进行排序,并且可以通过不执行任何操作对其进行排序。同样,如果为first > last
,则要排序的子数组为空,也可以不进行任何排序。
答案 1 :(得分:-1)
尝试这样做:
public static int [] quickSort (int [] array, int first, int last){
int pivot = array[last/2];
while (!isSorted(array)) {
int left = first;
int right = last;
while (true) {
while (array[left] < pivot && left < last) {
left++;
}
while (array[right] >= pivot && right > first) {
right--;
}
if (array[left] > array[right]) {
swap(array, left, right);
System.out.println(Arrays.toString(array));
}
if (left >= right)
break;
if (right - left == 1)
break;
}
}
return array;
}
此方法检查数组是否已排序:
private static boolean isSorted(int [] array){
for (int i = 0; i < array.length; i++){
if (array[i] > array[i+1])
return false;
}
return true;
}