成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Swoole 源碼分析——基礎(chǔ)模塊之 Heap 堆

callmewhy / 1252人閱讀

摘要:中是數(shù)據(jù)堆的權(quán)重,也是數(shù)據(jù)堆排序的依據(jù),是其在數(shù)據(jù)堆中的位置。改變數(shù)據(jù)的權(quán)重改變了數(shù)據(jù)節(jié)點(diǎn)的權(quán)重之后,需要重新進(jìn)行堆排序,將數(shù)據(jù)節(jié)點(diǎn)向上提升,或者將數(shù)據(jù)向下調(diào)整。

前言

heap 堆是 swoole 實(shí)現(xiàn)定時(shí)器最重要的數(shù)據(jù)結(jié)構(gòu),定時(shí)器將各個(gè)定時(shí)任務(wù)按照其下一次執(zhí)行的時(shí)間構(gòu)建最小堆,快速進(jìn)行插入與刪除。

heap 數(shù)據(jù)結(jié)構(gòu)

heapnum 是現(xiàn)有數(shù)據(jù)堆的數(shù)量,size 是數(shù)據(jù)堆的大小,type 用于確定數(shù)據(jù)堆是最大堆還是最小堆,nodes 是數(shù)據(jù)堆的節(jié)點(diǎn)。swHeap_nodepriority 是數(shù)據(jù)堆的權(quán)重,也是數(shù)據(jù)堆排序的依據(jù),position 是其在數(shù)據(jù)堆中的位置。

typedef struct swHeap_node
{
    uint64_t priority;
    uint32_t position;
    void *data;
} swHeap_node;

typedef struct _swHeap
{
    uint32_t num;
    uint32_t size;
    uint8_t type;
    swHeap_node **nodes;
} swHeap;

heap 數(shù)據(jù)堆 swHeap_new 創(chuàng)建數(shù)據(jù)堆

創(chuàng)建一個(gè)數(shù)據(jù)堆就是初始化 swHeap 的各個(gè)屬性。

swHeap *swHeap_new(size_t n, uint8_t type)
{
    swHeap *heap = sw_malloc(sizeof(swHeap));
    if (!heap)
    {
        return NULL;
    }
    if (!(heap->nodes = sw_malloc((n + 1) * sizeof(void *))))
    {
        sw_free(heap);
        return NULL;
    }
    heap->num = 1;
    heap->size = (n + 1);
    heap->type = type;
    return heap;
}
swHeap_push 數(shù)據(jù)入堆

數(shù)據(jù)入堆首先要檢查 heapsize 是否已經(jīng)足夠,如果不夠那么需要擴(kuò)容。

swHeap_bubble_up 函數(shù)負(fù)責(zé)將數(shù)據(jù)節(jié)點(diǎn)提升到數(shù)據(jù)堆中相應(yīng)的位置。方法很簡(jiǎn)單,新的數(shù)據(jù)節(jié)點(diǎn)不斷的和父節(jié)點(diǎn)進(jìn)行對(duì)比,符合條件就進(jìn)行替換,不符合條件就停止,結(jié)束。

swHeap_node* swHeap_push(swHeap *heap, uint64_t priority, void *data)
{
    void *tmp;
    uint32_t i;
    uint32_t newsize;

    if (heap->num >= heap->size)
    {
        newsize = heap->size * 2;
        if (!(tmp = sw_realloc(heap->nodes, sizeof(void *) * newsize)))
        {
            return NULL;
        }
        heap->nodes = tmp;
        heap->size = newsize;
    }

    swHeap_node *node = sw_malloc(sizeof(swHeap_node));
    if (!node)
    {
        return NULL;
    }
    node->priority = priority;
    node->data = data;
    i = heap->num++;
    heap->nodes[i] = node;
    swHeap_bubble_up(heap, i);
    return node;
}

#define left(i)   ((i) << 1)
#define right(i)  (((i) << 1) + 1)
#define parent(i) ((i) >> 1)

static void swHeap_bubble_up(swHeap *heap, uint32_t i)
{
    swHeap_node *moving_node = heap->nodes[i];
    uint32_t parent_i;

    for (parent_i = parent(i);
            (i > 1) && swHeap_compare(heap->type, heap->nodes[parent_i]->priority, moving_node->priority);
            i = parent_i, parent_i = parent(i))
    {
        heap->nodes[i] = heap->nodes[parent_i];
        heap->nodes[i]->position = i;
    }

    heap->nodes[i] = moving_node;
    moving_node->position = i;
}

