我正在C ++中实现一个最大的二进制堆,它似乎工作正常。

但是,当我重复轮询操作(代码中的delMax方法)直到堆(如果为空)花费的时间太长时,它比构建堆本身要长,在10 ^ 7个元素的情况下,大约是6秒它几乎不需要时间。

此外,在打印堆摘要和打印删除时间之间,我得到了“无子女元素!”打印两次(来自leftChild和rightChild方法),但我不知道那是哪里来的,因为这些方法还没有在那里被调用。

我的代码:

  #include "pch.h"
  #include <iostream>
  #include "time.h"
  #include <random>
  #include <string>
  #include <functional>
  #include <vector>
 using namespace std;
 template <typename T>
 class BinaryHeap;

template <typename T>
class BinaryHeap
{
vector <T> heap;
int getParent(int childInd)
{
    if (heap.size() == 0)
    {
        return -1;
    }
    //int parent = 0;
    int parent = floor((childInd - 1) / 2);
    if (heap.size() <= childInd)
    {
        cout << "No such element!" << endl;
        return -1;
    }
    else
        return parent;
}
int leftChild(int parentInd)
{
    int left = floor(2 * parentInd + 1);
    if (heap.size() <= parentInd)
    {
        cout << "Childless element!" << endl;
        return -1;
    }
    else
        return left;
}
int rightChild(int parentInd)
{
    int right = (2 * parentInd + 2);
    if (heap.size() <= parentInd)
    {
        cout << "Childless element!" << endl;
        return -1;
    }
    else
        return right;
}
void heapifydown(int index)
{
    int left = leftChild(index);
    int right = rightChild(index);
    int largest = index;
    if (heap.size() > left&&heap[left] > heap[index])
    {
        largest = left;
    }
    if (heap.size() > right&& heap[right] > heap[largest])
    {
        largest = right;
    }
    if (largest != index)
    {
        int temp = heap[index];
        heap[index] = heap[largest];
        heap[largest] = temp;
        heapifydown(largest);
    }
}
void heapifyup(int index)
{
    int p = getParent(index);
    if (heap.size() > index&& heap[p] < heap[index])
    {
        int temp = heap[index];
        heap[index] = heap[p];
        heap[p] = temp;
        heapifyup(p);
    }
}

public:
BinaryHeap() {};
~BinaryHeap()
{
    heap.clear();
}
void addElement(T el)
{
    heap.push_back(el);
    int index = heap.size() - 1;
    heapifyup(index);
}
void printHeap()
{
    if (heap.size() == 0)
    {
        cout << "Empty heap!" << endl;
        return;
    }
    for (int i = 0; i < heap.size(); i++)
    {

        cout << heap[i] << endl;
    }
}
T delMax()
{
    if (heap.size() == 0)
    {
        return -1;
    }
    T temp = heap[0];
    T temp2 = heap[0];
    heap[0] = heap.at(heap.size()-1);
    heap.pop_back();
    //T parent = 0;
    //T child = 2 * parent + 2;
    heapifydown(0);
    return temp;
    //delete &temp;
}
void clearHeap()
{
    for (int i = heap.size(); i > 0; --i)
    {
        heap.pop_back();
    }
}
void print()
{
    if (heap.size() == 0)
    {
        cout << "Empty heap!" << endl;
        return;
    }
    cout << "Size: " << heap.size()<<endl;
    cout << " Root: " << heap[0] << endl;
    cout << "L. child: " << heap[1] << endl;
    cout << "R. Child: " << heap[2] << endl;
    cout << "3 last elements: " << heap[heap.size()-3] <<
    " "<<heap[heap.size() - 2]<<
    " "<<heap[heap.size() - 1]<<endl;
}
};
int randomInt()
{
static default_random_engine generator{ 10 };
static uniform_int_distribution<int> rozklad{ 0, 11000000 };
static function<int()> los{ bind(rozklad, generator) };
int l = los();
return l;
}
int main()
{
BinaryHeap<int>*bh = new BinaryHeap<int>();
const int MAX_ORDER = 7; // maksymalny rzad wielkosci dodawanych danych
for (int i = 1; i <= MAX_ORDER; i++)
{
    const int n = pow(10, i);
    clock_t start1 = clock();
    for (int i = 0; i < n; i++)
    {
        int el = randomInt();
        bh->addElement(el);
    }
    clock_t stop1 = clock();
    double adding_time = (stop1 - start1) / (double)CLOCKS_PER_SEC;
    cout << "Adding time: " << adding_time << "s" << endl;
    bh->print();
    clock_t start2 = clock();
    for (int j = 0; j < n; j++)
    {
        int out = bh->delMax();
        //cout << "WyciagniEty: "<<bh->delMax()<<endl;
        //delete &out;
    }
    clock_t stop2 = clock();
    double polling_time = (stop2 - start2) / (double)CLOCKS_PER_SEC;
    cout << "Removing time: " << polling_time << "s" << endl;
    bh->print();
    bh->clearHeap();
}
delete bh;
return 0;
}

最佳答案

当父索引小于或等于堆大小时,在leftChildrightChild函数中可能会出现“无子元素”消息。通过检查您的代码,我想说这是在您尝试删除堆中的最后一个节点时发生的。考虑您的delMax函数(我已经删除了无效的和注释掉的代码):

T delMax()
{
    if (heap.size() == 0)
    {
        return -1;
    }
    T temp = heap[0];
    heap[0] = heap.at(heap.size()-1);
    heap.pop_back();
    heapifydown(0);
    return temp;
}


当堆大小为1时,对heap.pop_back()的调用将删除最后一个元素,并且大小现在为0。然后,您调用heapifydown(0)

heapifydown调用leftChildrightChild,它们都包含以下代码:

if (heap.size() <= parentInd)
{
    cout << "Childless element!" << endl;
    return -1;
}
else


heap.size()返回0,因为堆为空。并且parentInd为0,因为这是您传递的参数的值。因此,打印了“无孩子元素”。

我对代码甚至可以正常工作感到很惊讶,因为leftChildrightChild都返回-1,而heapifyDown不检查返回值。结果,用于计算最大子级的代码将报告该heap.size() > left,并且会将heap[-1]heap[0]进行比较,并有可能破坏程序的内存堆。这取决于阵列开始之前内存中的内容。

我的建议是将您的leftChild函数修改为:

return (parentInd * 2) + 1;


并对rightChild进行类似的修改。

在您的heapifyDown函数中,如果左孩子超出了堆的范围,则返回:

void heapifydown(int index) {
    int left;
    int right;
    int largest = index;

    left = leftChild(index);
    if (heap.size() <= left) {
        // left child index is outside range of the heap.
        // node has no children, so return.
        return;
    }

    if (heap[left] > heap[index]) {
        largest = left;
    }

    right = rightChild(index);
    if (heap.size() > right && heap[right] > heap[largest])
    {
        largest = right;
    }
    if (largest != index)
    {
        int temp = heap[index];
        heap[index] = heap[largest];
        heap[largest] = temp;
        heapifydown(largest);
    }
}

关于c++ - 我的最大二进制堆中的C++轮询操作非常缓慢,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59075372/

10-11 22:57