摘要:中是數(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)heap 中 num 是現(xiàn)有數(shù)據(jù)堆的數(shù)量,size 是數(shù)據(jù)堆的大小,type 用于確定數(shù)據(jù)堆是最大堆還是最小堆,nodes 是數(shù)據(jù)堆的節(jié)點(diǎn)。swHeap_node 中 priority 是數(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ù)入堆首先要檢查 heap 的 size 是否已經(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
摘要:當(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),一種是基于...
摘要:原文鏈接起步模塊實(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...
摘要:消息隊(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...
摘要:前言內(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)用層不需...
摘要:關(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)存管理。 ...
閱讀 2350·2021-11-15 11:38
閱讀 3563·2021-09-22 15:16
閱讀 1204·2021-09-10 11:11
閱讀 3175·2021-09-10 10:51
閱讀 2962·2019-08-30 15:56
閱讀 2793·2019-08-30 15:44
閱讀 3199·2019-08-28 18:28
閱讀 3537·2019-08-26 13:36