Is there a C++ MinMax Heap implementation?

前端 未结 5 1812
暖寄归人
暖寄归人 2020-12-31 06:51

I\'m looking for algorithms like ones in the stl (push_heap, pop_heap, make_heap) except with the ability to pop both the minimum and

5条回答
  •  旧巷少年郎
    2020-12-31 07:08

    Sorry for lengthy code but it works fine except it may complicate to read and may contain some unnecessary variables and I am not uploading the Insert function. Use it as include .h file.

    #include 
    #define bool int
    #define true 1
    #define false 0
    #define Left(i) (2 * (i))
    #define Right(i) (2 * (i) + 1)
    #define Parent(i) ((i) / 2)
    
    void TrickleDown(int* A, int n)
    {
        int i;
        for (i = 1; i <= n / 2; i++)
        {
    
            if (isMinLevel(i, n) == true)
                TrickleDownMin(A, i, n);
            else
                TrickleDownMax(A, i, n);
            Print(A, n);
            printf("i = %d\n", i);
        }
    }
    
    int isMinLevel(int i, int n)//i is on min level or not
    {
        int h = 2;
        if (i == 1)
            return true;
        while (true)
        {
            if (i >= pow(2, h) && i <= pow(2, h + 1) - 1)
                return true;
            else if (i > n || i < pow(2, h))
                return false;
            h += 2;
        }
    }
    
    void swap(int* a, int* b)
    {
        *a ^= *b;
        *b ^= *a;
        *a ^= *b;
    }
    
    void TrickleDownMin(int* A, int i, int n)
    {
        int m, lc, rc, mc, lclc, lcrc, mlc, rclc, rcrc, mrc;
        int child;
        lc = Left(i);
        if (lc > n) // A[i] has no children
            return;
        else
        {
            rc = Right(i);
            mc = rc > n ? lc : (A[lc] > A[rc]) ? rc : lc;
            child = true; // keep tracking m comes from children or grandchildren
            // m = smallest of children and grand children
            lclc = Left(lc);
            if (lclc <= n)
            {
                lcrc = Right(lc);
                mlc = lcrc > n ? lclc :(A[lclc] > A[lcrc]) ? lcrc : lclc;
                mc = mlc > mc ? mc : mlc;
                if (mc == mlc)
                    child = false;
            }
            rclc = Left(rc);
            if (rclc <= n)
            {
                rcrc = Right(rc);
                mrc = rcrc > n ? rclc : (A[rclc] > A[rcrc]) ? rcrc : rclc;
                mc = mrc > mc ? mc : mrc;
                if (mc == mrc)
                    child = false;
            }
            m = mc;
            if (!child)//m is one of the child of i
            {
                if (A[m] < A[i])
                {
                    swap(&A[m], &A[i]);
                    if (A[m] > A[Parent(m)])
                        swap(&A[m], &A[Parent(m)]);
                    TrickleDownMin(A, i, m);
                }
            }
            else    //m is child of i
            {
                if (A[m] < A[i])
                    swap(&A[i], &A[m]);
            }
    
        }
    }
    
    void TrickleDownMax(int* A, int i, int n)
    {
        int m, lc, rc, mc, lclc, lcrc, mlc, rclc, rcrc, mrc;
        int child;
        lc = Left(i);
        if (lc > n)//A[i] has no children
            return;
        else
        {
            rc = Right(i);
            mc = rc > n ? lc : (A[lc] < A[rc]) ? rc : lc;
            child = true; //keep tracking m comes from choldren or grandchildren
            //m = greatest of children and grand children
            lclc = Left(lc);
            if (lclc <= n)
            {
                lcrc = Right(lc);
                mlc = lcrc < n ? lclc : (A[lclc] < A[lcrc]) ? lcrc : lclc;
                mc = mlc < mc ? mc : mlc;
                if (mc == mlc)
                    child = false;
            }
            rclc = Left(rc);
            if (rclc <= n)
            {
                rcrc = Right(rc);
                mrc = rcrc < n ? rclc : (A[rclc] < A[rcrc]) ? rcrc : rclc;
                mc = mrc < mc ? mc : mrc;
                if (mc == mrc)
                    child = false;
            }
            m = mc;
            if (!child)//m is one of the child of i
            {
                if (A[m] > A[i])
                {
                    swap(&A[m], &A[i]);
                    if (A[m] < A[Parent(m)])
                        swap(&A[m], &A[Parent(m)]);
                    TrickleDownMax(A, i, m);
                }
            }
            else      //m is child of i
            {
                if (A[m] > A[i])
                    swap(&A[i], &A[m]);
            }
    
        }
    }
    
    void Print(int* a, int n)
    {
        int i;
        for (i = 1; i < n + 1; i++)
        {
            printf("%d  ", a[i]);
        }
    
    }
    
    int DeleteMin(int* A, int n)
    {
        int min_index = 1;
        int min = A[1];
        swap(&A[min_index], &A[n]);
        n--;
        TrickleDown(A, n);
        return min;
    }
    
    int DeleteMax(int* A, int n)
    {
        int max_index, max;
        max_index = n < 3 ? 2 : (A[2] > A[3]) ? 2 : 3;
        max = A[max_index];
        swap(&A[max_index], &A[n]);
        n--;
        TrickleDown(A, n);
        return max;
    }
    

提交回复
热议问题