我正在尝试在源cpp文件中实现最小类型的二进制堆,并使用一些不同输入和操作的特定情况对其进行测试。但是,我的断言测试未通过以下操作序列:

    cout << "Testing percolate down  If there are two children nodes that are both smaller than
    the parent... " << endl;
    heap.insert(23);
    heap.insert(43);
    heap.insert(234);
    heap.insert(321);
    heap.insert(243);
    cout<<"nerde"<<endl;
    cout << "Testing percolate down  If there are two children nodes that are both smaller than
     the parent..." << endl;
    assert(heap.getMin() == 23);
    heap.deleteMin();
    assert(heap.getMin() == 43);
    heap.deleteMin();
    assert(heap.getMin() == 234);
    heap.deleteMin();
    cout<<"nerde78"<<endl;
    assert(heap.getMin() == 243);
    heap.deleteMin();
    assert(heap.getMin() == 321);
    heap.deleteMin();


我的输出在上述cout<<"nerde78"<<endl;处给出断言失败

我基于堆数组的实现从索引1开始(不使用零索引)。而且我认为所有DeleteMin,GetMin和Insert函数都是正确的。
堆的构造函数:

  BinaryHeap::BinaryHeap(int capacity) {
    this->capacity = capacity;

    // The element at index 0 is not used!
    // The root element will be placed at index 1
    heap = new int[capacity+1];
    size = 0;

  }


插入:

void BinaryHeap::insert(int element) {

    //Parcolate up
    if(size<capacity)
    {
        int hole=++size;
        for( ;hole>1 && element<heap[hole/2];hole/=2 )
        {
            heap[hole]=heap[hole/2];
        }
        heap[hole]=element;
    }
    // TO BE COMPLETED

    // The capacity of the heap is assumed to be fixed.
    // Insert the element if size < capacity
    // Do nothing otherwise.

    // After the new element is inserted, perform a percolate up operation here.
    // You can add a percolateUp method to the class,
    // or just implement the operations within this insert method.
}


DeleteMin:

void BinaryHeap::deleteMin() {


    if(size>=1)
    {
        heap[1]=heap[size-1];
        size--;
        percolateDown(1);
    }
}


GetMin:

int BinaryHeap::getMin() {
    if(size<1)
    {
        return -1;
    }
    else
        return heap[1];

    // TO BE COMPLETED

    // If the size is less than 1, return -1
    // Otherwise, return the value of the root node


}


percolateDown:

void BinaryHeap::percolateDown(int hole) {

    // TO BE COMPLETED

    // Compare the node with its children; if they are in the correct order, stop
    // Otherwise, swap the element with the smallest child
    // Repeat the operation for the swapped child node
           int min_index = hole;
            int left = hole * 2  ;
            int right = hole * 2 + 1;
            if (left < size && heap[left]<heap[min_index]) {
                min_index = left;
            }
            if (right < size && heap[right]<heap[min_index]) {
                min_index = right;
            }

            if (min_index != hole) {
                swap(hole, min_index);
                percolateDown( hole);
            }
}


交换:

void BinaryHeap::swap(int i, int j) {
    int t = heap[i];
    heap[i] = heap[j];
    heap[j] = t;
}


我当前的错误信息:

Assertion failed: heap.getMin() == 243


我猜想我需要包括另一个if / else案例,以便向下结合左右孩子索引从下面提到的案例中获得渗透,但是我并没有真正弄清楚如何。也许绘制形成的树是一个好主意。

最佳答案

我更改了一些插入方法以提高可读性。首先,如果有足够的空间,我们将新元素插入数组的末尾。然后,我们检查一下heap属性是否有效,换句话说,我们进行到根交换子节点和父交换节点(如果后者更大)。

void insert(int element) {

    if(size < capacity) {
        int hole = ++size;
        heap[hole] = element;

        while(hole > 1 && heap[hole] < heap[hole / 2]){
            swap(hole / 2, hole);
            hole /= 2;
        }

    }
}


然后,在deleteMin和percolateDown这两个函数中,索引编制都存在问题,因为当前您的算法暗含零索引编制。我已将尺寸更改为1。

void deleteMin() {
    if(size >= 1) {
        heap[1] = heap[size];
        size--;
        percolateDown(1);
    }
}


同样,在percolateDown函数中需要较少或相等的运算符来进行索引比较。另外,您要从min_index而不是作为父级的hole继续进行下去。

void percolateDown(int hole) {

    int min_index = hole;
    int left = hole * 2;
    int right = hole * 2 + 1;

    if (left <= size && heap[left] < heap[min_index]) {
        min_index = left;
    }
    if (right <= size && heap[right] < heap[min_index]) {
        min_index = right;
    }

    if (min_index != hole) {
        swap(hole, min_index);
        percolateDown(min_index);
    }
}

10-08 19:58