Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 从堆中删除元素_C++_Algorithm_Data Structures_Heap_Heapsort - Fatal编程技术网

C++ 从堆中删除元素

C++ 从堆中删除元素,c++,algorithm,data-structures,heap,heapsort,C++,Algorithm,Data Structures,Heap,Heapsort,我做了一堆。我很好奇我的remove函数是否有一些微妙的错误: int Heap::remove() { if (n == 0) exit(1); int temp = arr[0]; arr[0] = arr[--n]; heapDown(0); arr[n] = 0; return temp; } void Heap::heapDown(int i) { int l = left(i); int r = r

我做了一堆。我很好奇我的remove函数是否有一些微妙的错误:

int Heap::remove() {
    if (n == 0)
        exit(1);

    int temp = arr[0];
    arr[0] = arr[--n];
    heapDown(0);
    arr[n] = 0;

    return temp;
}

void Heap::heapDown(int i)
{
    int l = left(i);
    int r = right(i);
    // comparing parent to left/right child
    // each has an inner if to handle if the first swap causes a second swap
    //  ie    1   ->   3   ->   5
    //      3   5    1   5    1   3

    if (l < n && arr[i] < arr[l])
    {
        swap(arr[i], arr[l]);
        heapDown(l);

        if (r < n && arr[i] < arr[r])
        {
            swap(arr[i], arr[r]);
            heapDown(r);
        }
    }
    else if (r < n && arr[i] < arr[r]) 
    {
        swap(arr[i], arr[r]);
        heapDown(r);

        if (l < n && arr[i] < arr[l])
        {
            swap(arr[i], arr[l]);
            heapDown(l);
        }
    }
}
以下是我老师的示例输出:

p
Active heap : 7 4 6 1 3 2 5
r   
Removed 7
r
Removed 6
p
Active heap : 5 4 2 1 3
s
Heapsorted : 1 2 3 4 5
虽然我们的输出是完全不同的,但我似乎坚持maxheap的原则,即所有节点都是左向的,所有节点都是parent>child(在我尝试过的每种情况下)。我试着从头开始做这样的Algs,所以也许我只是在做一些奇怪的和错误的事情(如果它是O(LG n)的话,我只会认为它是错误的,因为移除是堆堆的。我的离开有什么特别的“错误”吗?谢谢


首先,我想你的意思是,除了你不需要它之外,因为我们在C++标准库中有一个完整的堆管理函数,包括MaxyHeopp、PuxJoHeP、POPYHEAP甚至SoTythHeP。 也就是说,我想我知道你的问题是什么。堆中的元素有不必要的移动。它处理堆下的交换算法:同样的问题在左侧和右侧都很明显,因此我将展示第一个问题:

if (l < n && arr[i] < arr[l])
{
    swap(arr[i], arr[l]);
    heapDown(l);

    if (r < n && arr[i] < arr[r])
    {
        swap(arr[i], arr[r]);
        heapDown(r);
    }
}
if(l
这里的逻辑不是最小运动的最佳逻辑。被压下的元件的“较小”状态必须属于两个基本类别中的一个,并且对每个类别采取不同的操作:

  • 元素不小于左或右。什么也不做
  • 元素小于左或右,仅与最大的元素交换,然后向下驱动到该子树中
  • 上面列表中的#2是代码中的问题。如果项<左<右,则交换较小的项,然后交换较大的项。我希望这是清楚的。如果你想要一个方案来修正你的逻辑,我可以提供一个方案,但是如果你理解我上面所描述的,我想你可能会处理好它


    扰流板

    void Heap::heapDown(int i)
    {
        int l = left(i);
        int r = right(i);
        int x = 0;
    
        if (l < n && arr[i] < arr[l])
        {
            x = l;
            if (r < n && arr[l] < arr[r])
                x = r;
        }
    
        else if (r < n && arr[i] < arr[r])
            x = r;
    
        if (x != 0)
        {
            swap(arr[i], arr[x]);
            heapDown(x);
        }
    }
    
    void Heap::heapDown(inti)
    {
    int l=左(i);
    int r=右(i);
    int x=0;
    if(l

    注:;如果不明显,这正是尾部递归的定义,因此可以很容易地转换为一个简单的迭代循环。

    Nice catch。我相信堆仍然有效,但它需要更多的工作,因为左分支和右分支都必须重新排序(而大个子上的heapDown就足够了,正如您所描述的)。@zennehoy如果我正确阅读代码,如果出现我提到的条件,它可能会交换左分支和右分支,这将是非常糟糕的。我必须得到一个白板才能肯定地知道这一点或那一点,但似乎可能。如果改成我所描述的那样,我知道它应该以最小的运动量正常工作。是的,是的,我喜欢stl。数据结构类:)+1的问题。您提供了代码、您声明的目标、您看到正在发生的事情、您认为应该发生的事情,以及您与这两者的脱节。示例代码是直截了当的,虽然它不是一个完整的、可编译的代码库,但您认为问题所在的核心是完整的、可理解的。谢谢你的提问。
    void Heap::heapDown(int i)
    {
        int l = left(i);
        int r = right(i);
        int x = 0;
    
        if (l < n && arr[i] < arr[l])
        {
            x = l;
            if (r < n && arr[l] < arr[r])
                x = r;
        }
    
        else if (r < n && arr[i] < arr[r])
            x = r;
    
        if (x != 0)
        {
            swap(arr[i], arr[x]);
            heapDown(x);
        }
    }