C implementation of skew heap - c

I'm trying to implement a skew heap in C, but my code doesn't compile. I'm not that experienced in C and never created any type of heap in C. That is why I don't know how to fix it, I'm hoping someone can point me the right direction. I have been reading articles about the skew heap and this is what I got so far using the algorithms I have found online. Thanks in Advance.
typedef struct node
{
int value;
struct node * root;
struct node * leftchild;
struct node * rightchild;
} Node;
struct skewHeap
{
struct node * root;
};
void skewHeapInit (struct skewHeap * sk)
{
sk->root = 0;
}
void skewHeapAdd (struct skewHeap *sk)
{
struct node *n = (struct node *) malloc(sizeof(struct node));
assert(n != 0);
n->value = 0;
n->leftchild = 0;
n->rightchild = 0;
line 185. s->root = skewHeapMerge(s->root, n);
}
void skewHeapRemoveFirst (struct skewHeap *sk)
{
struct node * n = sk->root;
free(n);
sk->root = skewHeapMerge(n->leftchild, n->rightchild);
}
line 196. struct node * skewHeapMerge(struct node *left, struct node *right)
{
struct node *temp = (struct node *) malloc(sizeof(struct node));
if (left == NULL)
return *right;
if (right == NULL)
return *left;
if (left->value < right-> value)
{
temp = left->leftchild;
left->leftchild = skewHeapMerge(left->rightchild, right);
left->rightchild = temp;
return left;
}
else
{
temp = right->rightchild;
right->rightchild = skewHeapMerge(right->leftchild, left);
right->leftchild = temp;
return right;
}
}
These are the compilations errors I'm getting at the moment:
program.c: In function ‘skewHeapAdd’:
program.c:185: warning: implicit declaration of function ‘skewHeapMerge’
program.c:185: warning: assignment makes pointer from integer without a cast
program.c: In function ‘skewHeapRemoveFirst’:
program.c:191: warning: assignment makes pointer from integer without a cast
program.c: At top level:
program.c:196: error: conflicting types for ‘skewHeapMerge’
program.c:185: note: previous implicit declaration of ‘skewHeapMerge’ was here
program.c: In function ‘skewHeapMerge’:
program.c:202: error: incompatible types when returning type ‘struct node’ but ‘struct node *’ was expected
program.c:205: error: incompatible types when returning type ‘struct node’ but ‘struct node *’ was expected

