小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

映射2分堆轉(zhuǎn)自 http://www.zhongsisi.com/stack

 dongsibei 2014-04-24

 引入

這2天都好囧,很久沒有寫了。今天說說堆與映射。

  平常,我們用堆,最常見的就是隨機(jī)地加入元素,隨機(jī)地取最大值或最小值。這些基本的操作C++中的priority_queue和set都能很好的完成,而且C++中還有一個(gè)make_heap,效率較前面2個(gè)會(huì)更高。而且前面提到的STL都是采用紅黑樹實(shí)現(xiàn)的,很具有穩(wěn)定性。

  上面的堆雖然使用簡單,但功能上還是有些局限。比如前面提到的堆都只能實(shí)現(xiàn)刪除最值并沒有辦法刪除指定的值。而且一般STL中的堆都是采用數(shù)據(jù)存儲(chǔ)的,但父親節(jié)點(diǎn)和兒子節(jié)點(diǎn)需要交換時(shí),我們需要拷貝所存儲(chǔ)的整個(gè)數(shù)據(jù)單元,但數(shù)據(jù)單元較大時(shí),拷貝的效率就低了。因此,這里介紹一中堆變種,在堆中引入了映射。

定義

具有映射功能的堆稱為雙向映射堆。又其常常是在二分堆的基礎(chǔ)上實(shí)現(xiàn)的,所以也常常叫映射二分堆。

特點(diǎn)

  映射二分堆其與普通堆不同的地方是它的節(jié)點(diǎn)并不真正保存數(shù)據(jù)單元本身,而是保存指向數(shù)據(jù)單元的指針。因此當(dāng)需要交換父子節(jié)點(diǎn)的數(shù)據(jù)時(shí),我們可以避免拷貝大量數(shù)據(jù)所消耗的時(shí)間。同時(shí),映射二分堆還有一個(gè)功能可以根據(jù)具體的數(shù)據(jù)單元的索引來刪除該單元,即使這個(gè)單元不是堆中的最值。

實(shí)現(xiàn)方法


  在實(shí)現(xiàn)是,我們可以用數(shù)字H[]存儲(chǔ)數(shù)據(jù)單元,然后采用數(shù)組ind[i]=j表示H[i]存放的是索引號(hào)為j的數(shù)據(jù),mp[i]=j表示索引索引為i的元素存儲(chǔ)在H[j]中,這樣就可以實(shí)現(xiàn)雙向映射了。
  插入堆,我們只需要將插入的元素放在堆尾,然后逐級(jí)調(diào)整,這個(gè)跟普通的二叉堆一樣樣。
  刪除最值,也跟普通的二叉堆一樣,先把堆中最后一個(gè)元素與最值對調(diào),然后在調(diào)整堆。
  增加一個(gè)的是刪除固定索引的數(shù)據(jù)單元,我們可以先通過mp[i],找到其在H[]中存放的位置,然后該位置的值跟堆最后一個(gè)元素對調(diào),接著從該節(jié)點(diǎn)向上調(diào)整堆,此時(shí)得到的還不是一個(gè)正規(guī)的堆,還需要重新堆整個(gè)堆進(jìn)行從上到下調(diào)整。
  上面的3中操作中都提到了堆的調(diào)整,還是上面說的,調(diào)整時(shí)我們不需要拷貝數(shù)據(jù)單元,我們只需交換ind[]和mp[]2個(gè)數(shù)組的對應(yīng)值即可。

應(yīng)用

  acm題目中,典型可以使用映射堆解決的題目是FOJ 1209 最小權(quán)無前綴語言問題,這道題在LRJ的書講得很詳細(xì),但他把這題目命名為最輕巧的語言,在P91。具體的方法我就不多說了,因?yàn)長RJ那里已經(jīng)很具體了。
  最后貼一個(gè)一個(gè)未成型的映射堆的代碼,之所以說為成型,是因?yàn)檫@個(gè)堆寫得不是很清晰,未把映射堆用類封裝起來,代碼讀起來比較辛苦。代碼來源dou。代碼對應(yīng)題目是poj 2442 Sequence

#include<stdio.h>
#include<string>
#include<algorithm>
usingnamespace std;
#define N 2010
#define inf 0x7fffffff
intdata1[N], data2[N], data3[N];
intpoint[N];
intheap[N];
structnode {
    intnum;
    inttoheap;
} que[N];
intn;
voidmovedown() {
    inti = 1;
    intl, r;
    while(1) {
        l = 2 * i;
        r = l + 1;
        if(l > n)
            break;
        if(que[heap[i]].num > que[heap[l]].num && ((r <= n && que[heap[l]].num <= que[heap[r]].num) || r > n)) {
            swap(que[i].toheap, que[l].toheap);
            swap(heap[i], heap[l]);
            i = l;
        }else
            if(que[heap[i]].num > que[heap[r]].num && r <= n && que[heap[r]].num <= que[heap[l]].num) {
            swap(que[i].toheap, que[r].toheap);
            swap(heap[i], heap[r]);
            i = r;
        }elsebreak;
    }
}
intmain() {
    intcas;
    inttemp;
    scanf("%d", &cas);
    while(cas--) {
        inti, j;
        intm;
        scanf("%d%d", &m, &n);
        for(i = 1; i <= n; ++i)
            scanf("%d", data1 + i);
        sort(data1 + 1, data1 + n + 1);
        for(j = 0; j < m - 1; ++j) {
            for(i = 1; i <= n; ++i)
                scanf("%d", data2 + i);
            sort(data2 + 1, data2 + n + 1);
            data2[n + 1] = inf;
            for(i = 1; i <= n; ++i) {
                que[i].num = data1[i] + data2[1];
                que[i].toheap = i;
                heap[i] = i;
                point[i] = 1;
            }
            for(i = 1; i <= n; ++i) {
                data3[i] = que[heap[1]].num;
                point[heap[1]]++;
                temp = data1[heap[1]] + data2[point[heap[1]]];
                que[heap[1]].num = temp;
                movedown();
            }
            memcpy(data1, data3, 4 * (n + 1));
        }
        printf("%d", data1[1]);
        for(i = 2; i <= n; ++i)
            printf(" %d", data1[i]);
        printf("n");
    }
    return0;
}

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請遵守用戶 評(píng)論公約

    類似文章 更多