Commit 5390778d authored by 's avatar
Browse files

Added a priority based heap, used in VOd.


git-svn-id: file:///home/svn/mapi/trunk@549 8d5bb341-7cf1-0310-8cf6-ba355fef3186
parent 8679767b
CFLAGS = -Wall -O2
DFLAGS =
all: test.c btheap.o
gcc ${DFLAGS} ${CFLAGS} test.c btheap.o -o test
btheap.o: btheap.c btheap.h
gcc ${DFLAGS} ${CFLAGS} -c btheap.c
clean:
rm -rf btheap.o test
/*
* btheap.c 03/01/2006 02:45
*/
#include <stdlib.h>
#include <assert.h>
#include "btheap.h"
static TreeNode *BinTree_swap(TreeNode * Root, TreeNode * K, TreeNode * L);
/***************************************************************************/
BTHeap *BTHeap_new(void) {
BTHeap *n;
if ((n = malloc(sizeof(BTHeap))) == 0x00) {
fprintf(stderr, "%s:%d:%s: malloc\n",__FILE__,__LINE__,__func__);
exit(1);
}
n->root = 0x00;
n->size = 0;
return n;
}
/***************************************************************************/
void BTHeap_destroy(BTHeap * heap) {
while (BTHeap_delete(heap))
;
heap->root = 0x00;
heap->size = 0;
free(heap);
}
/***************************************************************************/
static void dec_tobin(unsigned int n, char str[MAX_BIN_NR_LEN]) {
int pos = 0;
unsigned int power_of_2 = 1;
/* find max. power of 2 that is <= n */
while (power_of_2 <= n) {
if (power_of_2 * 2 > n) {
break;
} else {
power_of_2 *= 2;
}
}
while (power_of_2 > 0) {
if (pos == MAX_BIN_NR_LEN) {
assert(0);
}
if (n / power_of_2 == 1) {
str[pos++] = '1';
n -= power_of_2;
} else {
str[pos++] = '0';
}
power_of_2 /= 2;
}
str[pos] = '\0';
return;
}
/***************************************************************************/
static TreeNode *BinTree_swap(TreeNode * Root, TreeNode * K, TreeNode * L) {
TreeNode *temp;
if (K == NULL || L == NULL)
return Root;
if (K != Root && L != Root)
{
if (K->parent->right == K)
{
temp = K->parent->right;
K->parent->right = L;
}
else
{
temp = K->parent->left;
K->parent->left = L;
}
if (L->parent->right == L)
L->parent->right = temp;
else
L->parent->left = temp;
}
else if (K == Root)
{
if (L->parent->right == L)
L->parent->right = K;
else
L->parent->left = K;
Root = L;
}
temp = K->parent;
K->parent = L->parent;
L->parent = temp;
temp = K->left;
K->left = L->left;
L->left = temp;
temp = K->right;
K->right = L->right;
L->right = temp;
if (K->right)
K->right->parent = K;
if (K->left)
K->left->parent = K;
if (L->right)
L->right->parent = L;
if (L->left)
L->left->parent = L;
return Root;
}
/***************************************************************************/
static TreeNode *BinTree_goto(TreeNode *root, char str[MAX_BIN_NR_LEN]) {
int i;
for (i = 1; str[i] != '\0' && root; i++) {
if (str[i] == '0')
root = root->left;
else if (str[i] == '1')
root = root->right;
}
return root;
}
/***************************************************************************/
int BTHeap_insert(BTHeap * heap, int elem, void *data) {
TreeNode *p, *q, *n;
char str[MAX_BIN_NR_LEN];
int i;
if ((n = malloc(sizeof(TreeNode))) == 0x00) {
fprintf(stderr, "%s:%d:%s: malloc\n",__FILE__,__LINE__,__func__);
exit(1);
}
n->key = elem;
n->data = data;
n->parent = 0x00;
n->left = 0x00;
n->right = 0x00;
if (heap->root == 0x00) { /* Check if tree is empty */
heap->root = n;
heap->size = heap->size + 1;
}
else { /* ...else, link it, so it will be the last node of last level */
p = heap->root;
heap->size = heap->size + 1;
dec_tobin(heap->size, str);
for (i = 1; str[i] != 0x00; i++) {
if (str[i] == '0') {
q = p->left;
if (str[i + 1] == 0x00) {
n->parent = p;
p->left = n;
}
p = q;
} else if (str[i] == '1') {
q = p->right;
if (str[i + 1] == 0x00) {
n->parent = p;
p->right = n;
}
p = q;
}
}
/* ...and promote it in the appropriate position. */
for (q = n; q->parent != 0x00;) {
if (q->key < q->parent->key)
heap->root = BinTree_swap(heap->root, q->parent, q);
else
break;
}
}
return 1;
}
/***************************************************************************/
void* BTHeap_delete(BTHeap * heap) {
TreeNode *t, *prevr;
void *data = 0x00;
char str[MAX_BIN_NR_LEN];
/* Check if empty */
if (heap->root == 0x00)
return data;
data = heap->root->data;
/* Find the node to be removed (last node of last level)... */
dec_tobin(heap->size, str);
t = BinTree_goto(heap->root, str);
/* ...(Check if only root)... */
if (t == heap->root) {
free(heap->root);
heap->root = 0x00;
heap->size = heap->size - 1;
assert(heap->size == 0);
return data;
}
prevr = heap->root;
/* ...swap the Root with TempNode... */
heap->root = BinTree_swap(heap->root, prevr, t);
/* ...and remove the link between PrevRoot and its Parent. */
if (prevr->parent->right != 0x00)
prevr->parent->right = 0x00;
else
prevr->parent->left = 0x00;
free(prevr);
prevr = 0x00;
/* New Root promotion... */
for (t = heap->root; t != 0x00 && t->left != 0x00;) {
if (t->right == 0x00) {
if (t->key > t->left->key)
heap->root = BinTree_swap(heap->root, t, t->left);
else
break;
} else if (t->key > t->left->key && t->left->key < t->right->key)
heap->root = BinTree_swap(heap->root, t, t->left);
else if (t->key > t->right->key && t->left->key >= t->right->key)
heap->root = BinTree_swap(heap->root, t, t->right);
else
break;
}
/* decrease the number of total nodes. */
heap->size = heap->size - 1;
return data;
}
/***************************************************************************/
TreeNode *BTHeap_min(BTHeap *heap) {
assert(heap && (heap->root));
return heap->root;
}
/***************************************************************************/
/*
* BTHeap.h 03/01/2006 02:45
*/
#ifndef _BTHEAP_H_
#define _BTHEAP_H_
#include <stdio.h>
#define MAX_BIN_NR_LEN 64
typedef struct tree_node {
int key;
void *data;
struct tree_node *parent;
struct tree_node *left;
struct tree_node *right;
} TreeNode;
typedef struct bt_heap {
struct tree_node *root;
unsigned long size;
} BTHeap;
#define BTHeap_isEmpty(heap) (((heap) && ((heap)->root)) ? 0 : 1)
#define isLeaf(node) (((node)->left == 0x0 (node)->right == 0x00) ? 1 : 0)
#define isRoot(node) (((node)->parent == 0x00) ? 1 : 0)
#define getData(node) (node->data)
#define getKey(node) (node->key)
BTHeap *BTHeap_new(void);
void BTHeap_destroy(BTHeap *);
int BTHeap_insert(BTHeap *, int, void*);
void *BTHeap_delete(BTHeap *);
TreeNode* BTHeap_min(BTHeap *);
#endif
/*
* test.c 03/01/2006 14:45
*
* Copyright (C) 2006 Vasiliades George (gvasil@csd.uoc.gr)
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "btheap.h"
static void BTHeap_print(TreeNode * Root) {
if (Root) {
BTHeap_print(Root->left);
printf(" [%d, %d]", getKey(Root), (int)getData(Root));
BTHeap_print(Root->right);
}
}
int main(void) {
int n, choice, i;
int key, data;
TreeNode *node;
BTHeap * heap = BTHeap_new();
srand(time(NULL));
do {
printf("\n");
printf("1.Insert\n");
printf("2.Delete Minimum\n");
printf("3.Find Minimum\n");
printf("4.Test\n");
printf("5.Print\n");
printf("0.Quit\n");
printf("\n>");
scanf("%d", &choice);
switch (choice) {
case 0:
BTHeap_destroy(heap);
exit(0);
break;
case 1:
printf("\nEnter n: ");
scanf("%d", &n);
BTHeap_insert(heap, n, (void*)n);
break;
case 2:
if (!BTHeap_isEmpty(heap)) {
node = BTHeap_min(heap);
key = getKey(node);
data = (int)getData(node);
if (BTHeap_delete(heap))
printf("\n[%d, %d] deleted\n", key, data);
}
else
printf("\nPriority queue is empty.\n");
break;
case 3:
if (!BTHeap_isEmpty(heap))
printf("\nMin... [%d, %d]\n", getKey(BTHeap_min(heap)), (int)getData(BTHeap_min(heap)));
else
printf("\nPriority queue is empty.\n");
break;
case 4:
for (i = 0; i < 10000; i++) {
switch (rand() % 2) {
case 0:
n = rand() % 1000;
BTHeap_insert(heap, n, (void*)n);
break;
case 1:
BTHeap_delete(heap);
break;
default:
break;
}
}
break;
case 5:
if (!BTHeap_isEmpty(heap)) {
printf("\n===\n");
BTHeap_print(heap->root);
printf("\n===\n");
}
else
printf("\nPriority queue is empty.\n");
break;
default:
printf("\nunknown command\n");
break;
}
} while (1);
return 0;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment