d-ary heap和percolateUp()问题

时间:2016-02-14 15:36:12

标签: java heap

我是学生学习java堆,我们有一个任务我们必须参加老师制作的课程并进行更改以使其作为d-heap工作,然后用另一个教师课程进行测试。我已经完成了大部分工作,但我们应该运行的JUnit测试之一总是在某个地方失败:testValues(5,23,17,12); (预计23岁,但是12岁)。 我确信这个问题出现在Insert()或percolateUp()中,但我没有想法。

package alda.heap;
import java.util.Arrays;            
import java.util.Comparator;            

public class DHeap<AnyType extends Comparable<? super AnyType>>
{
private int d;  //added
private static final int DEFAULT_CAPACITY = 10;
private int currentSize = 0;      // Number of elements in heap
private AnyType [ ] array; // The heap array
protected Comparator comparator;

public DHeap( )
{

    this( DEFAULT_CAPACITY, DEFAULT_CAPACITY ); //added Default_capacity
}


public DHeap( int capacity, int d ) 
{

    this.d=d;       //added
    array = (AnyType[]) new Comparable[ capacity + 1 ];
}



public DHeap(int d) {       //added
    if (d < 2) {
        throw new IllegalArgumentException("d bigger than 1 plz");
    }
        this.d=d;
        array = (AnyType[]) new Comparable[ DEFAULT_CAPACITY + 1 ];
}


public int size(){ 
    return currentSize; 
    }

public AnyType get(int index){ 
    return array[index]; 
    }

public void insert( AnyType x )  //teacher made, gets error from JUnit.
{
    if(x == null){
        throw new NullPointerException("cannot insert null");
    }
    if(array.length -1 == currentSize){
        enlargeArray();
    }
        // Percolate up
    int hole = ++currentSize;
    for( array[ 0 ] = x; x.compareTo( array[ hole / 2 ] ) < 0; hole /= 2 )
        array[ hole ] = array[ hole / 2 ];
    array[ hole ] = x;
    //percolateUp(currentSize - 1); //my method, which doesnt work
}

private void percolateUp(int childIndex){ //made by me

    AnyType tmp = array[childIndex];

    while(childIndex > 0)
    {
        if(tmp.compareTo(array[getParentIndex(childIndex)]) < 0){
        array[childIndex] = array[getParentIndex(childIndex)];
        childIndex = getParentIndex(childIndex);
    }
    array[childIndex] = tmp;
}
}


public boolean isFull(){        //added method
    return currentSize == array.length -1;
}

private void enlargeArray(){    //made from scratch
    System.out.println("1");
    array = Arrays.copyOf(array, array.length * 2);
    System.out.println("2");
}

@SuppressWarnings("unchecked")
private void enlargeArray1( ){   
    AnyType [] old = array;
        array = (AnyType []) new Comparable[old.length * 2];
        for( int i = 0; i < old.length; i++ )
            array[ i ] = old[ i ];        
}


public AnyType findMin( )
{
    if( isEmpty( ) )
        throw new UnderflowException();
    return array[ 1 ];
}

public AnyType deleteMin( )
{
    if( isEmpty( ) )
        throw new UnderflowException( );

    AnyType minItem = findMin( );
    array[ 1 ] = array[ currentSize-- ];
    percolateDown( 1 );

    return minItem;
}

public boolean isEmpty( )
{
    return currentSize == 0;
}

private int getParentIndex(int index) {
    return (index - 1) / d;
    }

public int getChildIndex(int index, int k){
    return d * index + k;
}

public void makeEmpty( )
{
    currentSize = 0;
}

private void percolateDown( int hole )
{
    int child;
    AnyType tmp = array[ hole ];

    for( ; hole * 2 <= currentSize; hole = child )
    {
        child = hole * 2;
        if( child != currentSize &&
                array[ child + 1 ].compareTo( array[ child ] ) < 0 )
            child++;
        if( array[ child ].compareTo( tmp ) < 0 )
            array[ hole ] = array[ child ];
        else
            break;
    }
    array[ hole ] = tmp;
}



