Indexerat binÀrt trÀd

Indexerat binÀrt trÀd

Jag stötte pÄ följande typ av problem. Det Àr nödvÀndigt att implementera en datalagringsbehÄllare som tillhandahÄller följande funktionalitet:

  • infoga nytt element
  • ta bort element med serienummer
  • fĂ„ element efter ordningsnummer
  • data lagras i sorterad form

Data lÀggs stÀndigt till och tas bort, strukturen mÄste sÀkerstÀlla snabb drifthastighet. Först försökte jag implementera en sÄdan sak med hjÀlp av standardbehÄllare frÄn std. Den hÀr vÀgen kröntes inte med framgÄng och förstÄelsen kom att jag behövde genomföra nÄgot sjÀlv. Det enda som kom att tÀnka pÄ var att anvÀnda ett binÀrt söktrÀd. Eftersom det uppfyller kravet pÄ snabb infogning, radering och lagring av data i sorterad form. Allt som ÄterstÄr Àr att ta reda pÄ hur man indexerar alla element och rÀknar om indexen nÀr trÀdet Àndras.

struct node_s {    
    data_t data;

    uint64_t weight; // ĐČДс узла

    node_t *left;
    node_t *right;

    node_t *parent;
};

Artikeln kommer att innehÄlla fler bilder och teori Àn kod. Koden kan ses pÄ lÀnken nedan.

Vikt

För att uppnÄ detta genomgick trÀdet en liten modifiering, ytterligare information lades till om vikt nod. Nodens vikt Àr antal Àttlingar till denna nod + 1 (vikten av ett enda element).

Funktion för att fÄ nodvikt:

uint64_t bntree::get_child_weight(node_t *node) {
    if (node) {
        return node->weight;
    }

    return 0;
}

Vikten av arket Àr motsvarande lika med 0.

LĂ„t oss sedan gĂ„ vidare till en visuell representation av ett exempel pĂ„ ett sĂ„dant trĂ€d. svart nodnyckeln kommer att visas i fĂ€rg (vĂ€rdet kommer inte att visas, eftersom detta inte Ă€r nödvĂ€ndigt), röd — knutvikt, grön — nodindex.

NÀr vÄrt trÀd Àr tomt Àr dess vikt 0. LÄt oss lÀgga till ett rotelement till det:

Indexerat binÀrt trÀd

TrÀdets vikt blir 1, rotelementets vikt blir 1. Rotelementets vikt Àr trÀdets vikt.

LÄt oss lÀgga till nÄgra fler element:

Indexerat binÀrt trÀd
Indexerat binÀrt trÀd
Indexerat binÀrt trÀd
Indexerat binÀrt trÀd

Varje gÄng ett nytt element lÀggs till gÄr vi ner i noderna och ökar viktrÀknaren för varje passerad nod. NÀr en ny nod skapas tilldelas den en vikt 1. Om en nod med en sÄdan nyckel redan existerar, kommer vi att skriva över vÀrdet och gÄ tillbaka till roten och avbryta förÀndringarna i vikten för alla noder som vi har passerat.
Om en nod tas bort, gÄr vi ner och minskar vikten av de passerade noderna.

Index

LÄt oss nu gÄ vidare till hur man indexerar noder. Noder lagrar inte explicit sitt index, det berÀknas utifrÄn nodernas vikt. Om de lagrade sitt index skulle det krÀvas O (n) dags att uppdatera indexen för alla noder efter varje Àndring i trÀdet.
LÄt oss gÄ vidare till en visuell representation. VÄrt trÀd Àr tomt, lÄt oss lÀgga till den första noden till det:

Indexerat binÀrt trÀd

Den första noden har ett index 0, och nu Àr 2 fall möjliga. I det första kommer indexet för rotelementet att Àndras, i det andra kommer det inte att Àndras.

Indexerat binÀrt trÀd

Vid roten vÀger det vÀnstra undertrÀdet 1.

Andra fallet:

Indexerat binÀrt trÀd

Rotens index Àndrades inte eftersom vikten av dess vÀnstra undertrÀd förblev 0.

