问题
创建一个程序以在链表上执行合并排序。
规范
使用合并排序例程对链接列表进行排序:
到目前为止我的代码:
public class MergeSort{
LinkedQueue<Integer> list = new LinkedQueue<Integer>();
Integer[] a = new Integer[100];
public MergeSort() {
for(int i=0; i<100; i++)
{
list.enqueue(StdRandom.uniform(999)+1);
}
}
private static boolean less(Comparable v, Comparable w)
{
return (v.compareTo(w) < 0);
}
private static void merge(Comparable[] a, Comparable[] aux, int lo, int mid, int hi)
{
for(int k = lo; k <= hi; k++)
aux[k] = a[k];
int i = lo, j= mid+1;
for(int k = lo; k <= hi; k++)
{
if (i>mid)
a[k] = aux[j++];
else if (j>hi)
a[k] = aux[i++];
else if (less(aux[j], aux[i]))
a[k] = aux[j++];
else
a[k] = aux[i++];
}
}
private static void sort(Comparable[] a, Comparable[] aux, int lo, int hi)
{
if((hi-lo) <= 6)
{
Comparable[] b = new Comparable[hi-lo];
for(int i=0; i<b.length; i++)
{
b[i] = a[lo+i];
}
Selection.sort(b);
for(int i=0; i<(hi-lo); i++)
{
a[lo+i] = b[i];
}
return;
}
int mid = lo + (hi - lo)/2;
sort(a, aux, lo, mid);
sort(a, aux, mid+1, hi);
merge(a, aux, lo, mid, hi);
}
public void sort(Comparable[] a)
{
Comparable[] aux = new Comparable[a.length];
sort(a, aux, 0, a.length-1);
}
public static void main(String[] args)
{
MergeSort merge = new MergeSort();
StdOut.println("Unsorted: ");
for(int i=0; i<10; i++)
{
for(int j=0; j<10; j++)
{
StdOut.print(merge.list.peek() + " ");
merge.a[i*10 + j] = merge.list.dequeue();
}
StdOut.println();
}
StdOut.println();
merge.sort(merge.a);
for(int i=0; i<100; i++)
{
merge.list.enqueue(merge.a[i]);
}
StdOut.println("Sorted: ");
for(int i=0; i<10; i++)
{
for(int j=0; j<10; j++)
{
StdOut.print(merge.list.dequeue() + " ");
}
StdOut.println();
}
}
}
我的问题是该数组似乎只是部分排序。上半部分排序很好,但在下半部分左右,它开始只有其他所有项目排序,而其他项目似乎是随机的。以下是输出的示例:
Unsorted:
580 314 331 643 597 587 798 980 87 53
526 787 993 336 552 338 950 460 441 566
428 115 670 28 384 596 781 489 630 91
272 563 428 644 696 120 538 729 477 637
196 564 784 770 702 56 992 413 753 266
847 751 659 426 59 738 185 589 650 636
849 437 361 519 980 723 973 217 414 548
337 935 656 944 485 233 431 170 327 832
53 236 447 184 842 286 303 153 697 713
303 64 268 725 229 127 517 15 427 372
Sorted:
15 28 53 53 56 59 64 87 91 115
120 127 170 184 196 217 229 233 268 272
286 303 303 314 327 331 336 337 338 413
426 427 428 428 431 437 447 460 477 489
517 372 519 526 538 548 552 564 566 580
587 589 596 597 630 636 637 643 644 650
656 659 670 384 696 697 702 713 723 725
729 738 751 753 781 563 784 770 787 798
832 236 842 153 847 185 849 361 935 944
485 950 441 973 980 980 414 992 266 993
我相信我已将问题缩小到递归排序方法的基本情况:
if((hi-lo) <= 6)
{
Comparable[] b = new Comparable[hi-lo];
for(int i=0; i<b.length; i++)
{
b[i] = a[lo+i];
}
Selection.sort(b);
for(int i=0; i<(hi-lo); i++)
{
a[lo+i] = b[i];
}
return;
}
每当我用if(hi&lt; = lo)返回时替换它;基本情况是基本合并排序的标准,一切正常。那么,任何人都可以帮我解决这个问题,或者在代码中发现错误吗?另外,如果你能就我为什么要在Selection上使用另一种非递归排序方法的问题给我任何建议,那将是非常感激的。
根据Kraskevich的要求,选择类的源代码:
import java.util.Comparator;
/**
* The <tt>Selection</tt> class provides static methods for sorting an
* array using selection sort.
* <p>
* For additional documentation, see <a href="http://algs4.cs.princeton.edu/21elementary">Section 2.1</a> of
* <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public class Selection {
// This class should not be instantiated.
private Selection() { }
/**
* Rearranges the array in ascending order, using the natural order.
* @param a the array to be sorted
*/
public static void sort(Comparable[] a) {
int N = a.length;
for (int i = 0; i < N; i++) {
int min = i;
for (int j = i+1; j < N; j++) {
if (less(a[j], a[min])) min = j;
}
exch(a, i, min);
assert isSorted(a, 0, i);
}
assert isSorted(a);
}
/**
* Rearranges the array in ascending order, using a comparator.
* @param a the array
* @param c the comparator specifying the order
*/
public static void sort(Object[] a, Comparator c) {
int N = a.length;
for (int i = 0; i < N; i++) {
int min = i;
for (int j = i+1; j < N; j++) {
if (less(c, a[j], a[min])) min = j;
}
exch(a, i, min);
assert isSorted(a, c, 0, i);
}
assert isSorted(a, c);
}
/***********************************************************************
* Helper sorting functions
***********************************************************************/
// is v < w ?
private static boolean less(Comparable v, Comparable w) {
return (v.compareTo(w) < 0);
}
// is v < w ?
private static boolean less(Comparator c, Object v, Object w) {
return (c.compare(v, w) < 0);
}
// exchange a[i] and a[j]
private static void exch(Object[] a, int i, int j) {
Object swap = a[i];
a[i] = a[j];
a[j] = swap;
}
/***********************************************************************
* Check if array is sorted - useful for debugging
***********************************************************************/
// is the array a[] sorted?
private static boolean isSorted(Comparable[] a) {
return isSorted(a, 0, a.length - 1);
}
// is the array sorted from a[lo] to a[hi]
private static boolean isSorted(Comparable[] a, int lo, int hi) {
for (int i = lo + 1; i <= hi; i++)
if (less(a[i], a[i-1])) return false;
return true;
}
// is the array a[] sorted?
private static boolean isSorted(Object[] a, Comparator c) {
return isSorted(a, c, 0, a.length - 1);
}
// is the array sorted from a[lo] to a[hi]
private static boolean isSorted(Object[] a, Comparator c, int lo, int hi) {
for (int i = lo + 1; i <= hi; i++)
if (less(c, a[i], a[i-1])) return false;
return true;
}
// print array to standard output
private static void show(Comparable[] a) {
for (int i = 0; i < a.length; i++) {
StdOut.println(a[i]);
}
}
/**
* Reads in a sequence of strings from standard input; selection sorts them;
* and prints them to standard output in ascending order.
*/
public static void main(String[] args) {
String[] a = StdIn.readAllStrings();
Selection.sort(a);
show(a);
}
}
答案 0 :(得分:1)
错误很简单:lo
和hi
索引包含在内。这就是为什么它应该是:
if (hi - lo) <= 6) {
Comparable[] b = new Comparable[hi - lo + 1];
// ^^^^
// We need plus one here.
for (int i = 0; i < b.length; i++) {
b[i] = a[lo + i];
}
Selection.sort(b);
for (int i = 0; i < b.length; i++) {
// ^^^^
// We should either iterate to hi - lo + 1 or b.length.
a[lo + i] = b[i];
}
return;
}