static sw_inline int swHeap_compare(uint8_t type, uint64_t a, uint64_t b)
{
    if (type == SW_MIN_HEAP)
    {
        return a > b;
    }
    else
    {
        return a < b;
    }
}
swHeap_change_priority 改變數(shù)據(jù)的權(quán)重

改變了數(shù)據(jù)節(jié)點(diǎn)的權(quán)重之后,需要重新進(jìn)行堆排序,將數(shù)據(jù)節(jié)點(diǎn)向上提升,或者將數(shù)據(jù)向下調(diào)整。向下調(diào)整方法也很簡(jiǎn)單,不斷的和兩個(gè)子節(jié)點(diǎn)進(jìn)行比較,調(diào)整該數(shù)據(jù)節(jié)點(diǎn)和子節(jié)點(diǎn)的順序。

void swHeap_change_priority(swHeap *heap, uint64_t new_priority, void* ptr)
{
    swHeap_node *node = ptr;
    uint32_t pos = node->position;
    uint64_t old_pri = node->priority;

    node->priority = new_priority;
    if (swHeap_compare(heap->type, old_pri, new_priority))
    {
        swHeap_bubble_up(heap, pos);
    }
    else
    {
        swHeap_percolate_down(heap, pos);
    }
}

static void swHeap_percolate_down(swHeap *heap, uint32_t i)
{
    uint32_t child_i;
    swHeap_node *moving_node = heap->nodes[i];

    while ((child_i = swHeap_maxchild(heap, i))
            && swHeap_compare(heap->type, moving_node->priority, heap->nodes[child_i]->priority))
    {
        heap->nodes[i] = heap->nodes[child_i];
        heap->nodes[i]->position = i;
        i = child_i;
    }

    heap->nodes[i] = moving_node;
    moving_node->position = i;
}

static uint32_t swHeap_maxchild(swHeap *heap, uint32_t i)
{
    uint32_t child_i = left(i);
    if (child_i >= heap->num)
    {
        return 0;
    }
    swHeap_node * child_node = heap->nodes[child_i];
    if ((child_i + 1) < heap->num && swHeap_compare(heap->type, child_node->priority, heap->nodes[child_i + 1]->priority))
    {
        child_i++;
    }
    return child_i;
}
swHeap_pop 彈出堆頂元素

彈出堆頂元素后,需要重新調(diào)整整個(gè)數(shù)據(jù)堆。方法是將尾部元素和堆頂元素進(jìn)行交換,然后再對(duì)堆頂元素進(jìn)行排序。

void *swHeap_pop(swHeap *heap)
{
    swHeap_node *head;
    if (!heap || heap->num == 1)
    {
        return NULL;
    }

    head = heap->nodes[1];
    heap->nodes[1] = heap->nodes[--heap->num];
    swHeap_percolate_down(heap, 1);

    void *data = head->data;
    sw_free(head);
    return data;
}

swHeap_remove 刪除元素

刪除堆節(jié)點(diǎn)元素和彈出堆頂元素類(lèi)似,都是先將該元素和尾部元素進(jìn)行替換,然后再對(duì)其進(jìn)行排序。由于尾部元素不一定比待刪除的元素權(quán)重高,因此需要先判斷其權(quán)重,再?zèng)Q定是提升還是降低。

int swHeap_remove(swHeap *heap, swHeap_node *node)
{
    uint32_t pos = node->position;
    heap->nodes[pos] = heap->nodes[--heap->num];

    if (swHeap_compare(heap->type, node->priority, heap->nodes[pos]->priority))
    {
        swHeap_bubble_up(heap, pos);
    }
    else
    {
        swHeap_percolate_down(heap, pos);
    }
    return SW_OK;
}

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/30855.html

