You've already forked qlg.tsgz.moe
220 lines
5.2 KiB
C
Executable File
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);
|
|
}
|
|
}
|