Indexet för en nod berĂ€knas som vikten av dess vĂ€nstra undertrĂ€d + antalet som skickas frĂ„n förĂ€ldern. Vad Ă€r detta nummer?, Detta Ă€r indexrĂ€knaren, initialt Ă€r den lika med 0, dĂ€rför att roten har ingen förĂ€lder. Sen beror allt pĂ„ var vi gĂ„r ner till vĂ€nster barn eller höger. Om till vĂ€nster lĂ€ggs ingenting till rĂ€knaren. Om vi ​​lĂ€gger till indexet för den aktuella noden till den högra.

Indexerat binÀrt trÀd

Till exempel hur indexet för ett element med nyckel 8 (det högra underordnade av roten) berÀknas. Detta Àr "Root Index" + "vikten av vÀnster undertrÀd av nod med nyckel 8" + "1" == 3 + 2 + 1 == 6
Indexet för elementet med nyckel 6 kommer att vara "Root Index" + 1 == 3 + 1 == 4

Följaktligen tar det tid att hÀmta och ta bort ett element per index O (log n), för för att fÄ det önskade elementet mÄste vi först hitta det (gÄ ner frÄn roten till detta element).

djup

Baserat pÄ vikten kan du Àven berÀkna trÀdets djup. NödvÀndigt för att balansera.
För att göra detta mÄste vikten av den aktuella noden avrundas till det första talet till potensen 2 som Àr större Àn eller lika med den givna vikten och ta den binÀra logaritmen frÄn den. Detta kommer att ge oss trÀdets djup, förutsatt att det Àr balanserat. TrÀdet Àr balanserat efter att ett nytt element har satts in. Jag kommer inte att ge en teori om hur man balanserar trÀd. KÀllkoderna ger en balanserande funktion.

Kod för omvandling av vikt till djup.

/*
 * Đ’ĐŸĐ·ĐČращаДт пДрĐČĐŸĐ” Ń‡ĐžŃĐ»ĐŸ ĐČ ŃŃ‚Đ”ĐżĐ”ĐœĐž 2, ĐșĐŸŃ‚ĐŸŃ€ĐŸĐ” Đ±ĐŸĐ»ŃŒŃˆĐ” ОлО Ń€ĐŸĐČĐœĐŸ x
 */
uint64_t bntree::cpl2(uint64_t x) {
    x = x - 1;
    x = x | (x >> 1);
    x = x | (x >> 2);
    x = x | (x >> 4);
    x = x | (x >> 8);
    x = x | (x >> 16);
    x = x | (x >> 32);

    return x + 1;
}

/*
 * ДĐČĐŸĐžŃ‡ĐœŃ‹Đč Đ»ĐŸĐłĐ°Ń€ĐžŃ„ĐŒ ĐŸŃ‚ чОсла
 */
long bntree::ilog2(long d) {
    int result;
    std::frexp(d, &result);
    return result - 1;
}

/*
 * ВДс Đș ĐłĐ»ŃƒĐ±ĐžĐœĐ”
 */
uint64_t bntree::weight_to_depth(node_t *p) {
    if (p == NULL) {
        return 0;
    }

    if (p->weight == 1) {
        return 1;
    } else if (p->weight == 2) {
        return 2;
    }

    return this->ilog2(this->cpl2(p->weight));
}

Resultat av

  • införande av ett nytt element sker i O (log n)
  • radering av ett element med serienummer sker i O (log n)
  • erhĂ„llande av ett element genom serienummer sker i O (log n)

Fart O (log n) Vi betalar för att all data lagras i sorterad form.

Jag vet inte var en sÄdan struktur kan vara anvÀndbar. Bara ett pussel för att Äterigen förstÄ hur trÀd fungerar. Tack för din uppmÀrksamhet.

referenser

Projektet innehÄller testdata för att kontrollera drifthastigheten. TrÀdet hÄller pÄ att fyllas 1000000 element. Och det finns en sekventiell radering, infogning och hÀmtning av element 1000000 en gÄng. Det Àr 3000000 operationer. Resultatet visade sig vara ganska bra ~ 8 sekunder.

KĂ€lla: will.com

Köp pĂ„litlig hosting för webbplatser med DDoS-skydd, VPS VDS-servrar đŸ”„ Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar | ProHoster