为什么bubbleDown方法没有按预期工作(堆排序)?

时间:2015-09-24 02:58:04

标签: java heapsort

这是一个到期的赋值,我在C ++和Java中尝试过它,但在两个版本中,bubbleDown方法都没有按预期工作,尽管我相信逻辑说它应该。我已经提交了两个版本,但由于Java版本是最新版本,我将在此处发布。

这是Java版本:

import java.io.*;
import java.util.Scanner;

public class HeapSort {
    static int[] heap;
    Integer[] sorted;
    String in, out;
    int fullLength = 0;

    public HeapSort(String inf, String outf) throws FileNotFoundException {
        in = inf;
        out = outf;

        Scanner scan = new Scanner(new File(in));
        while (scan.hasNextInt()) {
            fullLength++;
            scan.nextInt();
        }

        sorted = new Integer[fullLength];
        heap = new int[fullLength+1];
        heap[0] = 0;

        scan.close();
    }

    public boolean isFull() {
        return heap[0] == fullLength;
    }

    public boolean isEmpty() {
        return heap[0] == 0;
    }

    public void buildHeap() throws IOException {
        Scanner scan = new Scanner(new File(in));
        while (scan.hasNextInt())
            insertOneDataItem(scan.nextInt());

        scan.close();
    }

    public void deleteHeap() throws IOException {
        while (!isEmpty()) {
            deleteRoot();
            printHeap();
        }
    }

    public void deleteRoot() throws IOException {
        if (isEmpty())
            return;

        FileWriter f = new FileWriter(out, true);
        f.write("Deleting " + heap[1] + "\n");
        f.close();
        int i;
        for(i = 0; sorted[i] != null; i++);
        sorted[i] = heap[1];
        heap[1] = heap[heap[0]--];
        bubbleDown();
    }


    public void insertOneDataItem(int num) throws IOException {
        if (isFull()) {
            p("Heap is full");
            return;
        }

        heap[++heap[0]] = num;
        bubbleUp();
        printHeap();
    }

    public void printHeap() throws IOException {
        FileWriter f = new FileWriter(out, true);
        f.write("Current Heap:\t");
        for (int i = 1; i <= heap[0]; i++) {
            if (i > 10) break;
            f.write(heap[i] + " ");
        }
        f.write("\n");
        f.close();
    }

    public void printSorted() throws IOException {
        FileWriter f = new FileWriter(out, true);
        f.write("Current Sorted:\t");
        for (int i = 1; i <= sorted.length; i++) {
            if (i > 10) break;
            f.write(sorted[i] + " ");
        }
        f.write("\n");
        f.close();
    }

    public void bubbleUp() {
        int h = heap[0];
        while (h >= 2 && heap[h] < heap[h/2]) {
            int x = heap[h];
            heap[h] = heap[h/2];
            heap[h/2] = x;
            h = h/2;
        }
    }

    public void bubbleDown() {
        int k = 1;
        // make sure we have at least a left child
        // before continuing on
        while (2*k <= heap.length) {
            int left = 2*k;
            int right = 2*k+1;
            if (heap[k] >= heap[left]) {
                int x = heap[k];
                heap[k] = heap[left];
                heap[left] = x;
                k = left;
                continue;
            }
            if (right <= heap.length &&
                heap[k] >= heap[right]) {
                int x = heap[k];
                heap[k] = heap[right];
                heap[right] = x;
                k = right;
            } else {
                return;
            }
        }
    }

    public void begin() throws IOException {
        buildHeap();
        deleteHeap();
        printSorted();
    }

    public static void main(String[] args) throws IOException {
        if (args.length < 2) {
            p("Please start with: program file1.txt file2.txt");
            System.exit(1);
        }

        // empty the output file
        (new FileOutputStream(args[1])).close();

        (new HeapSort(args[0], args[1])).begin();

    }

    public static void p(String s) {
        System.out.println(s);
    }
}

输入文件(args [0])在文件中只有整数,有些在同一行,在不同的行上。 args [1]是输出文件名。

当程序通过bubbleDown时,它开始按预期工作,但随后它会跳过一些数字,最后我会看到一个应该位于顶部的数字。有人可以向我解释我在这个功能中做错了吗?

1 个答案:

答案 0 :(得分:2)

由于多种原因,您的代码看起来很可疑。 1 - 您正在混合实际的数据结构实现和读取一个没有意义的文件。很难遵循。那么这件作品就不对了:

sorted[i] = heap[1];
heap[1] = heap[heap[0]--];

第一行表明堆数组包含实际的数据元素。 但第二行是将堆内容视为某种索引? heap [0] - 将减少存储在堆数组的位置0的值,但首先它将使用它将堆[heap [0]]的内容移动到堆[1]?什么?你是否使用heap [0]作为特殊的东西来存储数组中最后一个元素的索引?我建议你从没有像这样的黑客重写代码开始,它应该使它更容易理解和修复。实际上,你的堆应该从元素0开始,你的左边节点将是2k + 1,右边将是2k + 2。

现在这闻起来有点不对劲:

right <= heap.length

你应该正确地比较那个可怕的堆[0],因为当你从中移除东西时,heap.length不会缩小。

for (int i = 1; i <= sorted.length; i++) {

应该是

for (int i = 0; i < sorted.length; i++) {

并且最终的错误在bubbleDown方法中。冒泡时,您需要使用其子项的较小交换向下移动的节点。因此,7是冒泡而其左边的孩子是6而右边的孩子是4,你需要交换7和4,否则你会得到无效的树

   6
 /   \
7     4

所以代码应该是

if (heap[k] >= heap[left] && heap[left] < heap[right]) {

欢迎你。而且你的教授欠我吃午饭为他做的工作。