简体   繁体   English

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

[英]Why isn't the bubbleDown method working as intended (Heap Sort)?

This was an assignment that was due, and I attempted it in both C++ and Java, but in both versions, the bubbleDown method wasn't working as intended, though I believe the logic says it should. 这是一个到期的赋值,我在C ++和Java中尝试过它,但在两个版本中,bubbleDown方法都没有按预期工作,但我相信逻辑说它应该。 I've already handed in both versions, but since the Java version is the most recent, I'll post it here. 我已经提交了两个版本,但由于Java版本是最新版本,我将在此处发布。

Here's the Java version: 这是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);
    }
}

The input file (args[0]) with have only integers in the file, with some on the same row, and on different lines. 输入文件(args [0])在文件中只有整数,有些在同一行,在不同的行上。 args[1] is the output file name. args [1]是输出文件名。

When the program goes through bubbleDown, it starts to work as intended in the beginning, but then it skips some numbers, and towards the end I'll eventually see a number that should have been at the top. 当程序通过bubbleDown时,它开始按预期工作,但随后它会跳过一些数字,到最后我最终会看到一个应该位于顶部的数字。 Can someone explain to me what I did wrong in this function? 有人可以向我解释我在这个功能中做错了什么吗?

Your code looks suspicious for a number of reasons. 由于多种原因,您的代码看起来很可疑。 1 -- you are mixing the actual data structure implementation with reading a file which makes no sense. 1 - 您正在混合实际的数据结构实现和读取一个没有意义的文件。 Very hard to follow. 很难遵循。 Then this piece can't be right: 然后这件作品不对:

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

First line suggests that heap array contains actual data elements. 第一行表明堆数组包含实际的数据元素。 But second line is treating heap contents as indexes of some sort? 但第二行是将堆内容视为某种索引? heap[0]-- will decrement the value stored at location 0 of the heap array, but first it will use it to move the contents of heap[heap[0]] to heap[1]? heap [0] - 将减少存储在堆数组的位置0的值,但首先它将使用它将堆[heap [0]]的内容移动到堆[1]? What? 什么? Are you using heap[0] as a special thing to store the index of the last element in the array? 你是否使用heap [0]作为特殊的东西来存储数组中最后一个元素的索引? I suggest you start by rewriting code w/o hacks like this, it should make it easier to understand and fix. 我建议你从没有像这样的黑客重写代码开始,它应该使它更容易理解和修复。 In reality your heap should start at element 0 and your left node will be at 2k+1 and right will be at 2k+2. 实际上,您的堆应该从元素0开始,左侧节点将是2k + 1,右侧将是2k + 2。

Now this smells like it is wrong: 现在这闻起来像是错的:

right <= heap.length

you should be comparing right to that terrible heap[0], because heap.length will not be shrinking when you remove things from it. 你应该正确地比较那个可怕的堆[0],因为当你从中移除东西时,heap.length不会缩小。

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

should be 应该

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

and the final main mistake is in the bubbleDown method. 而最后的主要错误是在bubbleDown方法中。 When bubbling down you need to be swapping the downward shifting node with the smaller of its children. 冒泡时,你需要用较小的孩子交换向下移动的节点。 So that is 7 is bubbling down and its left child is 6 and right child is 4, you need to swap 7 and 4, otherwise you get invalid tree of 那就是7是冒泡而它的左子是6而右子是4,你需要交换7和4,否则你得到无效的树

   6
 /   \
7     4

So code should be 所以代码应该是

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

You are welcome. 别客气。 And your professor owes me lunch for doing his job for him. 而你的教授欠我吃午饭为他做的工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM