这是一个到期的赋值,我在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时,它开始按预期工作,但随后它会跳过一些数字,最后我会看到一个应该位于顶部的数字。有人可以向我解释我在这个功能中做错了吗?
答案 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]) {
欢迎你。而且你的教授欠我吃午饭为他做的工作。