当前位置: 首页 > 后端技术 > PHP

Swoole源码解析——基础模块Heap堆

时间:2023-03-29 19:11:34 PHP

前言heap堆是swoole实现定时器最重要的数据结构。定时器根据每个定时任务的下一次执行时间,为每个定时任务建立一个最小堆,并快速插入和删除。heap数据结构heap中,num是现有数据堆的个数,size是数据堆的大小,type用来判断数据堆是最大堆还是最小堆,nodes是数据堆的节点数据堆。swHeap_node中的priority是数据堆的权重,也是数据堆排序的依据,position是它在数据堆中的位置。typedefstructswHeap_node{uint64_t优先级;uint32_t位置;void*data;}swHeap_node;typedefstruct_swHeap{uint32_tnum;uint32_t大小;uint8_t类型;初始化swHeap的各种属性。swHeap*swHeap_new(size_tn,uint8_ttype){swHeap*heap=sw_malloc(sizeof(swHeap));如果(!堆){返回NULL;}if(!(heap->nodes=sw_malloc((n+1)*sizeof(void*)))){sw_free(heap);返回空值;}堆->num=1;堆->大小=(n+1);堆->类型=类型;returnheap;}swHeap_pushdatainput将堆数据加载到堆中,首先检查堆的大小是否足够,如果不够,则扩大大小。swHeap_bubble_up函数负责将数据节点提升到数据堆中的相应位置。方法很简单。新的数据节点不断地与父节点进行比较。如果满足条件,它将被替换。如果不满足条件,则停止并结束。swHeap_node*swHeap_push(swHeap*heap,uint64_tpriority,void*data){void*tmp;uint32_t我;uint32_t新闻大小;if(heap->num>=heap->size){newsize=heap->size*2;如果(!(tmp=sw_realloc(heap->nodes,sizeof(void*)*newsize))){returnNULL;}heap->nodes=tmp;堆->大小=新闻大小;}swHeap_node*node=sw_malloc(sizeof(swHeap_node));如果(!节点){返回NULL;}节点->优先级=优先级;节点->数据=数据;i=heap->num++;堆->节点[i]=节点;swHeap_bubble_up(堆,我);返回节点;}#defineleft(i)((i)<<1)#defineright(i)(((i)<<1)+1)#defineparent(i)((i)>>1)staticvoidswHeap_bubble_up(swHeap*heap,uint32_ti){swHeap_node*moving_node=heap->nodes[i];uint32_tparent_i;对于(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];堆->节点[i]->位置=我;}heap->nodes[i]=moving_node;moving_node->position=i;}staticsw_inlineintswHeap_compare(uint8_ttype,uint64_ta,uint64_tb){if(type==SW_MIN_HEAP){返回a>b;}else{返回a位置;uint64_told_pri=节点->优先级;节点->优先级=新优先级;if(swHeap_compare(heap->type,old_pri,new_priority)){swHeap_bubble_up(heap,pos);}else{swHeap_percolate_down(heap,pos);}}staticvoidswHeap_percolate_down(swHeap*heap,uint32_ti){uint32_tchild_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[孩子我];堆->节点[i]->位置=我;我=孩子我;}heap->nodes[i]=moving_node;moving_node->position=i;}staticuint32_tswHeap_maxchild(swHeap*heap,uint32_ti){uint32_tchild_i=left(我);if(child_i>=heap->num){返回0;}swHeap_node*child_node=heap->nodes[child_i];if((child_i+1)num&&swHeap_compare(heap->type,child_node->priority,heap->nodes[child_i+1]->priority)){child_i++;}returnchild_i;}swHeap_pop弹出堆顶元素后,需要重新调整整个数据堆。与堆顶元素交换,然后对堆顶元素进行排序。void*swHeap_pop(swHeap*heap){swHeap_node*head;if(!heap||heap->num==1){returnNULL;}head=heap->nodes[1];heap->nodes[1]=heap->nodes[--heap->num];swHeap_percolate_down(堆,1);void*data=head->data;sw_free(头);returndata;}swHeap_removedeleteelements删除堆节点元素,弹出堆顶元素,同理先替换元素和尾元素,再排序。由于尾部元素的权重不一定比要删除的元素高,所以需要先判断其权重再决定增减。intswHeap_remove(swHeap*heap,swHeap_node*node){uint32_tpos=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);}返回SW_OK;}

最新推荐
猜你喜欢