I'm having problems declaring a new heap, empty, with max size "capacity".
Heap struct:
typedef struct {
/* number of elements on vector */
int size;
/* vector max size */
int capacity;
/*vector of pointers for elements*/
element_t** elements;
} heap;
Element_t struct:
typedef struct element_
{
char nameItem[100];
char expirationDate[11];
int qty;
int sellRate;
float priorityVal;
} element_t;
The function that I need to create the heap is declared like that, where the argument capacity is the heap capacity.
heap* new_heap(int capacity){
Function that insert elements in Heap:
int heap_insert(heap *h, element_t* elem)
{
element_t * aux;
int i;
//gilc
if(!h) return 0;
/* if heap is full, dont insert element */
if (h->size >= h->capacity)
return 0;
if (!elem)
return 0;
/* insert element in the end of the heap */
h->size++;
i = h->size;
h->elements[i] = elem;
/* while element has more prioritary than his father, trade them */
while (i != ROOT && bigger_than(h->elements[i], h->elements[FATHER(i)]))
{
aux = h->elements[FATHER(i)];
h->elements[FATHER(i)] = h->elements[i];
h->elements[i] = aux;
i = FATHER(i);
}
return 1;
//Default
return 0;
}
FATHER and ROOT is defined like that (I don't understand what that means, was pre-defined for the project too)
#define FATHER(x) (x/2)
#define ROOT (1)
and bigger_than like this:
int bigger_than(element_t* e1, element_t* e2)
{
if (e1 == NULL || e2 == NULL)
{
return 0;
}
return e1->priorityVal > e2->priorityVal;
}
What malloc calls do I need to use? The function new_heap must allocate all memory necessary for the number of elements specified as argument capacity.
heap *new_heap(int capacity) {
heap *h = malloc(sizeof(heap));
h->size = 0;
h->capacity = capacity;
h->elements = malloc(capacity * sizeof(element_t *));
return h;
}
The first malloc will make enough space for your heap structure. The second is for "vector" (as you called it) of pointers to elements, since these need to be stored in a separate spot in memory (based on your declaration of heap). Together, this allocates all the memory you need for the heap. I'm assuming you'll also have a new_element function that will handle allocating the memory for an individual element for you whenever you want to add something to the heap.
Related
I'm trying to implement stack in C.
What I'm going for:
Design a Stack structure with push and pop functions for the implementation.
Create a Memory structure owns number of block, block size, and stack attributes.
Stack attribute represents memory blocks. Number of block attribute represents the length of the stack. Block size represents the maximum value that each element in the stack can get.
Write an allocate function that takes a size parameter. If the given size is bigger than block size of the Memory, the allocation will be distributed to the different blocks in the stack attribute.
For example, calling allocate(27) updates the stack as:
allocate(27) = [10, 10, 7, 0, 0]
for a Memory with number of block = 5, block size = 10. The remaining of the elements which don't have maximum value can be sealed until the element is flushed. Therefore, the next allocation can start from next element position after 7 given above.
Write a deallocate function that flushes the last used block.
My Work:
First, created the structs:
stack attribute represents memory blocks.
number of block attribute represents the length of the stack.
Block size represents the maximum value that each element in the stack can get.
#include <stdio.h>
#include <stdlib.h> // Provides function For memory locating. allocate & deallocate.
struct Stack {
int top;
};
struct Memory{
int stack;
int number_of_block; // 5
int block_size; // 10
};
Then I have tried to create allocate & push function but they are not working.
int main(){
allocate(30);
return 0;
}
int allocate(int size){
struct Stack* stack = (struct Stack*)malloc(sizeof(struct Stack));
struct Memory* memory = (struct Memory*)malloc(sizeof(struct Memory));
memory->block_size = 10;
stack->top = -1;
memory->stack = (int*)malloc(memory->block_size * sizeof(int));
struct Memory memory = {1, 5, 10};
for(int i = 0; i < 5; i++){
if(size > 10){
size = size - 10; //27 - 10 = 17 -> 17 - 10 = 7
push(stack, 10);
}
}
if(size % 10 != 0){
int size_mod = size % 10; //27 % 10 = 7
push(stack, size_mod);
}
}
void push(struct Stack* stack, struct Memory* memory, int item){
if(stack->top == memory->block_size - 1){
return;
}
memory->stack[++stack->top] = item;
printf("%d ", item);
}
The Memory structure contains a pointer to the first block, as well as the number of blocks and the maximum size of each block. Each block then contains the data and a pointer to the next block, meaning all the blocks are stored in a linked list.
The function allocate returns a pointer to the Memory structure created.
#include <stdio.h>
#include <stdlib.h>
struct Block {
int data;
struct Block *next;
};
struct Memory {
int block_count;
int block_size;
struct Block *head;
};
/* Push a new block onto the stack */
void push(struct Block **head, int data)
{
struct Block *new = malloc(sizeof *new);
if (!new) {
printf("Error: memory allocation failed");
exit(EXIT_FAILURE);
}
new->data = data;
*head = new;
/* `printf` is not needed */
printf("%d\n", data);
}
/* Returns a pointer to the `Memory` structure */
struct Memory *allocate(int size)
{
struct Memory *memory = malloc(sizeof *memory);
if (!memory) {
printf("Error: memory allocation failed");
exit(EXIT_FAILURE);
}
memory->block_count = 5;
memory->block_size = 10;
struct Block *head = NULL;
for (int i = 0; i < memory->block_count; ++i) {
int data = 0;
if (size > 10)
data = 10;
else if (size > 0)
data = size;
size -= data;
push(&head, data);
}
memory->head = head;
return memory;
}
int main(void)
{
struct Memory *memory = allocate(27);
return EXIT_SUCCESS;
}
And as you can see, you don't need to cast malloc, because it returns void *, which is automatically and safely promoted to any other pointer.
I have a program that creates a struct named Stack that holds a pointer to an array of ints and an int that shows the size of this array.
I have functions to:
Initialize the struct with empty values
Push integers to the array (dynamically allocate more memory and write a value to it)
Pop an int from the array
However, when I try to pop the last element by freeing the memory it occupies, my program crashes.
What am I doing wrong here?
Is my process correct?
I realize the problem is probably that I'm trying to free a segment of memory that has not been allocated dynamically, but I just don't see where the issue is exactly.
#include <stdio.h>
#include <stdlib.h>
#include <mem.h>
struct Stack{
int *array;
int size;
};
typedef struct Stack Stack;
void initStack(Stack *stack);
void push(Stack *stack, int value);
int pop(Stack *stack);
int main()
{
Stack firstStack;
initStack(&firstStack);
push(&firstStack, 1222);
pop(&firstStack);
push(&firstStack, 555);
for(int i = 0; i < firstStack.size; ++i){
printf("#%d: %d (%p) ", i , firstStack.array[i], &firstStack.array[i]);
}
return 0;
}
void initStack(Stack *stack){
stack->array = NULL;
stack->size = 0;
}
void push(Stack *stack, int value){
int size = stack->size;
int newSize = size + 1;
stack->array = realloc(stack->array, newSize * sizeof(int));
if(stack->array != NULL){
stack->array[size] = value;
stack->size = stack->size + 1;
}
else{
printf("MALLOC ERROR");
}
}
int pop(Stack *stack){
int lastValue = stack->array[stack->size];
int lastIndex = (stack->size)-1;
int* lastAddress = (stack->array)+lastIndex;
free(lastAddress);
stack->size = (stack->size) - 1 ;
printf("memory free\n");
return lastValue;
}
int* lastAddress = (stack->array)+lastIndex;
free(lastAddress);
is wrong because lastAddress may not be an address allocated via malloc() family by adding lastIndex.
Remove the line
free(lastAddress);
If you want the system to change tha allocated size, you should change the line to
stack->array = realloc(stack->array, ((stack->size) - 1) * sizeof(int));
This is a problem:
int* lastAddress = (stack->array)+lastIndex;
free(lastAddress);
The argument to free must be an address value returned from malloc, calloc, or realloc - you cannot free memory at an arbitrary address, even within a dynamically allocated block.
Can we dynamically allocate memory for structures? Is this a correct procedure to approach a dynamically allocated structures? Please tell me how to malloc() and realloc() a structure.
newnode is of type struct List * but when start indexing it converts to struct List.How this conversion possible?My insert function accepts only (struct List*) Am I wrong somewhere?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct List {
char val[20];
};
void insert(struct List *);
int main(void) {
int i = 0;
int size = 1;
struct List *newnode = (struct List *)malloc(size * sizeof(struct List));
for (i = 0; i < 5; i++) {
if (size <= i) {
size = size + size;
newnode = (struct List *)realloc(newnode, size * sizeof(struct List));
}
scanf("%s", newnode[i].val);
insert(newnode[i]);
}
for (i = 0; i < 5; i++) {
printf("%s\n", newnode[i].val);
}
return 0;
}
void insert(struct List *node) {
printf("%s\n", node->val);
}
The code works except for 3 problems:
You do not test for memory allocation failure. Both malloc() and realloc() will return NULL if memory cannot be allocated: you will get undefined behavior when dereferencing newnode should this happen.
to handle the case of realloc() failure gracefully, you should store the reallocated pointer to a different variable so you can still access the previous array that has not been deallocated and free it.
scanf("%s", newnode[i].val); is a security flaw: you should limit the number of bytes that can be stored to the destination array with
scanf("%19s", newnode[i].val);
you do not test the return value of scanf() to detect invalid or missing input.
insert() does not insert anything.
Here is a modified version with error handling and less confusing names:
#include <stdio.h>
#include <stdlib.h>
struct Item {
char val[20];
};
//void insert(struct Item *);
int main(void) {
int i, j;
int size = 0;
struct Item *array = NULL;
for (i = 0; i < 5; i++) {
if (i >= size) {
int newsize = size ? 1 : size + size;
struct Item *newarray = realloc(array, sizeof(*array) * size);
if (newarray == NULL) {
perror("cannot reallocate the array");
break;
}
size = newsize;
array = newarray;
}
if (scanf("%19s", array[i].val) != 1) {
fprintf(stderr, "missing input\n");
break;
}
//insert(array[i]);
}
for (j = 0; j < i; i++) {
printf("%s\n", array[i].val);
}
free(array);
return 0;
}
Yes, this is fine except that you are assigning the return value to your original array pointer. realloc() returns NULL if it can't resize the memory. You need to assign it to a temporary variable and, if the value is NULL, don't overwrite a.
The main thing you have to watch out for are pointers, which your struct doesn't have. In those cases, the memory pointed to is not part of the allocated array.
I'm not sure why my add function is resulting in numerous memory leaks, invalid reads and invalid writes. Of course, it includes several other functions in it, so I am including them as well. I hate to upload so much of my code, but I'm just not sure where I'm going wrong here.
heap.h header file:
struct Entry {
int key;
char* value;
};
typedef struct Entry Entry;
struct Heap {
int capacity;
int size;
Entry** elements;
};
typedef struct Heap Heap;
heap.c:
void add(Heap* h, int priority, char* val) {
if (h->size >= h->capacity) {
expandCapacity(h);
}
//insert at end of storage array and bubble up
Entry* toAdd = calloc(1, sizeof(Entry*));
toAdd->key = priority;
toAdd->value = calloc(1, sizeof(char*));
toAdd->value = val;
h->elements[h->size]=toAdd;
h->size += 1;
bubbleUp(h, h->size);
}
bubbleUp and swap were given functions, all I had to do was adapt them for this project and translate them to c, so there may have been an issue in doing that though they make sense to me logically.
void bubbleUp(Heap* h, int index) {
if(index <= 0) { return; }
Entry* e = h->elements[index];
Entry* parent = h->elements[(index-1)/2];
int comp = strcmp(e->value, parent->value);
if(comp > 0) {
swap(h, index, parent->key);
bubbleUp(h, parent->key);
}
else {
return;
}
}
void swap(Heap* h, int index1, int index2) {
Entry* tmp = h->elements[index1];
h->elements[index1] = h->elements[index2];
h->elements[index2] = tmp;
}
In
void add(Heap* h, int priority, char* val) {
if (h->size >= h->capacity) {
expandCapacity(h);
}
//insert at end of storage array and bubble up
Entry* toAdd = calloc(1, sizeof(Entry*));
toAdd->key = priority;
toAdd->value = calloc(1, sizeof(char*));
toAdd->value = val;
h->elements[h->size]=toAdd;
h->size += 1;
bubbleUp(h, h->size);
}
you want to allocate memory for one struct Entry, not for its pointer so this would do the job
Entry* toAdd = calloc(1, sizeof(Entry));
You don't need to allocate memory for the pointer toAdd->value because it was already statically allocated by the compiler.
At this point, if you want to copy the pointer just remove this line toAdd->value = calloc(1, sizeof(char*));
Instead, if you want to copy the content of the string you have to use strncpy
This is a memory leak. A block is allocated and then immediately lost. I would just delete the first line.
toAdd->value = calloc(1, sizeof(char*));
toAdd->value = val;
Also, you should allocate sizeof(Entry) here, not size of a pointer.
Entry* toAdd = calloc(1, sizeof(Entry*));
I have an issue freeing my array of struct pointers for a priority queue that I am implementing. I create two dynamic arrays of node pointers with a fixed size from client c program. The array heapMap contains node pointers that map to each created node with a specific ID integer value and the array heap is the heap array that contains the nodes with respect to their current values.
Everything seems to work, however, my pq_free function seems to cause errors or doesn't properly deallocate the arrays. Any help would be appreciated
Structures
typedef struct node_struct{
int ID;
double val;
}NODE;
struct pq_struct {
char heapType;
int max;
int inUse;
NODE ** heap; //BOTH have a specific capacity
NODE **heapMap; //array of pointers to each
};
This is the function I use to allocate memory for the structure.
PQ * pq_create(int capacity, int min_heap){
PQ * newQueue = (PQ*) malloc(sizeof(PQ)); //Allocate memory for a new heap
newQueue->max = capacity;
newQueue->inUse = 0;
int inUse = 1;//1 in use by default, the 0th point in the array is left alone intentionally
//If min_heap == 0, it it is a max heap, any other value is a min heap.
if(min_heap != 0){
newQueue->heapType = 'm';
}else{
newQueue->heapType = 'M';
}
//Allocate memory for heapMap and heap..
newQueue->heap = (NODE**) malloc(sizeof(NODE*)*capacity); //array of nodes, the heap
newQueue->heapMap = (NODE**) malloc(sizeof(NODE*) * capacity);//array of node pointers, the HEAPMAP
int i = 0;
for (i = 0; i < capacity + 1;i++) {
newQueue->heapMap[i] = NULL;
}
//return PQ pointer
return newQueue;
}
This is my pq_free function that doesn't seem to work properly. Thanks for help in advance.
void pq_free(PQ * pq){
//free all nodes
NODE * temp;
NODE ** temp2;
int i;
for (i = 0; i < pq->inUse; i++) {
if (pq->heapMap[i] != NULL) {
temp = pq->heapMap[i];
free(temp);
}
}
//pq->heapMap = NULL;
free(pq->heap);
free(pq->heapMap);
free(pq);
}
As I was once railed on this site for doing this, I feel obligated to do the same to you. You shouldn't cast malloc because it is automatically cast to the assigned data type and can lead to some bad situations.
Other than that how are the individual nodes allocated? What errors specifically are given? I think you are also walking off your heapMap as you allocate capacity but iterate over capacity + 1 elements.