實現堆結構

題目如下:

描述

定義一個數組,初始化爲空。在數組上執行兩種操作:

1、增添1個元素,把1個新的元素放入數組。

2、輸出並刪除數組中最小的數。

使用堆結構實現上述功能的高效算法。

輸入第一行輸入一個整數t,代表測試數據的組數。
對於每組測試數據,第一行輸入一個整數n,代表操作的次數。
每次操作首先輸入一個整數type。
當type=1,增添操作,接着輸入一個整數u,代表要插入的元素。
當type=2,輸出刪除操作,輸出並刪除數組中最小的元素。
1<=n<=100000。輸出每次刪除操作輸出被刪除的數字。樣例輸入
2
5
1 1
1 2
1 3
2
2
4
1 5
1 1
1 7
2
樣例輸出
1
2
1
提示每組測試數據的複雜度爲O(nlgn)的算法才能通過本次,否則會返回TLE(超時)

需要使用最小堆結構來實現本題的算法



以前寫樹的代碼時一直用的鏈表形式,現在試了一下數組的寫法,感覺比較也比較好理解,寫法也比較簡單。代碼及註釋如下:

#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;

int a[100010];
int n;

//下標下移,在刪除後更新樹時需要用到
void down( int root )
{
    int son =  2*root;  //記錄根節點的左兒子
    int t = a[root];   
    while( son <= n)
    {
        if( son <= n -1  && a[son] > a[son+1]) //防止數組越界,且記錄較小值兒子節點的下標
            son++;
        if( t > a[son])   //更新節點。
        {
            a[root] = a[son];
            root = son;
            son = 2*root;
        }
        else break;
    }
    a[root] = t;
}

//數組下標上移,插入節點時用到。
void up( int son )
{
    int t = a[son];
    int tson = son;
    while( (tson > 1)&&( a[tson/2] > t))  //更新節點。
    {
        a[tson] = a[tson/2];
        tson = tson/2;
    }
    a[tson] = t;
}

void charu( int  t)
{
    a[ ++n ] = t;
    up( n );
}

void del( )
{

    if(n==0)
        return ;
    cout << a[1] << endl; //根節點肯定是最小值。
    a[1] = a[n--];
    down( 1 );

}

int main()
{
    int t;
    scanf("%d",&t);
    while( t-- )
    {
        n = 0;
        int type;
        int m;
        scanf("%d",&m);
        for(int i = 0; i< m; i++)
        {
            scanf("%d",&type);
            if(type == 1)
            {
                int b;
                scanf("%d",&b);
                charu( b ) ;
            }
            else
            {
                del();
            }
        }
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章