What is wrong with my insert function for min-heaps? - c

I'm trying to write a minimum heap data structure in C, but I ran into some issues while implementing the insert function.
It looks like this :
void insert(MinHeap* minh , int key)
{
if(minh->itemcount == minh->maxSize)
{
printf("cant insert,heap is full\n");
return;
}
minh->itemcount++;
minh->HeapArray[minh->itemcount]=key;
int parent=getParent(minh->itemcount);
while(parent != 0 && minh->HeapArray[parent] > minh->HeapArray[minh->itemcount])
{
swap(&(minh->HeapArray[parent]), &(minh->HeapArray[minh->itemcount]));
parent = parent/2;
}
}
Now the insertion process works if I insert the following values:
insert(minheap,5);
insert(minheap,3);
insert(minheap,2);
insert(minheap,4);
The output came out to be:
2 4 3 5
This is a valid output, since it follows the minimum heap property.
But once I start adding more values like 1, the output is:
2 1 3 5 4
As can you see, there is "bubbling up" of 1 occurring, but it doesn't seem to go all the way up, since 1 should be the first element, not 2.
I'm not sure why is this occurring, because my code for insertion has the same logic as any other minimum heap insertion function.
It would be great if anyone can help with clearing this up.
Some side notes:
MinHeap is a type-defined structure, and its members are :
typedef struct Heap
{
int* HeapArray;
int maxSize;
int itemcount;
} MinHeap;
I have a created an "instance" (with malloc) of this structure in the main function. I also dynamically allocated memory for the HeapArray Member. I also set the itemcount member to be equal to 0.
Also, the indexing for my minimum heap array starts with 1 not 0,
so the getParent function returns the following:
int getParent(int index)
{
return floor(index/2);
}

The main issue is that you are always swapping with the same element, i.e. with the last one at minh->HeapArray[minh->itemcount]: in the first iteration of the loop this is indeed the child of parent, but if there are more iterations, it no longer represents the child.
As a side issue: you have parent = parent / 2 in your loop: why didn't you use the getParent function here?
Secondly, the getParent function does not need to use floor: the division is already an integer division.
Here is the correction of where the main issue occurred:
int child = ++minh->itemcount;
minh->HeapArray[child] = key;
int parent = getParent(child);
while (parent != 0 && minh->HeapArray[parent] > minh->HeapArray[child]) {
swap(&(minh->HeapArray[parent]) , &(minh->HeapArray[child]));
child = parent;
parent = getParent(child);
}

Related

Alias for variable of type struct in C

I would like to create (some type of) "alias" to a struct object in C.
Based on a variable, a should be x or y. But it should not be copied, it needs to be a reference to that a-object.
Some code:
void search(node start, node end) {
int myid = omp_get_thread_num();
node localstart;
if (myid == 0) {
// start correct way
localstart = start; // <-- how?!
}
else{
// start reversed way
localstart = end; // <-- how?!
}
// do something with localstart eg.:
localstart->dist = 0;
// now should
// start->dist == 0 or end->dist == 0 (based on myid)
// be true!
}
The code is some part of a bidirectional search. One thread should start at the start and search for the end and the other one should start at the end and search for the start.
On the other hand, I could call a function with start and end (and reversed). But also here, I would need to pass the struct as reference.
I would like to use the first idea, if possible!
In C, you reference a variable using a pointer:
node *localstart;
if (myid == 0) {
// start correct way
localstart = &start;
}
else {
// start reversed way
localstart = &end;
}
(*localstart)->dist = 0;
From your usage of node it is clear that it is actually a pointer to a structure, so now you have a pointer-to-pointer. Not a problem for the C compiler, it can even optimize away the pointer variable in some cases. Just do not forget the parentheses!

Freeing a dynamically allocated structure instance in C

