A
arnuld
After discussing in my other thread titled "A C implementation of Binary
Heap", I have done this attempt of coding and came with this code makes a
proper Binary Heap inside the array without any problems so far.
I am posting the code for verification of my assumptions and of course as
usual for any advice on improvements. Does anyone see a hidden bug inside
the program before I go on extending it to completion. Any advice will be
appreciated
If array has five elements then this should be the Binary-Heap, correct
me if I am wrong:
P5
/ \
P4 P3
/ \
P2 P1
(section 9.2, Algorithms in C - Robert Sedgewick)
NOTE: one strange thing though, I am using -ansi flgg rather than -
std=c99 with gcc but then why it does not report any warning/error if I
am using __func__ , a C99 facility, not present in C90
/* A simple implementation of Priority Queue using a heap-based array. We
will be using it for 3 operations:
*
* (1) Insert an element with some priority in the PQ. No duplicate
elements.
* (2) Delete the element with highest priority.
* (3) find the element with highest priority.
*
*
* VERSION 0.0
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* we are going to use an array of pointers, a pointer takes 4 bytes, so
using an array of 100,000 elements = 400 KB, which is an amount
of memory too small to be concerned about when we 64 MB of RAM at our
disposal. 10,000 is the minimum number of elements we will
be needing. In an average case we will need to use 100,000 elements,
hence the number of element in the array */
enum { SIZE_ARR = 100000 };
enum { SIZE_PRIO = 20,
SIZE_GRADE = 20
};
enum BOOL { NO = 0,
YES = 1,
VAL_FAIL = NO,
VAL_SUCC = YES};
struct pq_element
{
char priority[SIZE_PRIO];
char grade[SIZE_GRADE];
};
struct pq_element* PQ_arr[SIZE_ARR] = {0};
static long int N = -1;
struct pq_element* PQ_create_element(char [], char []);
void PQ_insert(struct pq_element* );
void PQ_remove(struct pq_element* [], long, long);
void PQ_heapify_up(long int );
enum BOOL PQ_element_exists(struct pq_element* );
enum BOOL PQ_comp_less(struct pq_element*, struct pq_element*);
void PQ_swap_elements(struct pq_element**, struct pq_element** );
void PQ_print(struct pq_element** );
void PQ_print_single_element(struct pq_element* );
int main(void)
{
struct pq_element* a1 = PQ_create_element("P1", "G-Average");
struct pq_element* a2 = PQ_create_element("P2", "G-First");
struct pq_element* a3 = PQ_create_element("P3", "G-First");
struct pq_element* a4 = PQ_create_element("P4", "G-First");
struct pq_element* a5 = PQ_create_element("P5", "G-First");
if(NULL == a1)
{
fprintf(stderr, "IN: %s : Memory Exhausted!\n", __func__);
}
PQ_insert(a1);
PQ_insert(a2);
PQ_insert(a3);
PQ_insert(a4);
PQ_insert(a5);
PQ_insert(a1);
PQ_print(PQ_arr);
return 0;
}
struct pq_element* PQ_create_element(char prio[], char grd[])
{
struct pq_element* p = malloc(1 * sizeof*p);
if(p)
{
strcpy(p->priority, prio);
strcpy(p->grade, grd);
}
return p;
}
void PQ_insert(struct pq_element* p)
{
if(NULL == p)
{
printf("IN: %s, Can not add NULL element to PQ\n", __func__);
return;
}
if(PQ_element_exists(p))
{
/* printf("IN: %s:, An element with same priority is already
present in the queue\n", __func__); */
return;
}
PQ_arr[++N] = p;
PQ_heapify_up(N);
}
enum BOOL PQ_element_exists(struct pq_element* p)
{
int i;
struct pq_element* c;
for(i = 0; i <= N; ++i)
{
c = PQ_arr;
if(0 == strcmp(c->priority, p->priority))
{
return YES;
}
}
return NO;
}
void PQ_heapify_up(long int n)
{
for( ; (n >= 0) && PQ_comp_less(PQ_arr[n/2], PQ_arr[n]); n = n/2 )
{
PQ_swap_elements(&PQ_arr[n/2], &PQ_arr[n]);
}
}
/* chekc if first argument has lesser priority than second */
enum BOOL PQ_comp_less(struct pq_element* b1, struct pq_element* b2)
{
int comp;
/*
printf("going to compare, N = %ld\n", N);
printf("b1->priority: %s\nb1->grade: %s\n", b1->priority, b1->grade);
printf("b2->priority: %s\nb2->grade: %s\n", b2->priority, b2->grade);
*/
if( (comp = strcmp( b1->priority, b2->priority)) < 0 )
{
/* printf("comp YES\n\n"); */
return YES;
}
/* printf("comp NO\n\n"); */
return NO;
}
void PQ_swap_elements(struct pq_element** p, struct pq_element** q)
{
struct pq_element* temp = *p;
*p = *q;
*q = temp;
}
void PQ_print(struct pq_element** p)
{
for( ; p && *p; ++p)
{
PQ_print_single_element(*p);
}
}
void PQ_print_single_element(struct pq_element* p)
{
if(p)
{
printf("priority: %s\n", p->priority);
printf("grade: %s\n\n", p->grade);
}
}
======================== OUTPUT ===========================
[arnuld@dune programs]$ gcc -ansi -pedantic -Wall -Wextra PQ-array.c
[arnuld@dune programs]$ ./a.out
priority: P5
grade: G-First
priority: P4
grade: G-First
priority: P3
grade: G-First
priority: P2
grade: G-First
priority: P1
grade: G-Average
[arnuld@dune programs]$
Heap", I have done this attempt of coding and came with this code makes a
proper Binary Heap inside the array without any problems so far.
I am posting the code for verification of my assumptions and of course as
usual for any advice on improvements. Does anyone see a hidden bug inside
the program before I go on extending it to completion. Any advice will be
appreciated
If array has five elements then this should be the Binary-Heap, correct
me if I am wrong:
P5
/ \
P4 P3
/ \
P2 P1
(section 9.2, Algorithms in C - Robert Sedgewick)
NOTE: one strange thing though, I am using -ansi flgg rather than -
std=c99 with gcc but then why it does not report any warning/error if I
am using __func__ , a C99 facility, not present in C90
/* A simple implementation of Priority Queue using a heap-based array. We
will be using it for 3 operations:
*
* (1) Insert an element with some priority in the PQ. No duplicate
elements.
* (2) Delete the element with highest priority.
* (3) find the element with highest priority.
*
*
* VERSION 0.0
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* we are going to use an array of pointers, a pointer takes 4 bytes, so
using an array of 100,000 elements = 400 KB, which is an amount
of memory too small to be concerned about when we 64 MB of RAM at our
disposal. 10,000 is the minimum number of elements we will
be needing. In an average case we will need to use 100,000 elements,
hence the number of element in the array */
enum { SIZE_ARR = 100000 };
enum { SIZE_PRIO = 20,
SIZE_GRADE = 20
};
enum BOOL { NO = 0,
YES = 1,
VAL_FAIL = NO,
VAL_SUCC = YES};
struct pq_element
{
char priority[SIZE_PRIO];
char grade[SIZE_GRADE];
};
struct pq_element* PQ_arr[SIZE_ARR] = {0};
static long int N = -1;
struct pq_element* PQ_create_element(char [], char []);
void PQ_insert(struct pq_element* );
void PQ_remove(struct pq_element* [], long, long);
void PQ_heapify_up(long int );
enum BOOL PQ_element_exists(struct pq_element* );
enum BOOL PQ_comp_less(struct pq_element*, struct pq_element*);
void PQ_swap_elements(struct pq_element**, struct pq_element** );
void PQ_print(struct pq_element** );
void PQ_print_single_element(struct pq_element* );
int main(void)
{
struct pq_element* a1 = PQ_create_element("P1", "G-Average");
struct pq_element* a2 = PQ_create_element("P2", "G-First");
struct pq_element* a3 = PQ_create_element("P3", "G-First");
struct pq_element* a4 = PQ_create_element("P4", "G-First");
struct pq_element* a5 = PQ_create_element("P5", "G-First");
if(NULL == a1)
{
fprintf(stderr, "IN: %s : Memory Exhausted!\n", __func__);
}
PQ_insert(a1);
PQ_insert(a2);
PQ_insert(a3);
PQ_insert(a4);
PQ_insert(a5);
PQ_insert(a1);
PQ_print(PQ_arr);
return 0;
}
struct pq_element* PQ_create_element(char prio[], char grd[])
{
struct pq_element* p = malloc(1 * sizeof*p);
if(p)
{
strcpy(p->priority, prio);
strcpy(p->grade, grd);
}
return p;
}
void PQ_insert(struct pq_element* p)
{
if(NULL == p)
{
printf("IN: %s, Can not add NULL element to PQ\n", __func__);
return;
}
if(PQ_element_exists(p))
{
/* printf("IN: %s:, An element with same priority is already
present in the queue\n", __func__); */
return;
}
PQ_arr[++N] = p;
PQ_heapify_up(N);
}
enum BOOL PQ_element_exists(struct pq_element* p)
{
int i;
struct pq_element* c;
for(i = 0; i <= N; ++i)
{
c = PQ_arr;
if(0 == strcmp(c->priority, p->priority))
{
return YES;
}
}
return NO;
}
void PQ_heapify_up(long int n)
{
for( ; (n >= 0) && PQ_comp_less(PQ_arr[n/2], PQ_arr[n]); n = n/2 )
{
PQ_swap_elements(&PQ_arr[n/2], &PQ_arr[n]);
}
}
/* chekc if first argument has lesser priority than second */
enum BOOL PQ_comp_less(struct pq_element* b1, struct pq_element* b2)
{
int comp;
/*
printf("going to compare, N = %ld\n", N);
printf("b1->priority: %s\nb1->grade: %s\n", b1->priority, b1->grade);
printf("b2->priority: %s\nb2->grade: %s\n", b2->priority, b2->grade);
*/
if( (comp = strcmp( b1->priority, b2->priority)) < 0 )
{
/* printf("comp YES\n\n"); */
return YES;
}
/* printf("comp NO\n\n"); */
return NO;
}
void PQ_swap_elements(struct pq_element** p, struct pq_element** q)
{
struct pq_element* temp = *p;
*p = *q;
*q = temp;
}
void PQ_print(struct pq_element** p)
{
for( ; p && *p; ++p)
{
PQ_print_single_element(*p);
}
}
void PQ_print_single_element(struct pq_element* p)
{
if(p)
{
printf("priority: %s\n", p->priority);
printf("grade: %s\n\n", p->grade);
}
}
======================== OUTPUT ===========================
[arnuld@dune programs]$ gcc -ansi -pedantic -Wall -Wextra PQ-array.c
[arnuld@dune programs]$ ./a.out
priority: P5
grade: G-First
priority: P4
grade: G-First
priority: P3
grade: G-First
priority: P2
grade: G-First
priority: P1
grade: G-Average
[arnuld@dune programs]$