Files
qlg.tsgz.moe/vendor/swoole/src/core/heap.c
2019-09-06 23:53:10 +08:00

220 lines
5.2 KiB
C
Executable File

/*
+----------------------------------------------------------------------+
| Swoole |
+----------------------------------------------------------------------+
| This source file is subject to version 2.0 of the Apache license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.apache.org/licenses/LICENSE-2.0.html |
| If you did not receive a copy of the Apache2.0 license and are unable|
| to obtain it through the world-wide-web, please send a note to |
| license@swoole.com so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Tianfeng Han <mikan.tenny@gmail.com> |
+----------------------------------------------------------------------+
*/
#include "swoole.h"
#include "heap.h"
#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);
static uint32_t swHeap_maxchild(swHeap *heap, uint32_t i);
static void swHeap_percolate_down(swHeap *heap, uint32_t i);
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;
}
void swHeap_free(swHeap *heap)
{
sw_free(heap->nodes);
sw_free(heap);
}
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;
}
}
uint32_t swHeap_size(swHeap *q)
{
return (q->num - 1);
}
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;
}
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 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;
}
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;
}
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);
}
}
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;
}
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;
}
void *swHeap_peek(swHeap *heap)
{
if (heap->num == 1)
{
return NULL;
}
swHeap_node *node = heap->nodes[1];
if (!node)
{
return NULL;
}
return node->data;
}
void swHeap_print(swHeap *heap)
{
int i;
for(i = 1; i < heap->num; i++)
{
printf("#%d\tpriority=%ld, data=%p\n", i, (long)heap->nodes[i]->priority, heap->nodes[i]->data);
}
}