I have following structure:
typedef struct generic_attribute_struct{
attribute_value current_value;
attribute_value previous_value;
attribute_value running_value;
} generic_attribute;
where attribute_value is simply a placeholder for unsigned long long int.
I have the following constructor for this structure:
generic_attribute* construct_generic_attribute(attribute_value current_value){
generic_attribute *ga_ptr; //allocate space for pointer to generic attribute
if(ga_ptr = malloc (sizeof (generic_attribute))){ //if allocation succeeds
set_ga_current_value(ga_ptr, current_value); //assigned the current value to given input
set_ga_previous_value(ga_ptr, 0); //set previous value to zero
set_ga_running_value(ga_ptr);
} else{ //else, inform user of error
fprintf(stderr, "Health Monitor ran out of space when allocating memory for a generic attribute.");
}
return ga_ptr; // return pointer to new attribute or a NULL pointer if memory allocation failed
}
where set_ga_running_value looks like this:
attribute_value set_ga_running_value(generic_attribute* ga_ptr){
attribute_value delta = get_ga_current_value(ga_ptr) - get_ga_previous_value(ga_ptr);
ga_ptr->running_value = (ga_ptr->running_value? ga_ptr->running_value : 0) + delta;
return ga_ptr->running_value;
}
Destructor for this structure looks like this:
void destroy_generic_attribute(generic_attribute** ga_ptr){
free(*ga_ptr);
}
I created a test that asks the user for some current_value input, constructs a pointer, and prints out whether the values for structure variables are what they ought to be. This test loops until the user no longer wants to test, in which case they quit out of the test.
So, the test looks like this:
Does user want to test? If yes, go to 2). If no, go to 7).
Get input from user
Call constructor for generic attribute with this new input
Verify that generic attribute was created correctly
Call the destructor on generic attribute
Go to 1.
Quit
This is what the test looks like:
void test_generic_attribute_constructor_with_user_input(){
attribute_value input;
int continue_var;
bool current_value_test, previous_value_test, running_value_test, pointer_test;
generic_attribute* ga_ptr;
while(1){
printf("Would you like to execute a test for Generic Attribute Constructor? Type 1 for YES, or 0 for NO: ");
scanf("%i", &continue_var);
if(continue_var){
printf(TESTING, "Constructor for Generic Attribute and Generic Attribute Reader");
printf("\n" INPUT, "single number");
scanf("%lld", &input);
ga_ptr = construct_generic_attribute(input);
read_generic_attribute(ga_ptr);
current_value_test = (get_ga_current_value(ga_ptr) == input ? true : false);
previous_value_test = (get_ga_previous_value(ga_ptr) == 0 ? true: false);
// THIS TEST FAILS
running_value_test = (get_ga_running_value(ga_ptr) == input ? true: false);
pointer_test = (ga_ptr ? true: false);
printf("%s.\n", ((current_value_test && previous_value_test && running_value_test && pointer_test) ? PASS : FAIL));
destroy_generic_attribute(&ga_ptr);
}else{
printf("\nOK! Testing concluded.");
break;
}
}
}
My problem is that the "running value" seems to never get "reset" when the ga_ptr gets destroyed. It seems to keep its old value. How would I clear memory for the entire ga_ptr structure properly?
test result:
Would you like to execute a test for Generic Attribute Constructor? Type 1 for YES, or 0 for NO: 1
Testing Constructor for Generic Attribute and Generic Attribute Reader:
Please enter single number for input: 10
Generic Attribute has the following contents:
Pointer Current Value Previos Value Running Value
0x600058530 10 0 10
PASS.
Would you like to execute a test for Generic Attribute Constructor? Type 1 for YES, or 0 for NO: 1
Testing Constructor for Generic Attribute and Generic Attribute Reader:
Please enter single number for input: 20
Generic Attribute has the following contents:
Pointer Current Value Previos Value Running Value
0x600058530 20 0 30
FAIL.
I would expect the Running value to be 20.
If I change the destructor to this:
void destroy_generic_attribute(generic_attribute** ga_ptr){
set_ga_current_value(*ga_ptr, 0);
set_ga_previous_value(*ga_ptr, 0);
(*ga_ptr)->running_value = 0;
free(*ga_ptr);
}
My test pass... However, I do not understand why skipping the setters makes the code fail.
You are just invoking undefined behaviour by using a never initialized value.
In construct_generic_attribute, you initialize current and previous value and then call set_ga_running_value. In the latter, you use current and previous values that have just been initialize to compute delta : fine until here. But then you have :
ga_ptr->running_value = (ga_ptr->running_value? ga_ptr->running_value : 0) + delta;
Meaning that you use running_value before initializing it. As it is in a freshly malloc'ed struct, its value is just undefined. It might be 0, or it might be the value that existed in this memory location before allocation, or it might be a special value that compiler uses as a special initialization : you cannot know and should not rely on anything.
You compiler seems to preinitialize memory to 0 on run and then never change the value on free and malloc, giving 30 on second run. Mine (in debug mode) allways initialized malloc'ed values to 0xcdcdcdcd, giving FAIL on each test. Just undefined behaviour ...
So you really should initialize the freshed allocated struct in your constructor :
if(ga_ptr = malloc (sizeof (generic_attribute))){ //if allocation succeeds
memset(ga_ptr, 0, sizeof(generic_attribute)); // ensure all values are set to 0
set_ga_current_value(ga_ptr, current_value); //assigned the current value to given input
set_ga_previous_value(ga_ptr, 0); //set previous value to zero
set_ga_running_value(ga_ptr);
or if you know that running_value is an integral, just replace the memset with:
ga_ptr->running_value = 0;

Stack implemented as an array defaulting first value to 0 in C

I have an assignment where I am supposed to use this very very simple (or so I thought) stack that my teacher wrote in C, just using an array. From this, I have to implement reverse polish notation from a text file.
In order for me to implement this, I am using a stack, pushing values on until I hit an operation. I then do the operation and push the result back onto the stack until the user hits p to print the value.
The problem is, for some reason, my professor's implementation of the stack array defaults the first (index 0) value to 0. Printing the stack without pushing anything onto it should result in null but it appears the output is 0.
Here is my professor's implementation of the stack:
#define STK_MAX 1024
#define ELE int
ELE _stk[STK_MAX];
int _top = 0;
void stk_error(char *msg)
{
fprintf(stderr, "Error: %s\n", msg);
exit(-1);
}
int stk_is_full()
{
return _top >= STK_MAX;
}
int stk_is_empty()
{
return _top == 0;
}
void stk_push(ELE v)
{
if ( stk_is_full() )
stk_error("Push on full stack");
_stk[_top++] = v;
}
ELE stk_pop()
{
if ( stk_is_empty() )
stk_error("pop on empty stack");
return _stk[--_top];
}
void print()
{
for(int i = 0; i <= _top; ++i)
printf("%d ", _stk[i]);
printf("\n");
}
I realize that the print statement will print a value that has not been pushed yet, but the problem is, is that when I don't print it, it still ends up there and it ends up screwing up my rpn calculator. Here is what happens when I do this:
// input
stk_push(2);
print();
stk_push(4);
print();
// output
2 0
2 4 0
How do I get rid of the 0 value that is affecting my calculator? Doing stk_pop() after the pushing the first value onto the stack didn't seem to work, and checking that top == 0, then directly inserting that element before incrementing _top didn't work.
When you are printing, loop from 0 to (_top - 1), since your top most element is actually at _top - 1. Hint : Look at your pop/push method.
void print()
{
for(int i = 0; i < _top; ++i)
printf("%d ", _stk[i]);
printf("\n");
}
"The problem is, is that the rpn calculator relies on the TOS being accurate. When I do pop() though, it will pop 0 and not the real TOS."
Sounds like a problem with your calculator implementation. You assumed the top of the stack would be null, but that's not the case for your professors stack implementation. Simply a invalid assumption.
Instead he's provided a stk_is_empty() method to help determine when you've pop everything.
If you need to pop all elements, you'll need to break on the condition of stk_is_empty().
stk_push(2);
stk_push(4);
while( stk_is_empty() == false)
{
stk_pop();
}
Of course in reality you'd be setting the pop return to a variable and doing something with it. The key point is leveraging stk_is_empty().
I haven't written C++ in few years so hopefully I didn't make a minor syntax error.

Search and Inserting in a binary tree recursively

first of all happy new year. I was trying to fix a piece of code I've been stumped on for hours. (Note: I am not a solid coder.)
What I am trying to do is to write a function "searchInsert", which will take in a binary tree and some integer i. It will then try to find the integer i in the tree. If it's not there it is inserted into the tree.
Other information: If we do in fact find the integer in the tree, return a pointer pointing to the node of to it. If we do not find it as we said before, insert it in BUT return a pointer pointing to the root of the tree.
I also must do this recursively.
Now I have tested it using an arbitrary tree along with i = 98, as follows:
Before what it looks like.
4
/ \
2 6
/ \ / \
1 3 5 7
After, what it should look like:
4
/ \
2 6
/ \ / \
1 3 5 7
\
98
But my code doesn't seem to be working.
treelink searchInsert(treelink t, TreeItem i){
treelink keyNode = NULL;
if (t == NULL) {
t = insertTreeNode(t, i);
} else if(i < t->item){
keyNode = searchInsert(t->left,i);
} else if(i > t->item){
keyNode = searchInsert(t->right,i);
} else {
keyNode = t;
return keyNode;
}
return t;
}
Other important notes: treelink is a pointer to a binary tree. Assume insertTreeNode works as it was a function given to us.
Any help would be appreciated thanks.
Among other problems, you have lost all context when you realize that you have not found the item that you are looking for:
if ( t == NULL ) {
t = insertTreeNode(t, i) ;
}
So you are always calling insertTreeNode with NULL as the first argument.
While recursion is a great way to step through a tree, you might instead want to create a pointer and iterate through the tree, so that you have the original t around when you decide to call insert.
{
treelink ptr= t ;
while ( ptr )
{
if ( ptr-> item == i ) return ptr ;
ptr= ( ptr-> item > i ) ? ptr-> left : ptr-> right ;
}
return insertTreeNode( t, i ) ;
}
A new node is created, but it is not linked to the tree. You never change your left and right pointers.
what you need is to update the link after recursive call, e.g.:
else if (i < t->item) {
t->left = searchInsert(t->left, i);
} ...
But then of course you cannot simply return a pointer to a found item if it's found, otherwise it would break the tree. That's because the statement of your task is NOT recursive: you have to return either root or an existing (inner) node. So you might want to write a recursive function which e.g. always returns a pointer to the root, but also returns a pointer to a found item (through an additional treelink* argument).
Or maybe it would be simpler to split the function into two: search which returns a pointer to an existing node, and insert which returns a pointer to the root. Both of them would be recursive and quite simple.

Build a binary-heap from an array, which method is more efficient and why

I am learning about heaps and i have found two ways of building them from a given array:
I am trying to build up a MAX Heap.
1.Top to down approach
Here i just check for every element if it is at the correct position or not. By using a method called restoreUp, in which every key is compared to its parent key , and if the parent key is smaller than the parent key is moved down.This procedue continues till the parent key is greater.I check it for every key starting at index position 2.
My Code is:
void restoreUp(int arr[],int i)
{
int k=arr[i];
int par=i/2;
while(arr[par]<k)
{
arr[i]=arr[par];
i=par;
par=i/2;
}
arr[i]=k;
}
void buildheap1(int arr[],int size)
{
int i;
for(i=2;i<=size;i++)
restoreUp(arr,i);
}
Bottom up approach
Here i start from the first non leaf node present at index floor(size/2), and call a method restoreDown until node number 1.I compare a key with both its left and right child and then the greater child is moved up.If both children are greater than the key then move the larger of the 2 children up.This procedure stops when both children are smaller than the key.
My Code is:
void restoreDown(int arr[],int i,int size)
{
int left=2*i;
int right=2*i+1;
int num=arr[i];
while(right<=size)
{
if(num>arr[left] && num>arr[right])
{
arr[i]=num;
return;
}
else if(arr[left]>arr[right])
{
arr[i]=arr[left];
i=left;
}
else
{
arr[i]=arr[right];
i=right;
}
left=2*i;
right=2*i+1;
}
if(left==size && arr[left]>num)
{
arr[i]=arr[left];
i=left;
}
arr[i]=num;
}
void buildheap2(int arr[],int size)
{
int i;
for(i=size/2;i>=1;i--)
restoreDown(arr,i,size);
}
Both the methods are working for me.
I just wanted to know which method is more efficient and why?
Generally speaking with modern CPU (having caches). Reading and array backward is usually a very bad idea as it generates a lot of cache misses. Unless (of course) the array was already in cache.
So first approach seems to be better from that point of view.

Resources