    // Test program
public static void main( String [ ] args )
{
    int numItems = 10000;
    DHeap<Integer> h = new DHeap<>( );
    int i = 37;

    for( i = 37; i != 0; i = ( i + 37 ) % numItems )
        h.insert( i );
    for( i = 1; i < numItems; i++ )
        if( h.deleteMin( ) != i )
            System.out.println( "Oops! " + i );
}

我的测试课程:

package org.junit;
import static org.junit.Assert.*;
import java.util.PriorityQueue;
import java.util.Random;
import org.junit.Before;
import alda.heap.DHeap;
public class DHeapTester {

private DHeap<Integer> heap = new DHeap<Integer>(4);

@Test
public void testFunctionality() {
    Random rnd = new Random();
    PriorityQueue<Integer> oracle = new PriorityQueue<Integer>();

    assertEquals(oracle.isEmpty(), heap.isEmpty());

    for (int n = 0; n < 1000; n++) {
        int tal = rnd.nextInt(1000);
        heap.insert(tal);
        oracle.add(tal);
        while (!heap.isEmpty() && rnd.nextBoolean()) {
            assertEquals(oracle.poll(), heap.deleteMin());
        }
        assertEquals(oracle.isEmpty(), heap.isEmpty());
    }
}

@Test
public void testConstructors() {
    heap = new DHeap<Integer>(); 
    heap = new DHeap<Integer>(2); 
    heap = new DHeap<Integer>(3);                                   
}

@Test(expected = IllegalArgumentException.class)
public void testTooSmallD() {
    new DHeap<Integer>(1);
}

private void testValues(Integer... expected) {
    assertEquals(expected.length, heap.size());
    for (int n = 0; n < expected.length; n++)
        assertEquals(expected[n], heap.get(n + 1));
}

@Test
public void testContent() {
    testValues();
    heap.insert(17);
    testValues(17);
    heap.insert(23);
    testValues(17, 23);
    heap.insert(5);
    testValues(5, 23, 17);
    heap.insert(12);
    testValues(5, 23, 17, 12);  //this is where JUnit gets error (expected 23 but was 12)
    heap.insert(100);
    heap.insert(51);
    heap.insert(52);
    testValues(5, 23, 17, 12, 100, 51, 52);
    heap.insert(4);
    testValues(4, 5, 17, 12, 100, 51, 52, 23);
    heap.insert(70);
    testValues(4, 5, 17, 12, 100, 51, 52, 23, 70);
    heap.insert(10);
    testValues(4, 5, 10, 12, 100, 51, 52, 23, 70, 17);
    heap.insert(1);
    testValues(1, 5, 4, 12, 100, 51, 52, 23, 70, 17, 10);

    assertEquals(1, (int) heap.deleteMin());
    testValues(4, 5, 10, 12, 100, 51, 52, 23, 70, 17);
    assertEquals(4, (int) heap.deleteMin());
    testValues(5, 17, 10, 12, 100, 51, 52, 23, 70);
    assertEquals(5, (int) heap.deleteMin());
    testValues(10, 17, 70, 12, 100, 51, 52, 23);
}

1 个答案:

答案 0 :(得分:0)

在insert,percolateUp和percolateDown方法中,您需要使用getParent()getChild()方法。目前,insert方法将索引除以2以获取元素的父级,如果您有2个堆,则仅为true。

此外,您的堆实现使用array[0]作为占位符。在这种情况下,您当前实现中的getParent()getChild()不起作用。这些函数的当前实现仅在您从0开始编制索引时才起作用。这个实现。

例如,如果您有一个大小为3的2堆,则在您的实现中,索引是(1,2,3)。 2的父级不是(2-1)/2。同样,如果将k用作正指数,则1的子项不是2*1 + k

当您从1开始索引时,对于d-heap:
parent of n: (n + (d-2))/d
children of n: ((n*d - (d-2)), ..., (n*d + 1))其中每个元素都是整数。