Regarding the compiler errors,
program.c: In function ‘skewHeapAdd’:
program.c:185: warning: implicit declaration of function ‘skewHeapMerge’
program.c:185: warning: assignment makes pointer from integer without a cast
tells you that no prototype of skewHeapMerge is in scope where skewHeapAdd is defined, hence (the compiler apparently operates in C89 mode, but thankfully warns about it), the compiler supposes an implicit declaration with return type int for skewHeapMerge.
Add a header file with prototypes for all your functions, and #include that in all *.c files where these functions are used or defined, so that the compiler knows the types of the functions.
program.c: In function ‘skewHeapRemoveFirst’:
program.c:191: warning: assignment makes pointer from integer without a cast
that should be the line
sk->root = skewHeapMerge(n->leftchild, n->rightchild);
where sk->root is a struct node*, but due to the implicit declaration of skewHeapMerge, that is assumed to return an int.
program.c: At top level:
program.c:196: error: conflicting types for ‘skewHeapMerge’
program.c:185: note: previous implicit declaration of ‘skewHeapMerge’ was here
here the compiler finds that the definition of skewHeapMerge gives a type conflicting with the one from the implicit declaration.
program.c: In function ‘skewHeapMerge’:
program.c:202: error: incompatible types when returning type ‘struct node’ but ‘struct node *’ was expected
program.c:205: error: incompatible types when returning type ‘struct node’ but ‘struct node *’ was expected
That is for the lines
if (left == NULL)
return *right;
if (right == NULL)
return *left;
where you ought to return right resp. left instead of *right resp. *left (I overlooked that at first).
You have a mistake in skewHeapRemoveFirst
void skewHeapRemoveFirst (struct skewHeap *sk)
{
struct node * n = sk->root;
free(n);
sk->root = skewHeapMerge(n->leftchild, n->rightchild);
}
where you use n after you freed it. You have to exchange the last two lines in that function.
And in skewHeapMerge
struct node * skewHeapMerge(struct node *left, struct node *right)
{
struct node *temp = (struct node *) malloc(sizeof(struct node));
if (left == NULL)
return *right;
if (right == NULL)
return *left;
you are leaking memory. Remove the allocation, since if temp is used at all, you assign either left->leftchild or right->rightchild to it.

Related

Array of Structurer in C

I was just brushing my pointer concepts and it seems its really messed up over time.
I was trying to implement BFS in binary tree.
Pseudo Code :
1) tempNode = root node
2) while tempNode is not null
print data at tempNode
enqueue left and right child
tempNode = dequeue
Here's my code :
#include <stdio.h>
#include <stdlib.h>
#define MAX_Q_SIZE 100
/**
* Using Queue to keep track of next nodes to be visited
*/
struct node
{
int data;
struct node *left;
struct node *right;
};
struct node *createQueue(int *front, int *rear)
{
struct node *queue = (struct node*)malloc(sizeof(struct node) * MAX_Q_SIZE);
*front = *rear = 0;
return queue;
}
void enQueue(struct node *queue, int *rear, struct node *newNode)
{
queue[*rear].data = newNode->data;
queue[*rear].left = newNode->left;
queue[*rear].right = newNode->right;
(*rear)++;
}
struct node *deQueue(struct node *queue, int *front)
{
(*front)++;
return &queue[*front - 1];
}
struct node *newNode(int data)
{
struct node *node = (struct node*)malloc(sizeof(struct node));
node->data = data;
node->left = NULL;
node->right = NULL;
return node;
}
void printBFS(struct node *root)
{
int front,rear;
struct node *queue = createQueue(&front, &rear);
struct node *tempNode = root;
while(tempNode != NULL)
{
printf("%d ",tempNode->data);
if(tempNode->left != NULL)
enQueue(queue,rear,tempNode->left);
if(tempNode->right != NULL)
enQueue(queue,rear,tempNode->right);
tempNode = deQueue(queue,front);
}
}
int main()
{
struct node *root = newNode(1);
root->left = newNode(2);
root->right = newNode(3);
root->left->left = newNode(4);
root->left->right = newNode(5);
printBFS(root);
return 0;
}
I am getting following 4 types of warnings :
BFS2.c: In function ‘printBFS’:
BFS2.c:60:13: warning: passing argument 2 of ‘enQueue’ makes pointer from integer without a cast [enabled by default]
enQueue(queue,rear,tempNode->left);
^
BFS2.c:23:6: note: expected ‘int *’ but argument is of type ‘int’
void enQueue(struct node *queue, int *rear, struct node *newNode)
^
BFS2.c:63:9: warning: passing argument 2 of ‘deQueue’ makes pointer from integer without a cast [enabled by default]
tempNode = deQueue(queue,front);
^
BFS2.c:34:14: note: expected ‘int *’ but argument is of type ‘int’
struct node *deQueue(struct node *queue, int *front)
Can anyone please help me to clarify the doubts as to why I am getting the warnings. I am unable to figure out the problems here. :(
You are passing int variables where int* (pointer to int) is expected. Pass the address of an int variable with & the address of operator. Multiple examples :
enQueue(queue, &rear, tempNode->left);
enQueue(queue, &rear, tempNode->right);
tempNode = deQueue(queue, &front);
As David has pointed out, the program will crash (segmentation fault). You may want to rethink the design of deQueue and/or what should happen if both tempNode->left and tempNode->right are NULL.
Instead of passing front and rear to enQueue() and deQueue(), pass &front and &rear. The & (address-of operator) takes the address of the variable. Since both front and rear are ints, this operator will create the correct result, an int *.
As an aside: don't cast the return value of malloc().
Your immediate pointer problems come from attempting to pass an int as a pointer:
int front,rear;
...
enQueue(queue,&rear,tempNode->left);
// enQueue(queue,rear,tempNode->left);
You have the same issue with deQueue immediately following. However, you have larger issues to deal with. Once you fix the pointer issues you will be faced with a Segmentation fault..
And to not leave you hanging, you simply need to go back and rework your queue implementation, it is a wreck. You will generate a Segmentation fault because your value for front in deQueue grows unchecked until i reaches a value of 100 and you attempt to write beyond the end of your MAX_Q_SIZE block of memory.
If you are brushing up on pointers, then don't torture pointers to try and shoehorn them into array syntax. There is no need for passing struct node *queue and then attempting to find array index syntax that will work:
queue[*rear].right = newNode->right;
when a simple pointer expression will do:
(queue + *rear)->right = newNode->right;
The same applies to:
return (queue + *front - 1); // syntax only your queue logic need fixing
This will make your code much more readable and reduce the chance for error when you pass pointers but then try and make the pointer work with something like:
return &queue[*front - 1];

Error while printing a string in a reverse order using stack

Hello friends this is my first post, I may have done something wrong while posting, sorry for that.
I am trying to print the String in a reverse order using stack. The point where I am trying to get the top value into the character array I am getting error at that part, please help.
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
struct StackNode
{
char data;
struct StackNode* next;
};
struct StackNode* createNode(char data){
struct StackNode* stack=(struct StackNode*)malloc(sizeof(struct StackNode));
stack->data=data;
stack->next=NULL;
return stack;
}
void push(struct StackNode** root,char data)
{
struct StackNode* stack=createNode(data);
stack->next=*root;
*root=stack;
}
char top(struct StackNode** root)
{
return (*root)->data;
}
void pop(struct StackNode** root, char c[],int k)
{
int i;
for(i=0;i<=k;i++)
{
c[i]=top(&root);
*root=(*root)->next;
}
}
void print(struct StackNode* root)
{
while(root!=NULL)
{
printf("%c",root->data);
root=root->next;
printf(" ");
}
printf("\n");
}
int main()
{
struct StackNode* root=NULL;
char c[]="Sherry";
int k=strlen(c);
int i;
for(i=0;i<=k;i++)
{
push(&root,c[i]);
}
pop(&root,c,k);
for(i=0;i<=k;i++)
{
printf("%c",c[i]);
printf(" ");
}
return 0;
}
stackreviseLinkedList.c: In function ‘pop’:
stackreviseLinkedList.c:36:1: warning: passing argument 1 of ‘top’ from incompatible pointer type [enabled by default]
c[i]=top(&root);
^
stackreviseLinkedList.c:26:6: note: expected ‘struct StackNode **’ but argument is of type ‘struct StackNode ***’
char top(struct StackNode** root)
The compiler is clearly pointing out the error here (Disclaimer: Apart from compiler error there could be other issues, I didn't try running the program!)
c[i]=top(&root); is the culprit
should be
c[i]=top(root); // no & required
Look at line# 36
stackreviseLinkedList.c: In function ‘pop’:
stackreviseLinkedList.c:36:1: warning: passing argument 1 of ‘top’ from incompatible pointer type [enabled by default]
c[i]=top(&root);
^
stackreviseLinkedList.c:26:6: note: expected ‘struct StackNode **’ but argument is of type ‘struct StackNode ***’
char top(struct StackNode** root)
The main issue that fails you is:
the line:
c[i]=top(&root);
should be:
c[i]=top(root);
Other issues that don't hurt you right now but are just bad programming:
pop() should handle only one character, should be symmetric to push
you have a memory leak. You should put the StackNode in a temporary pointer, change the root pointer, then release the StackNode
as I commented, indentation. It help to spot coding issues.

Multiple Queues in C

I have a basic queue design, but I want to have multiple queues. The way it looks right now is that I would need another queue.h file and replace head and tail with different names, but I am sure there is a better way?
queue.h *Edited
#include<stdlib.h> // malloc
struct Node {
int data;
struct Node* next;
};
struct Queue {
struct Node *head, *tail;
};
struct Queue *QueueInit() {
//allocate and initialize a queue
struct Queue *thisQueue = malloc(sizeof *thisQueue);
thisQueue->head = NULL;
thisQueue->tail = NULL;
return thisQueue;
}
void push(struct Queue *myQueue, int x) {
struct Node *temp;
temp = malloc(sizeof(struct Node));
temp->data = x;
temp->next = NULL;
if(myQueue->head == NULL && myQueue->tail == NULL) { //empty
myQueue->head = myQueue->tail = temp;
return;
}
myQueue->tail->next = temp;
myQueue->tail = temp;
}
void pop(struct Queue *myQueue) {
struct Node* temp = myQueue->head;
if(myQueue->head == NULL) return; //empty
if(myQueue->head == myQueue->tail) {
myQueue->head = myQueue->tail = NULL;
}
else {
myQueue->head = myQueue->head->next;
}
free(temp);
}
How can I create multiple queues like this?
main.c
int main() {
struct Node iceCreamLine;
struct Node bathroomLine;
iceCreamLine.push(13);
bathroomLine.push(2);
//It looks like I will have to use this syntax then instead?
struct Queue *droneQueue; //(THIS IS LINE 5)
push(&droneQueue,1666);
push(&droneQueue,100);
printf("--> %d",&droneQueue->head->data);
printf("--> %d",&droneQueue->head->next->data);
}
The first printf works, but the second one gives me a segmentation dump. Also here are the warnings
main.c: In function ‘main’:
main.c:6:2: warning: passing argument 1 of ‘push’ from incompatible pointer type [enabled by default]
In file included from queue.c:2:0:
queue.h:21:6: note: expected ‘struct Queue *’ but argument is of type ‘struct Queue **’
main.c:7:2: warning: passing argument 1 of ‘push’ from incompatible pointer type [enabled by default]
In file included from queue.c:2:0:
queue.h:21:6: note: expected ‘struct Queue *’ but argument is of type ‘struct Queue **’
main.c:9:2: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘int *’ [-Wformat]
main.c:10:2: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘int *’ [-Wformat]
struct Queue {
struct Node *head, *tail;
};
Add a QueueInit function to allocate and initialize a queue, returning a pointer to a struct Queue. Pass a pointer to struct Queue to push and pop, and get rid of your global head and tail.

C struct error "pointer to incomplete class type is not allowed"

I'm using Visual Studio 2013 Professional and I've tried it in Eclipse on Kali and Ubuntu as well.
There are more areas where the same two errors occur, though I will only show some of the code here.
I've seen a few questions related to the same problem. Most of the answers seemed to be that the struct was not previously defined though I don't think that applies here. I have also tried to putting all the code into a single source file, this changed nothing.
Visual Studio underlines the errors in code showing error: pointer to incomplete class type is not allowed and when I build the project it shows error C2037: left of 'previous' specifies undefined struct/union 'NODE' These locations are noted in the code below.
Another error is warning C4133: '=' : incompatible types - from 'NODE *' to 'NODE *' and the locations are noted below as well.
So of course my question is how do I fix these errors?
The relevant information from my header file:
list.h
#ifndef LIST_H
#define LIST_H
typedef struct node{
struct NODE *next;
struct NODE *previous;
}NODE;
typedef struct list{
NODE node;
int count;
}LIST;
extern void listDelete(LIST *pList, NODE *pNode);
extern void listFree(LIST *pList);
#endif
The relevant information from my C source file:
list.c
#include "list.h"
#define HEAD node.next /* first node in list */
#define TAIL node.previous /* last node in list */
void listDelete(LIST *pList, NODE *pNode)
{
NODE *mynode;
if (pNode->previous == NULL)
{
pList->HEAD = pNode->next;
}
else
{
pNode->previous->next = pNode->next; // pointer to incomplete class type is not allowed
}
if (pNode->next == NULL)
{
pList->TAIL = pNode->previous;
}
else
{
pNode->next->previous = pNode->previous; // pointer to incomplete class type is not allowed
}
pList->count--;
}
void listFree(LIST *pList)
{
NODE *p1, *p2;
if (pList->count > 0)
{
p1 = pList->HEAD; // warning C4133: '=' : incompatible types - from 'NODE *' to 'NODE *'
while (p1 != NULL)
{
p2 = p1->next; // warning C4133: '=' : incompatible types - from 'NODE *' to 'NODE *'
free((char *)p1);
p1 = p2;
}
pList->count = 0;
pList->HEAD = pList->TAIL = NULL;
}
}
You can't use NODE inside the definition of struct node, because NODE isn't defined yet.
The slow way to do it would be:
struct node {
struct node *next;
struct node *previous;
};
typedef struct node NODE;
so that after you define what struct node is, you can refer to it as NODE.
Change
typedef struct node{
struct NODE *next;
struct NODE *previous;
}NODE;
to
typedef struct node {
struct node *next;
struct node *previous;
} NODE;

initializing error in while loop

Here is a small program I wrote, (I am still writing it), however till this point the program on compilation should not be giving any error as per my understanding.
#include <stdio.h>
#include <stdlib.h>
struct node t1 {
int data;
struct node *next, *prev;
};
struct node *root;
root = NULL;
int main()
{
int i, j, choice, count;
printf("enter choice\n");
scanf("%d", &choice);
count = 0;
while (choice == 1) {
printf("enter a data element");
scanf("%d", &j);
count++;
}
}
void push()
{
}
void pop()
{
}
The error I get is
cc linklist.c
linklist.c:3:16: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘{’ token
linklist.c:8:1: warning: data definition has no type or storage class [enabled by default]
linklist.c:8:1: error: conflicting types for ‘root’
linklist.c:7:14: note: previous declaration of ‘root’ was here
linklist.c:8:8: warning: initialization makes integer from pointer without a cast [enabled by default]
I use gcc and Ubuntu 11.04.
What is the reason that upon compiling the code I get above warning.
struct node *root;
root = NULL;
You can't assign like that outside a function. Drop the root = NULL since it's implicit for objects with static storage (such as global variables).
EDIT
As spotted by Tom Dignan the struct declaration is also wrong:
struct node t1 { ... };
^^
You can't put a statement like root = NULL; at top-level (outside of any function). Do
struct node *root = NULL;
(The = NULL part is actually optional; a global or static pointer is automatically null.)
For one, you have an assignment statement outside of main or a function.
root = NULL;
I have not tried anything else.
struct node t1 {
int data;
struct node *next, *prev;
};
You want to create alias for struct node. It shoud be:
typedef struct node { /* typedef! */
int data;
struct node *next, *prev;
}t1; /* alternative name go here */

Resources