C: insert element in empty heap - c

i'm supposed to write a code, that inserts numbers from stdin into an at first empty max-heap. my code just doesn't get the order of elements right, i found out, that it doesnt even enter the while loop before the third number. Anybody willing to help? Thanks in advance!
int heap_insert(heap* h, int key) {
if (h->size==MAX_HEAP_SIZE){
return(-1);
}
h->size=h->size+1;
int i=h->size-1;
h->array[i]=key;
int parent=(i-1)/2;
while (i>1 && h->array[parent]< key) {
h->array[i]= h->array[parent];
i = parent;
h->array[i]=key;
}
return(0);
}

it doesnt even enter the while loop before the third number
That part can be answered. Your loop won't go until i is 2 or greater...
while (i > 1 && h->array[parent]< key) {
^^^^^
Here's the code that sets i.
h->size = h->size+1;
int i = h->size-1;
That code is easier to understand like so:
int i = h->size;
h->size++;
First time through, i will be 0 (assuming h->size is initialized to 0, you didn't show your heap init code). Second time it will be 1. Third time it will be 2 and then finally the loop can run.
I'm guessing you want i >= 1 in the while loop so it will go on the second call.
As for why it's not working, the primary problem is you're forgetting to change parent in the loop.
/* i and parent initialized */
int i=h->size-1;
...
int parent=(i-1)/2;
while (i>1 && h->array[parent]< key) {
h->array[i]= h->array[parent];
/* i is changed, but where's parent? */
i = parent;
h->array[i]=key;
}
Here's what it should look like. I've changed i, which should only be used in loop indexes, to the more descriptive new.
/* new and parent initialized */
int new = h->size;
...
int parent = (new-1)/2;
while( new != 0 && h->array[parent] < key ) {
h->array[new] = h->array[parent];
h->array[parent] = key;
/* new AND parent changed */
new = parent;
parent = (new-1)/2;
}
Here's the complete code, plus I made the heap size dynamic because fixed size structures are a crutch best avoided.
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int size;
int max_size;
int *array;
} heap;
#define INIT_HEAP_SIZE 4
static heap *heap_init() {
heap *h = calloc(1, sizeof(heap));
h->max_size = INIT_HEAP_SIZE;
h->array = calloc(h->max_size, sizeof(int));
return h;
}
static void heap_destroy(heap *h) {
free(h->array);
free(h);
}
static void heap_grow(heap *h) {
h->max_size *= 2;
h->array = realloc( h->array, h->max_size * sizeof(int) );
}
static void heap_insert(heap* h, int key) {
if (h->size >= h->max_size) {
heap_grow(h);
}
int new = h->size;
h->size++;
h->array[new] = key;
int parent = (new-1)/2;
while( new != 0 && h->array[parent] < key ) {
h->array[new] = h->array[parent];
h->array[parent] = key;
new = parent;
parent = (new-1)/2;
}
return;
}
int main(void) {
heap *h = heap_init();
heap_insert(h, 23);
heap_insert(h, 11);
heap_insert(h, 42);
heap_insert(h, 5);
heap_insert(h, 99);
for( int i = 0; i < h->size; i++ ) {
printf("%d: %d\n", i, h->array[i]);
}
heap_destroy(h);
}

It doesn't enter the while loop before the 3rd number because your i is not greater than 1 until the 3rd number is entered. At 1st number i = 0, then 1 then 2.
For the loop, here's my advice on figuring out the problem: Suppose you enter the values 3, 5, 7. As soon as 5 is entered, you need a swap. 5 should become the new root, and 3 should be a child. (So maxheap property is kept) Then, when 7 is entered, another swap is in order. This time with 5. 7 becomes root, 3 and 5 are children. What does this tell you about the indexes? What happens if we insert 10, 16, 1 as well? More swaps? If you answer these properly the while loop should be easy to solve. (Hint: You need to keep swapping by starting from the child, and move to next parent until everything is in order)

Related

How do I free struct pointers with nested double pointers?

I pasted code at the bottom that allocates lots of pointers but doesn't free any. I have a struct named Node that has fields of type struct Node**. In my main function I have the variable: Node** nodes = malloc(size * typeof(Node*));. I would like to know how to properly deallocate nodes.
typedef struct Node {
size_t id; // identifier of the node
int data; // actual data
size_t num_parents; // actual number of parent nodes
size_t size_parents; // current maximum capacity of array of parent nodes
struct Node** parents; // all nodes that connect from "upstream"
size_t num_children; // actual number of child nodes
size_t size_children; // current maximum capacity of array of children nodes
struct Node** children; // all nodes that connect "downstream"
} Node;
I've pasted the whole code down at the bottom because it is already almost minimal (only things we don't need here are the printing function and find_smallest_value function). VS2019 also gives me two warnings for two lines within the main loop in the main function where I'm allocating each node:
Node** nodes = malloc((num_nodes + 1) * sizeof(Node*));
for (size_t i = 1; i <= num_nodes; i++) {
nodes[i] = malloc(sizeof(Node)); // WARNING Buffer overrun while writing to 'nodes': the writable size is '((num_nodes+1))*sizeof(Node *)' bytes, but '16' bytes might be written.
nodes[i]->id = i; // WARNING Reading invalid data from 'nodes': the readable size is '((num_nodes+1))*sizeof(Node *)' bytes, but '16' bytes may be read.
I don't understand these warnings at all. Finally, you can obtain large input for this program from this website. Just save it to a text file and modify the hardcoded file name in the main function. The program runs fine if I comment out the last lines where I try to deallocate my nodes. My attempt at deallocating crashes the program. I'd greatly appreciate if anyone could explain the correct way to do it.
Explaining the purpose of the code:
The code at the bottom has the following goal. I'm trying to build a directed graph where every vertex has a label and a value. An example of such a graph. The graphs I'm interested in all represent hierarchies. I am to perform two operations on these graphs: I. given a vertex, find the one with smallest value that above it in the hierarchy and print its value; II. given a pair of vertices, swap their places. For example, given vertices 4 and 2 in that figure, the result of operation II would be the same graph but the vertices labelled 2 and 4 would have their labels and data swapped. Given vertex 6, the result of operation I would be "18". I implemented both operations successfully, I believe.
My main function reads from a txt file in order to build the data structure, which I chose to be a multiply linked list. Any input file should be of the following format (this file generates the graph shown in the figure and performs some operations on it):
7 8 9
21 33 33 18 42 22 26
1 2
1 3
2 5
3 5
3 6
4 6
4 7
6 7
P 7
T 4 2
P 7
P 5
T 1 4
P 7
T 4 7
P 2
P 6
First line has three numbers: number of vertices (nodes), number of edges (k, connections) and number of instructions (l, either operation I or II).
Second line is the data in each node. Labels correspond to the index of the node.
The next k lines consist of two node labels: left is a parent node, right is a child node.
The next l lines consist of instructions. P stands for operation I and it's followed by the label of the node. T stands for operation II and it's followed by the two labels of the nodes to be swapped.
The entire pattern can repeat.
The code:
#include<stdlib.h>
#include<stdio.h>
typedef unsigned int uint;
typedef struct Node {
size_t id; // identifier of the node
int data; // actual data
size_t num_parents; // actual number of parent nodes
size_t size_parents; // current maximum capacity of array of parent nodes
struct Node** parents; // all nodes that connect from "upstream"
size_t num_children; // actual number of child nodes
size_t size_children; // current maximum capacity of array of children nodes
struct Node** children; // all nodes that connect "downstream"
} Node;
Node** reallocate_node_array(Node** array, size_t* size) {
Node** new_array = realloc(array, sizeof(Node*) * (*size) * 2);
if (new_array == NULL) {
perror("realloc");
exit(1);
}
*size *= 2;
return new_array;
}
// The intention is to pass `num_children` or `num_parents` as `size` in order to decrease them
void remove_node(Node** array, size_t* size, size_t index) {
for (size_t i = index; i < *size - 1; i++) {
array[i] = array[i + 1];
}
(*size)--; // the decrement to either `num_children` or `num_parents`
}
void remove_parent(Node* node, size_t id) {
for (size_t i = 0; i < node->num_parents; i++) {
if (node->parents[i]->id == id) {
remove_node(node->parents, &node->num_parents, i);
}
}
}
void remove_child(Node* node, size_t id) {
for (size_t i = 0; i < node->num_children; i++) {
if (node->children[i]->id == id) {
remove_node(node->children, &node->num_children, i);
}
}
}
void add_parent(Node* node, Node* parent) {
if (node->num_parents >= node->size_parents) {
node->parents = reallocate_node_array(node->parents, &node->size_parents);
}
node->parents[node->num_parents++] = parent;
}
void add_child(Node* node, Node* child) {
if (node->num_children >= node->size_children) {
node->children = reallocate_node_array(node->children, &node->size_children);
}
node->children[node->num_children++] = child;
}
uint number_of_digits(int n) {
uint d = 0;
do { d++; n /= 10; } while (n != 0);
return d;
}
// return format: "{ parent1.id parent2.id ...} { id data } { child1.id child2.id ...}"
void print_node(Node node) {
printf("{ ");
for (size_t i = 0; i < node.num_parents; i++) {
printf("%zu ", node.parents[i]->id);
}
printf("} [ %zu %d ] { ", node.id, node.data);
for (size_t i = 0; i < node.num_children; i++) {
printf("%zu ", node.children[i]->id);
}
printf("}\n");
}
void switch_nodes(Node* n1, Node* n2, Node** array) {
uint temp_id = n1->id;
uint temp_data = n1->data;
n1->id = n2->id;
n1->data = n2->data;
n2->id = temp_id;
n2->data = temp_data;
Node* temp = array[n1->id];
array[n1->id] = array[n2->id];
array[n2->id] = temp;
}
int find_smallest_valued_parent(Node* node, uint depth) {
// has no parents
if (node->num_parents == 0 || node->parents == NULL) {
if (depth == 0) return -1; // there was no parent on first call (nothing to report)
else return node->data;
}
else {
depth++;
int minimum_value = node->parents[0]->data; // we're guaranteed 1 parent
for (size_t i = 0; i < node->num_parents; i++) {
int next_value = find_smallest_valued_parent(node->parents[i], depth);
if (node->parents[i]->data < next_value) next_value = node->parents[i]->data;
if (next_value < minimum_value) minimum_value = next_value;
}
return minimum_value;
}
}
void free_node_array(Node** array, size_t start, size_t end) {
for (size_t i = start; i < end; i++) {
free(array[i]);
}
free(array);
}
int main() {
char* file_name = "input_feodorv.txt";
FILE* data_file = fopen(file_name, "r");
if (data_file == NULL) {
printf("Error: invalid file %s", file_name);
return 1;
}
for (;;) {
size_t num_nodes, num_relationships, num_instructions;
if (fscanf(data_file, "%zu %zu %zu\n", &num_nodes, &num_relationships, &num_instructions) == EOF)
break;
Node** nodes = malloc((num_nodes + 1) * sizeof(Node*));
for (size_t i = 1; i <= num_nodes; i++) {
nodes[i] = malloc(sizeof(Node)); // WARNING Buffer overrun while writing to 'nodes': the writable size is '((num_nodes+1))*sizeof(Node *)' bytes, but '16' bytes might be written.
nodes[i]->id = i; // WARNING Reading invalid data from 'nodes': the readable size is '((num_nodes+1))*sizeof(Node *)' bytes, but '16' bytes may be read.
fscanf(data_file, "%u ", &nodes[i]->data);
nodes[i]->num_children = 0;
nodes[i]->size_children = 2;
nodes[i]->children = (Node**)malloc(2 * sizeof(Node*));
for (size_t j = 0; j < 2; j++) nodes[i]->children[j] = malloc(sizeof(Node));
nodes[i]->num_parents = 0;
nodes[i]->size_parents = 2;
nodes[i]->parents = (Node**)malloc(2 * sizeof(Node*));
for (size_t j = 0; j < 2; j++) nodes[i]->parents[j] = malloc(sizeof(Node));
}
for (size_t i = 0; i < num_relationships; i++) {
size_t parent_id, child_id;
fscanf(data_file, "%zu %zu\n", &parent_id, &child_id);
add_child(nodes[parent_id], nodes[child_id]);
add_parent(nodes[child_id], nodes[parent_id]);
}
for (size_t i = 0; i < num_instructions; i++) {
char instruction;
fscanf(data_file, "%c ", &instruction);
if (instruction == 'P') {
size_t id;
fscanf(data_file, "%zu\n", &id);
int minimum_value = find_smallest_valued_parent(nodes[id], 0);
if (minimum_value == -1) printf("*\n");
else printf("%u\n", minimum_value);
}
else {
size_t n1_id, n2_id;
fscanf(data_file, "%zu %zu\n", &n1_id, &n2_id);
switch_nodes(nodes[n1_id], nodes[n2_id], nodes);
}
}
/**/
for (size_t i = 1; i <= num_nodes; i++) {
free_node_array(nodes[i]->parents, 0, nodes[i]->size_parents);
free_node_array(nodes[i]->children, 0, nodes[i]->size_children);
}
free_node_array(nodes, 0, num_nodes);
/**/
}
}
There is a memory leak in your code. In the main() function, you are doing:
nodes[i]->children = (Node**)malloc(2 * sizeof(Node*));
for (size_t j = 0; j < 2; j++) nodes[i]->children[j] = malloc(sizeof(Node));
and
nodes[i]->parents = (Node**)malloc(2 * sizeof(Node*));
for (size_t j = 0; j < 2; j++) nodes[i]->parents[j] = malloc(sizeof(Node));
that mean, allocating memory to nodes[i]->children[j] and nodes[i]->parents[j] pointers.
In add_child() and add_parent() function, you are making them point to some other node resulting in loosing there allocated memory reference:
void add_parent(Node* node, Node* parent) {
.....
node->parents[node->num_parents++] = parent;
}
void add_child(Node* node, Node* child) {
.....
node->children[node->num_children++] = child;
}
You actually don't need to allocate memory to nodes[i]->children[j] and nodes[i]->parents[j] pointers in main() because these pointer are suppose to point to the existing nodes of the graph and you are already allocating memory to those nodes here in main():
nodes[i] = malloc(sizeof(Node));
nodes[i] is an element of array of all the nodes of the given graph and childrens and parents pointer should point to these nodes only.
Now coming to freeing these pointers:
The way you are freeing the nodes of graph is not correct. Look at free_node_array() function:
void free_node_array(Node** array, size_t start, size_t end) {
for (size_t i = start; i < end; i++) {
free(array[i]);
}
free(array);
}
and you are calling it in this way:
for (size_t i = 1; i <= num_nodes; i++) {
free_node_array(nodes[i]->parents, 0, nodes[i]->size_parents);
free_node_array(nodes[i]->children, 0, nodes[i]->size_children);
}
That mean, you are freeing the pointers pointed by array of pointers nodes[i]->parents and nodes[i]->children. The members of nodes[i]->parents and nodes[i]->children are pointers which are pointing to elements of nodes array. It is perfectly possible that a node can be a child 1 or more parents and a parent node can have more than 1 child. Now assume case where a child node is pointed by 2 parent nodes, say n1 and n2. When you call free_node_array() function and pass the first parent (n1), it will end you freeing that child node and when free_node_array() function is called to free the second parent (n2), it will try to free the node which is already freed while freeing n1.
So, this way of freeing the memory is not correct. The correct way to free the memory is, simply, free the elements of nodes array because it's the array which will contain all the nodes of given graph and parents and children pointers are supposed to point to these nodes only. No need to traverse the hierarchy of parent and child nodes. To free the graph appropriately, you should do:
Traverse through the nodes array and for each element of array:
Free the array of parents pointer (free (nodes[i]->parents).
Free the array of children pointer (free (nodes[i]->children).
Free that element of nodes array (free (nodes[i]).
Once, this is done then free the nodes array - free (nodes).

A function in C runs for a set of values but gives Segmentation Fault: 11 for another

I am trying to find unique non-zero intersection between two sets. I have written a program which works for some set of arrays but gives segmentation fault for some. I have been trying to figure out why but have failed, any help will be greatly valued. The thing is the functions defined (NoRep and ComEle) are working fine but are unable to return the value to the assigned pointer in the case when Seg Fault is shown. Below is the code:
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
int* ComEle(int ar_1[], int size_ar1, int ar_2[], int size_ar2);
int* NoRep(int a[], int l1);
int main ()
{
// Case 1: Gives segmentation fault
int A[10] = {1,1,0,2,2,0,1,1,1,0};
int B[10] = {1,1,1,1,0,1,1,0,4,0};
int *C = ComEle(A,10,B,10); printf("check complete\n");
// //Case 2: Does not give segmentation fault
// int A[4] = {2,3,4,5};
// int B[4] = {1,2,3,4};
// int *C = ComEle(A,4,B,4); printf("check complete\n");
}
//---------------- Local Functions --------------------//
int* ComEle(int ar_1[], int size_ar1, int ar_2[], int size_ar2) {
// sort of intersection of two arrays but only for nonzero elements.
int i=0, j=0, cnt1 = 0;
int temp1 = size_ar1+size_ar2;
int CE1[temp1]; for(i=0;i<temp1;i++) {CE1[i] = 0;}
/* Size of CE1 is knowingly made big enough to accommodate repeating
common elements which can expand the size of resultant array to
values bigger than those for the individual arrays themselves! */
for(i=0;i<size_ar1;i++) {
j = 0;
while(j<size_ar2) {
if(ar_1[i]==ar_2[j] && ar_1[i]!=0) {
CE1[cnt1] = ar_1[i];
cnt1++;
}
j++;
}
}
// Have to remove repeating elements.
int *CE = NoRep(CE1, cnt1);
for(i=0;i<(CE[0]+1);i++) {printf("CE:\t%d\n", CE[i]);}
printf("ComEle: %p\n",CE);
return(CE);
}
int* NoRep(int a[], int l1) {
int cnt = 0, i = 0, j =0;
int *NR; NR = (int*)calloc((l1), sizeof(int));
//int NR[l1]; for(i=0;i<l1;i++) {NR[i] = 0;}
for(i=0;i<l1;i++) {
j = 0;
while(j<i) {
if(a[i]==a[j]) {break;}
j++;
}
if(j == i) {
cnt++;
NR[cnt] = a[i];
}
}
NR[0] = cnt; // First element: # of relevant elements.
printf("NoRep: %p\n",NR);
return(NR);
}
Thanks again for your help!
Take a look at this code:
int temp1 = size_ar1+size_ar2;
int CE1[temp1]; for(i=0;i<temp1;i++) {CE1[i] = 0;}
/* Size of CE1 is knowingly made big enough to accommodate repeating
common elements which can expand the size of resultant array to
values bigger than those for the individual arrays themselves! */
for(i=0;i<size_ar1;i++) {
j = 0;
while(j<size_ar2) {
if(ar_1[i]==ar_2[j] && ar_1[i]!=0) {
CE1[cnt1] = ar_1[i];
cnt1++;
}
j++;
}
}
Here you have nested loops, i.e. a for-loop with a while-loop inside. So - in worst case - how many times can cnt1 be incremented?
The answer is size_ar1 * size_ar2
But your code only reserve size_ar1 + size_ar2 element for CE1. So you may end up writing outside the array.
You can see this very easy by printing cnt1 inside the loop.
In other words - your CE1 is too small. It should be:
int temp1 = size_ar1*size_ar2; // NOTICE: * instead of +
int CE1[temp1]; for(i=0;i<temp1;i++) {CE1[i] = 0;}
But be careful here - if the input arrays are big, the VLA gets huge and you may run in to stack overflow. Consider dynamic memory allocation instead of an array.
Besides the accepted answer: I have been missing a break statement in the while loop in ComEle function. It was not giving me the expected value of cnt1. The following will be the correct way to do it:
for(i=0;i<size_ar1;i++) {
j = 0;
while(j<size_ar2) {
if(ar_1[i]==ar_2[j] && ar_1[i]!=0) {
CE1[cnt1] = ar_1[i];
cnt1++;
break;
}
j++;
}
}
This will also do away with the requirement for a bigger array or dynamic allocation as suggested (and rightly so) by #4386427

Recovering elements of large array with multiple index ranges

This is a tricky problem that I have been thinking about for a long time and have yet to see a satisfactory answer anywhere. Lets say I have a large int array of size 10000. I can simply declare it in the following manner:
int main()
{
int foo[10000];
int i;
int n;
n = sizeof(foo) / sizeof(int);
for (i = 0; i < n; i++)
{
printf("Index %d is %d\n",i,foo[i] );
}
return 0;
}
It is pretty clear that each index in the array will hold a random assortment of numbers before I formally initialize them:
Index 0 is 0
Index 1 is 0
Index 2 is 0
Index 3 is 0
.
.
.
Index 6087 is 0
Index 6088 is 1377050464
Index 6089 is 32767
Index 6090 is 1680893034
.
.
.
Index 9996 is 0
Index 9997 is 0
Index 9998 is 0
Index 9999 is 0
Then lets say that I initialize select index ranges of my array with values that hold a specific value for the program as a whole and must be preserved, with the goal of passing in those values for subsequent operation to some function:
//Call this block 1
foo[0] = 0;
foo[1] = 7;
foo[2] = 99;
foo[3] = 0;
//Call this block 2
foo[9996] = 0;
foo[9997] = 444;
foo[9998] = 2;
foo[9999] = 0;
for (i = 0; i < (What goes here?); i++)
{
//I must pass in only those values initialized to select indices of foo[] (Blocks 1 and 2 uncorrupted)
//How to recover those values to pass into foo_func()?
foo_func(foo[]);
}
Some of those values that I initialized foo[] with overlap with pre-existing values in the array before formally initializing the array myself. How can I pass in just the indices of the array elements that I initialized, given that there are multiple index ranges? I just can't figure this out. Thanks for any and all help!
EDIT:
I should also mention that the array itself will be read from a .txt file. I just showed the initialization in the code for illustrative purposes.
There's a number of ways you can quickly zero out the memory in the array, either while initializing or after.
For an array on the stack, initialize it with zeros. {0} is shorthand for that.
int foo[10000] = {0};
For an array on the heap, use calloc to allocate memory and initialize it with 0's.
int *foo = calloc(10000, sizeof(int));
If the array already exists, use memset to quickly overwrite all the array's memory with zeros.
memset(foo, 0, sizeof(int) * 10000);
Now all elements are zero. You can set individual elements to whatever you like one by one. For example...
int main() {
int foo[10] = {0};
foo[1] = 7;
foo[2] = 99;
foo[7] = 444;
foo[8] = 2;
for( int i = 0; i < 10; i++ ) {
printf("%d - %d\n", i, foo[i]);
}
}
That will print...
0 - 0
1 - 7
2 - 99
3 - 0
4 - 0
5 - 0
6 - 0
7 - 444
8 - 2
9 - 0
As a side note, using only a few elements of a large array is a waste of memory. Instead, use a hash table, or if you need ordering, some type of tree. These can be difficult to implement correctly, but a library such as GLib can provide you with good implementations.
Introduction
I'm making a strong assumption on your problem, and it is sparsness (a majority of the elements in your array will remain zero).
Under this assumption I would build the array as a list. I'm including a sample code, that it is not complete and it is not intended to
be---you should do your own homework :)
The core object is a struct with a pointer to a begin element and the size:
typedef struct vector {
size_t size;
vector_element_t * begin;
} vector_t;
each element of the vector has its own index and value and a pointer to the next element in a list:
typedef struct vector_element vector_element_t;
struct vector_element {
int value;
size_t index;
vector_element_t *next;
};
on this basis we can build a dynamical vector as a list, by dropping a constraint on the ordering (it is not needed, you can modify this code
to maintain the ordering), using some simple custom methods:
vector_t * vector_init(); // Initialize an empty array
void vector_destroy(vector_t* v); // Destroy the content and the array itself
int vector_get(vector_t *v, size_t index); // Get an element from the array, by searching the index
size_t vector_set(vector_t *v, size_t index, int value); // Set an element at the index
void vector_delete(vector_t *v, size_t index); // Delete an element from the vector
void vector_each(vector_t *v, int(*f)(size_t index, int value)); // Executes a callback for each element of the list
// This last function may be the response to your question
Test it online
The main example
This is a main that uses all this methods and prints in console:
int callback(size_t index, int value) {
printf("Vector[%lu] = %d\n", index, value);
return value;
}
int main() {
vector_t * vec = vector_init();
vector_set(vec, 10, 5);
vector_set(vec, 23, 9);
vector_set(vec, 1000, 3);
printf("vector_get(vec, %d) = %d\n", 1000, vector_get(vec, 1000)); // This should print 3
printf("vector_get(vec, %d) = %d\n", 1, vector_get(vec, 1)); // this should print 0
printf("size(vec) = %lu\n", vec->size); // this should print 3 (the size of initialized elements)
vector_each(vec, callback); // Calling the callback on each element of the
// array that is initialized, as you asked.
vector_delete(vec, 23);
printf("size(vec) = %lu\n", vec->size);
vector_each(vec, callback); // Calling the callback on each element of the array
vector_destroy(vec);
return 0;
}
And the output:
vector_get(vec, 1000) = 3
vector_get(vec, 1) = 0
size(vec) = 3
Vector[10] = 5
Vector[23] = 9
Vector[1000] = 3
size(vec) = 3
Vector[10] = 5
Vector[1000] = 3
The callback with the function vector_each is something you really should look at.
Implementations
I'm giving you some trivial implementations for the functions in the introdution. They are not complete,
and some checks on pointers should be introduced. I'm leaving that to you. As it is, this code is not for production and under some circumstances can also overflow.
The particular part is the search of a specific element in the vector. Every time you tranverse the list,
and this is convenient only and only if you have sparsity (the majority of your index will always return zero).
In this implementation, if you access an index that is not enlisted, you get as a result 0. If you don't want this
you should define an error callback.
Initialization and destruction
When we initialize, we allocate the memory for our vector, but with no elements inside, thus begin points to NULL. When we destroy the vector we have not only to free the vector, but also each element contained.
vector_t * vector_init() {
vector_t * v = (vector_t*)malloc(sizeof(vector_t));
if (v) {
v->begin = NULL;
v->size = 0;
return v;
}
return NULL;
}
void vector_destroy(vector_t *v) {
if (v) {
vector_element_t * curr = v->begin;
if (curr) {
vector_element_t * next = curr->next;
while (next) {
curr = curr->next;
next = next->next;
if (curr)
free(curr);
}
if (next)
free(next);
}
free(v);
}
}
The get and set methods
In get you can see how the list works (and the same concept
is used also in set and delete): we start from the begin, and
we cross the list until we reach an element with an index equal
to the one requested. If we cannot find it we simply return 0.
If we need to "raise some sort of signal" when the value is
not found, it is easy to implement an "error callback".
As long as sparsness holds, searching in the whole array for an index is a good compromise in terms of memory requirements, and efficiency may be not an issue.
int vector_get(vector_t *v, size_t index) {
vector_element_t * el = v->begin;
while (el != NULL) {
if (el->index == index)
return el->value;
el = el->next;
}
return 0;
}
// Gosh, this set function is really a mess... I hope you can understand it...
// -.-'
size_t vector_set(vector_t *v, size_t index, int value) {
vector_element_t * el = v->begin;
// Case 1: Initialize the first element of the array
if (el == NULL) {
el = (vector_element_t *)malloc(sizeof(vector_element_t));
if (el != NULL) {
v->begin = el;
v->size += 1;
el->index = index;
el->value = value;
el->next = NULL;
return v->size;
} else {
return 0;
}
}
// Case 2: Search for the element in the array
while (el != NULL) {
if (el->index == index) {
el->value = value;
return v->size;
}
// Case 3: if there is no element with that index creates a new element
if (el->next == NULL) {
el->next = (vector_element_t *)malloc(sizeof(vector_element_t));
if (el->next != NULL) {
v->size += 1;
el->next->index = index;
el->next->value = value;
el->next->next = NULL;
return v->size;
}
return 0;
}
el = el->next;
}
}
Deleting an element
With this approach it is possible to delete an element quite easily, connecting
curr->next to curr->next->next. We must though free the previous curr->next...
void vector_delete(vector_t * v, size_t index) {
vector_element_t *curr = v->begin;
vector_element_t *next = curr->next;
while (next != NULL) {
if (next->index == index) {
curr->next = next->next;
free(next);
return;
} else {
curr = next;
next = next->next;
}
}
}
An iteration function
I think this is the answer to the last part of your question,
instead passing a sequence of indexes, you pass a callback to the vector.
The callback gets and sets value in a specific index. If you want to
operate only on some specific indexes, you may include a check in the
callback itself. If you need to pass more data to the callback, check
the very last section.
void vector_each(vector_t * v, int (*f)(size_t index, int value)) {
vector_element_t *el = v->begin;
while (el) {
el->value = f(el->index, el->value);
el = el->next;
}
}
Error callback
You may want to raise some out of bounds error or something else. One solution is to enrich your list with function pointer that represent a callback that should be called when your user sk for an undefined element:
typedef struct vector {
size_t size;
vector_element_t *begin;
void (*error_undefined)(vector *v, size_t index);
} vector_t
and maybe at the end of your vector_get function you may want to do something like:
int vector_get(vector_t *v, size_t index) {
// [ . . .]
// you know at index the element is undefined:
if (v->error_undefined)
v->error_undefined(v, index);
else {
// Do something to clean up the user mess... or simply
return 0;
}
}
usually it is nice to add also an helper function to set the callback...
Passing user data to "each" callback
If you want to pass more data to the user callback, you may add a void* as last argument:
void vector_each(vector_t * v, void * user_data, int (*f)(size_t index, int value, void * user_data));
void vector_each(vector_t * v, void * user_data, int (*f)(size_t index, int value, void * user_data)) {
[...]
el->value = f(el->index, el->value, user_data);
[...]
}
if the user do not need it, he can pass a wonderful NULL.

Max in array and its frequency

How do you write a function that finds max value in an array as well as the number of times the value appears in the array?
We have to use recursion to solve this problem.
So far i am thinking it should be something like this:
int findMax(int[] a, int head, int last)
{
int max = 0;
if (head == last) {
return a[head];
}
else if (a[head] < a[last]) {
count ++;
return findMax(a, head + 1, last);
}
}
i am not sure if this will return the absolute highest value though, and im not exactly sure how to change what i have
Setting the initial value of max to INT_MIN solves a number of issues. #Rerito
But the approach OP uses iterates through each member of the array and incurs a recursive call for each element. So if the array had 1000 int there would be about 1000 nested calls.
A divide and conquer approach:
If the array length is 0 or 1, handle it. Else find the max answer from the 1st and second halves. Combine the results as appropriate. By dividing by 2, the stack depth usage for a 1000 element array will not exceed 10 nested calls.
Note: In either approach, the number of calls is the same. The difference lies in the maximum degree of nesting. Using recursion where a simple for() loop would suffice is questionable. To conquer a more complex assessment is recursion's strength, hence this approach.
To find the max and its frequency using O(log2(length)) stack depth usage:
#include <stddef.h>
typedef struct {
int value;
size_t frequency; // `size_t` better to use that `int` for large arrays.
} value_freq;
value_freq findMax(const int *a, size_t length) {
value_freq vf;
if (length <= 1) {
if (length == 0) {
vf.value = INT_MIN; // Degenerate value if the array was size 0.
vf.frequency = 0;
} else {
vf.value = *a;
vf.frequency = 1;
}
} else {
size_t length1sthalf = length / 2;
vf = findMax(a, length1sthalf);
value_freq vf1 = findMax(&a[length1sthalf], length - length1sthalf);
if (vf1.value > vf.value)
return vf1;
if (vf.value == vf1.value)
vf.frequency += vf1.frequency;
}
return vf;
}
Your are not thaaaat far.
In order to save the frequency and the max you can keep a pointer to a structure, then just pass the pointer to the start of your array, the length you want to go through, and a pointer to this struct.
Keep in mind that you should use INT_MIN in limits.h as your initial max (see reset(maxfreq *) in the code below), as int can carry negative values.
The following code does the job recursively:
#include <limits.h>
typedef struct {
int max;
int freq;
} maxfreq;
void reset(maxfreq *mfreq){
mfreq->max = INT_MIN;
mfreq->freq = 0;
}
void findMax(int* a, int length, maxfreq *mfreq){
if(length>0){
if(*a == mfreq->max)
mfreq->freq++;
else if(*a > mfreq->max){
mfreq->freq = 1;
mfreq->max = *a;
}
findMax(a+1, length - 1, mfreq);
}
}
A call to findMax will recall itself as many times as the initial length plus one, each time incrementing the provided pointer and processing the corresponding element, so this is basically just going through all of the elements in a once, and no weird splitting.
this works fine with me :
#include <stdio.h>
#include <string.h>
// define a struct that contains the (max, freq) information
struct arrInfo
{
int max;
int count;
};
struct arrInfo maxArr(int * arr, int max, int size, int count)
{
int maxF;
struct arrInfo myArr;
if(size == 0) // to return from recursion we check the size left
{
myArr.max = max; // prepare the struct to output
myArr.count = count;
return(myArr);
}
if(*arr > max) // new maximum found
{
maxF = *arr; // update the max
count = 1; // initialize the frequency
}
else if (*arr == max) // same max encountered another time
{
maxF = max; // keep track of same max
count ++; // increase frequency
}
else // nothing changes
maxF = max; // keep track of max
arr++; // move the pointer to next element
size --; // decrease size by 1
return(maxArr(arr, maxF, size, count)); // recursion
}
int main()
{
struct arrInfo info; // return of the recursive function
// define an array
int arr[] = {8, 4, 8, 3, 7};
info = maxArr(arr, 0, 5, 1); // call with max=0 size=5 freq=1
printf("max = %d count = %d\n", info.max, info.count);
return 0;
}
when ran, it outputs :
max = 8 count = 3
Notice
In my code example I assumed the numbers to be positive (initializing max to 0), I don't know your requirements but you can elaborate.
The reqirements in your assignment are at least questionable. Just for reference, here is how this should be done in real code (to solve your assignment, refer to the other answers):
int findMax(int length, int* array, int* maxCount) {
int trash;
if(!maxCount) maxCount = &trash; //make sure we ignore it when a NULL pointer is passed in
*maxCount = 0;
int result = INT_MIN;
for(int i = 0; i < length; i++) {
if(array[i] > result) {
*maxCount = 1;
result = array[i];
} else if(array[i] == result) {
(*maxCount)++;
}
}
return result;
}
Always do things as straight forward as you can.

replace/remove cycle in graph

I'm trying to replace cycle in the graph to a group of the vertexes (remove this cycle and put there once vertex with maximum number)
struct group {
int master; // representative of cycle
};
struct vertex {
int *to; // neighbor list
int nb; // how many neighbor
int p; // parent
short v; // was visited? 0 = false, 1 = true
struct group *cycle; // is part of cycle? NULL = no, else pointer to group
};
I'm running dfs on each vertex
void searchCycles() {
int i;
for (i = 0; i < MAX_VER; i += 1)
if (ver[i].v == 0 && ver[i].nb > 0)
dfs(i);
}
dfs:
void dfs(int v) {
ver[v].v = 1;
int i;
for (i = 0; i < ver[v].nb; i += 1) {
ver[ver[v].to[i]].p = v;
if (ver[ver[v].to[i]].v == 0)
dfs(ver[v].to[i]);
else
// cycle found
replaceCycle(ver[v].to[i]);
}
}
and replace function shout print what vertexes are in cycle
void replaceCycle(int v) {
struct group *g = &gr[usedGroup++];
g->master = -1;
printf("\nCYKL: %d ", v);
int p = ver[v].p;
while (p != v) {
printf("%d(%d) ", p, v);
p = ver[p].p;
}
printf("\n");
}
Generally it's works, but sometimes it get a infinity loop. I tried to debug it and if there are two or more cycles, parents (p in vertex struct) are lost, it's means it works fine but there is wrong number. I'm learning C and algorithms, so I don't know a lot of it.
It's not a homework, it's a spoj problem
Once you replace a cycle, restart your dfs.
Basically, the visited flag might be set for your first cycle, but you'd want that cleared to test your second cycle. (And third, and fourth, etc.)

Resources