相關(guān)文章

  • Swoole 源碼分析——Server模塊Timer模塊與時(shí)間輪算法

    摘要:當(dāng)其就緒時(shí),會(huì)調(diào)用執(zhí)行定時(shí)函數(shù)。進(jìn)程超時(shí)停止進(jìn)程將要停止時(shí),并不會(huì)立刻停止,而是會(huì)等待事件循環(huán)結(jié)束后停止,這時(shí)為了防止進(jìn)程不退出,還設(shè)置了的延遲,超過(guò)就會(huì)停止該進(jìn)程。當(dāng)允許空閑時(shí)間小于時(shí),統(tǒng)一每隔檢測(cè)空閑連接。 前言 swoole 的 timer 模塊功能有三個(gè):用戶定時(shí)任務(wù)、剔除空閑連接、更新 server 時(shí)間。timer 模塊的底層有兩種,一種是基于 alarm 信號(hào),一種是基于...

    qieangel2013 評(píng)論0 收藏0
  • Python 的 heapq 模塊源碼分析

    摘要:原文鏈接起步模塊實(shí)現(xiàn)了適用于列表的最小堆排序算法。本文內(nèi)容將分為三個(gè)部分,第一個(gè)部分簡(jiǎn)單介紹模塊的使用第二部分回顧堆排序算法第三部分分析中的實(shí)現(xiàn)??偨Y(jié)堆排序結(jié)合圖來(lái)理解還是比較好理解的。 原文鏈接:https://www.hongweipeng.com/i... 起步 heapq 模塊實(shí)現(xiàn)了適用于Python列表的最小堆排序算法。 showImg(https://segmentfaul...

    CoderBear 評(píng)論0 收藏0
  • Swoole 源碼分析——基礎(chǔ)模塊Queue隊(duì)列

    摘要:消息隊(duì)列的接受消息隊(duì)列的接受是利用函數(shù),其中是消息的類(lèi)型,該參數(shù)會(huì)取出指定類(lèi)型的消息,如果設(shè)定的是爭(zhēng)搶模式,該值會(huì)統(tǒng)一為,否則該值就是消息發(fā)送目的的。環(huán)形隊(duì)列的消息入隊(duì)發(fā)送消息首先要確定環(huán)形隊(duì)列的隊(duì)尾。取模操作可以優(yōu)化 前言 swoole 的底層隊(duì)列有兩種:進(jìn)程間通信 IPC 的消息隊(duì)列 swMsgQueue,與環(huán)形隊(duì)列 swRingQueue。IPC 的消息隊(duì)列用于 task_wor...

    jollywing 評(píng)論0 收藏0
  • Swoole 源碼分析——基礎(chǔ)模塊 Channel 隊(duì)列

    摘要:前言內(nèi)存數(shù)據(jù)結(jié)構(gòu),類(lèi)似于的通道,底層基于共享內(nèi)存互斥鎖實(shí)現(xiàn),可實(shí)現(xiàn)用戶態(tài)的高性能內(nèi)存隊(duì)列。是當(dāng)前隊(duì)列占用的內(nèi)存大小,用來(lái)指定是否使用共享內(nèi)存是否使用鎖是否使用通知。 前言 內(nèi)存數(shù)據(jù)結(jié)構(gòu) Channel,類(lèi)似于 Go 的 chan 通道,底層基于 共享內(nèi)存 + Mutex 互斥鎖實(shí)現(xiàn),可實(shí)現(xiàn)用戶態(tài)的高性能內(nèi)存隊(duì)列。Channel 可用于多進(jìn)程環(huán)境下,底層在讀取寫(xiě)入時(shí)會(huì)自動(dòng)加鎖,應(yīng)用層不需...

    txgcwm 評(píng)論0 收藏0
  • JavaScript 內(nèi)存分析新工具 OneHeap

    摘要:關(guān)注于運(yùn)行中的內(nèi)存信息的展示,用可視化的方式還原了,有助于理解內(nèi)存管理。背景運(yùn)行過(guò)程中的大部分?jǐn)?shù)據(jù)都保存在堆中,所以性能分析另一個(gè)比較重要的方面是內(nèi)存,也就是堆的分析。上周發(fā)布了工具,可以用來(lái)動(dòng)態(tài)地展示的結(jié)果,分析各種函數(shù)的調(diào)用關(guān)系。 OneHeap 關(guān)注于運(yùn)行中的 JavaScript 內(nèi)存信息的展示,用可視化的方式還原了 HeapGraph,有助于理解 v8 內(nèi)存管理。 ...

    zilu 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<