What mistake am I making in the function definition(C) - c

So I have this code thats supposed to do this
// REQUIRES: n >= 1. Elements a[0] ... a[n-1] exist.
// PROMISES
// If n == 1, returns 1.
// Returns 1 if all of a[0] <= a[1] ... a[n-2] <= a[n-1] are true.
// Otherwise, returns 0.
#include <assert.h>
#include "array-utils4F.h"
#define UNIT_TESTS 1
int is_sorted(const int *a, int n)
{
assert (n >= 1);
if (n == 1)
return 1;
int k ;
for (k = 1; k < n ; k++) {
if (a[k-1] > a[k])
return 0;
return 1;
}
}
int max_el(const int *a, int n)
{
assert(n >= 1);
int result = 0, i;
for (i = 0; i < n; i++)
if (a[i] > result)
result = a[i];
return result;
}
#ifdef UNIT_TESTS
#include <stdio.h>
#define COUNT(x) (sizeof(x)/sizeof(x[0]))
void test_is_sorted(const char *tag, const int *a, int n, int expected_rv);
void test_max_el(const char *tag, const int *a, int n, int expected_rv);
int main(void)
{
int test_01[] = { 10, 20, 30, 40, 50 };
int test_02[] = { 10, 10, 10, 10 };
int test_03[] = { 10, 20, 30, 40, 35 };
int test_04[] = { 10, 20, 30, 25, 40 };
int test_05[] = { 10, 5, 15, 25 };
test_is_sorted("test_01", test_01, COUNT(test_01), 1);
test_is_sorted("test_02", test_02, COUNT(test_02), 1);
test_is_sorted("test_03", test_03, COUNT(test_03), 0);
test_is_sorted("test_04", test_04, COUNT(test_04), 0);
test_is_sorted("test_05", test_05, COUNT(test_05), 0);
fputc('\n', stdout);
int test_06[] = { 100, 1, 2, 3 };
int test_07[] = { 1, 2, 100, 3 };
int test_08[] = { 1, 2, 3, 100 };
int test_09[] = { -1, -2, -3, -4 };
int test_10[] = { -8, -7, -6, -7, -8 };
test_max_el("test_06", test_06, COUNT(test_06), 100);
test_max_el("test_07", test_07, COUNT(test_07), 100);
test_max_el("test_08", test_08, COUNT(test_08), 100);
test_max_el("test_09", test_09, COUNT(test_09), -1);
test_max_el("test_10", test_10, COUNT(test_10), -6);
fputc('\n', stdout);
return 0;
}
void test_is_sorted(const char *tag, const int *a, int n, int expected_rv)
{
printf("Testing is_sorted for case with tag \"%s\":", tag);
if (expected_rv == is_sorted(a, n))
printf(" Pass.\n");
else
printf(" FAIL!\n");
}
void test_max_el(const char *tag, const int *a, int n, int expected_rv)
{
printf("Testing max_el for case with tag \"%s\":", tag);
if (expected_rv == max_el(a, n))
printf(" Pass.\n");
else
printf(" FAIL!\n");
}
#endif // #ifdef UNIT_TESTS
but when I test it it doesnt work, what can I change.
when i use this test int test_04[] = { 10, 20, 30, 35, 40 };
it returns 0. what am i doing wrong?I have added my entire code but the function still shows some defect, idk why it is doing this any help would be appreciated.

For now, when you did that if (a[0] <= a[k+ 1]), you just check if all value in the array are greater or equal than the first element of your array. You must check if an element is greater or equal than the previous element and if it's lesser or equal than the next element.
int is_sorted(const int *a, int n)
{
assert (n >= 1);
int k;
for (k = 1 ; k < n ; k++) {
if (a[k-1] > a[k])
return 0;
}
return 1;
}
Instead of use a variable result, you can directly return 0 when you know that the array isn't sorted.

Without added local variables
int is_sorted(const int *a, int n) {
assert (n >= 1);
while (--n)
if (a[n] < a[n-1])
return 0;
return 1;
}

Try this one
int is_sorted(const int *a, int n)
{
assert (n >= 1);
if (n == 1)
return 1;
int k, result=1;
for (k = 0; k < n - 1; k++) {
if (a[k] > a[k+ 1])
{
result = 0;
break;
}
}
return result;
}

Related

Finding Median of an Array

I am trying to write a C program to find the median of an array, but the task requires to not sort the array. The current code I have works, but fails when there is a repeated number. I am struggling to find a way to account for this case. Any help would be appreciated.
#include <stdio.h>
#include <stdlib.h>
int median_finder(int size, int* data) {
int n1, n2;
int count = 0;
for (int t = 0; t < size; t ++) {
int piv = data[t];
int higher = 0;
int lower = 0;
int median;
if (size % 2 != 0) {
for (int j = 0; j < size; j++) {
if (piv < data[j]) {
higher++;
} else if (piv > data[j]) {
lower++;
}
}
if (higher != 0 && lower == higher) {
printf("MEDIAN: %d\n", piv);
return 0;
}
} else {
//int num = 0;
for (int j = 0; j < size; j++) {
if (piv < data[j]) {
higher++;
} else if (piv > data[j]) {
lower++;
}
}
if (higher != 0 && (lower == size/2 || higher == size/2)) {
count++;
if (count == 1) {
n1 = piv;
} if (count == 2) {
n2 = piv;
}
}
} if (count == 2) {
if (n1 > n2) {
median = n2;
} else {
median = n1;
}
printf("Median: %d\n", median);
return 0;
}
}
}
int main(int argc, char** argv) {
int size = atoi(argv[1]);
argv++;
argv++;
int data[size];
for (int i = 0; i < size; i++) {
data[i] = atoi(argv[i]);
}
median_finder(size, data);
}
The median for an unsorted array with possible duplicate values a of length n is the element with the value a[i] where half of the remaining elements (n-1)/2 (rounded down) are between less than (lt) or less than and equal (lt + eq) to a[i]:
#include <assert.h>
#include <stdio.h>
int median(size_t n, int *a) {
assert(n > 0);
for(size_t i = 0; i < n; i++) {
size_t lt = 0;
size_t eq = 0;
for(size_t j = 0; j < n; j++) {
if(i == j) continue;
if(a[j] < a[i]) lt++;
else if(a[j] == a[i]) eq++;
}
if((n-1)/2 >= lt && (n-1)/2 <= lt + eq)
return a[i];
}
assert(!"BUG");
}
// tap-like
void test(size_t test, int got, int expected) {
printf("%sok %zu\n", got == expected ? "" : "not ", test);
if(got != expected) {
printf(" --\n"
" got: %d\n"
" expected: %d\n"
" ...\n", got, expected);
}
}
int main(void) {
struct {
size_t n;
int *a;
} tests[] = {
{1, (int []) {0}},
{2, (int []) {0, 1}},
{3, (int []) {-1, 0, 1}},
{4, (int []) {-1, 0, 0, 1}},
};
for(int i = 0; i < sizeof tests / sizeof *tests; i++) {
test(i+1, median(tests[i].n, tests[i].a), 0);
}
}

Returning value from a function with 'NULL' as parameter

I've got an assignment in which functions return MIN and MAX value of elements in an array. But I also have to return value from function with 'NULL' parameter and I don't understand it.
My code:
int array_min(const int [], const int);
int array_max(const int [], const int);
int main() {
int input_arr[] = {2,3,4,5,6};
printf("%d\t", array_min(input_arr, 5));
// : 2
printf("%d\t", array_max(input_arr, 5));
// : 6
printf("%d\t", array_max(NULL, 5));
// : -1
return 0;
}
int array_min(const int input_arr[], const int arr_size) {
int a, b = arr_size, min = input_arr[0];
for(a = 0; a < b; a++) {
if(input_arr[a] < min) {
min = input_arr[a];
}
}
return min;
}
int array_max(const int input_arr[], const int arr_size) {
int a, b = arr_size, max = input_arr[0];
for(a = 0; a < b; a++) {
if(input_arr[a] > max) {
max = input_arr[a];
}
}
return max;
}
So, my question is, how do I use 'NULL' in function to get return value -1?
It is modified version of the #chux-ReinstateMonica answer with some changes.
Use size_t (not int) for sizes.
Try if possible to have one return point from the function
There is no need to check index 0 as it will be equal to the min value
In this case it is better to keep value and the index of the minimal value instead of pointer to it (it will help the compiler to optimize the code)
const int *array_min1(const size_t arr_size, const int input_arr[arr_size]) {
const int *result = arr_size ? input_arr : NULL;
if (result)
{
size_t a, min_index = 0;
int min = input_arr[0];
for(a = 1; a < arr_size; a++) {
if(input_arr[a] < min) {
min = input_arr[a];
min_index = a;
}
}
result = input_arr + min_index;
}
return result;
}
how do I use 'NULL' in function to get return value -1?
Parameter input validation is a common task. Simple test up front.
When input is troublesome:
int array_min(const int input_arr[], const int arr_size) {
if (input_arr == NULL || arr_size <= 0) {
return -1;
}
...
Returning -1 on error is a weak design choice as it is not distinguishable from a good return of -1:
int input_arr[] = {-1, 2, 3, 4, 5};
printf("%d\t", array_min(input_arr, 5));
functions return MIN and MAX value of elements in an array.
Consider instead: return the address of the minimum/maximum. Return NULL on error.
// int array_min(const int input_arr[], const int arr_size) {
const int *array_min(const int input_arr[], const int arr_size) {
if (input_arr == NULL || arr_size <= 0) {
return NULL;
}
//int a, b = arr_size, min = input_arr[0];
int a, b = arr_size;
const char *min = &input_arr[0];
// for(a = 0; a < b; a++) {
for(a = 1; a < b; a++) { // No need to test input_arr[0]
//if(input_arr[a] < min) {
if(input_arr[a] < *min) {
//min = input_arr[a];
min = &input_arr[a];
}
}
return min;
}
Now the calling code can detect troubles.
// printf("%d\t", array_min(input_arr, 5));
const int *min = array_min(input_arr, 5);
// or
const int *min = array_min(input_arr, 0);
// or
const int *min = array_min(NULL, 5);
if (min) {
printf("%d\t", *min);
} else {
printf("Min not found\t");
}

How to make dynamic int array

I have trouble getting my dynamic int array to work properly. I have tried some examples but still can not get it to work. I think I am doing a minor pointer problem but I cannot figure out what. I want to have a dynamic int array and then from another function add numbers to this array. I have gotten the counter to work.
I have tried putting * at different places and trying my way but I am at this point lacking the knowledge to actually know where the * should be. I know some basics about & and * but apparently not enough
static void counterFunction(int* pointerToArray[], int* count)
{
while (*count < 10) {
*(*pointerToArray + *count) = *count;
*count = *count + 1;
}
}
static int* writeSortedToArray(void)
{
// I need to store 1000 numbers at this point
int* dynamicArray = malloc(1000 * sizeof(int));
int counter = 0;
counterFunction(&dynamicArray, &counter);
return 0;
}
The counter works properly, the dynamic array does not work at all. It only store a 0 according to my debugger (xcode)
To add to the other answers, I'd suggest a more generic approach and encapsulation of the management logic:
#include <assert.h> // assert()
#include <stddef.h> // size_t
#include <stdbool.h> // bool, true, false
#include <stdlib.h> // malloc(), calloc(), free(), EXIT_FAILURE, EXIT_SUCCESS
#include <stdio.h> // fputs(), printf(), putchar()
typedef int value_type;
char const *conversion_specifier = "%d"
size_t const initial_capacity = 10
size_t growth_factor = 2
typedef struct dynarray_tag {
size_t size;
size_t capacity;
value_type *data;
} dynarray_t;
dynarray_t dynarray_create(void)
{
dynarray_t new_dynarray = { 0, 0, NULL };
return new_dynarray;
}
dynarray_t dynarray_create_reserve(size_t capacity)
{
dynarray_t new_dynarray = { 0, capacity, NULL };
new_dynarray.data = malloc(capacity * sizeof *new_dynarray.data);
return new_dynarray;
}
dynarray_t dynarray_create_size(size_t size)
{
dynarray_t new_dynarray = { size, size, NULL };
new_dynarray.data = calloc(size, sizeof *new_dynarray.data);
return new_dynarray;
}
bool dynarray_is_valid(dynarray_t const *dynarray)
{
if (!dynarray)
return false;
if (!dynarray->size && !dynarray->capacity && !dynarray->data)
return true;
if (dynarray->size > dynarray->capacity)
return false;
if (dynarray->capacity && dynarray->data)
return true;
return false;
}
size_t dynarray_get_size(dynarray_t const *dynarray)
{
assert(dynarray_is_valid(dynarray));
return dynarray->size;
}
size_t dynarray_get_capacity(dynarray_t const *dynarray)
{
assert(dynarray_is_valid(dynarray));
return dynarray->capacity;
}
value_type* dynarray_at(dynarray_t *dynarray, size_t position)
{
assert(dynarray_is_valid(dynarray) && dynarray->size && position < dynarray->size);
return &dynarray->data[position];
}
value_type* dynarray_front(dynarray_t *dynarray)
{
assert(dynarray_is_valid(dynarray));
return dynarray_at(dynarray, 0);
}
value_type* dynarray_back(dynarray_t *dynarray)
{
assert(dynarray_is_valid(dynarray));
return dynarray_at(dynarray, dynarray->size - 1);
}
bool dynarray_reserve(dynarray_t *dynarray, size_t new_capacity)
{
assert(dynarray_is_valid(dynarray));
if (new_capacity <= dynarray->capacity)
return true;
if (new_capacity < dynarray->size)
return false;
value_type *new_data = realloc(dynarray->data, new_capacity * sizeof *new_data);
if (!new_data)
return false;
dynarray->data = new_data;
dynarray->capacity = new_capacity;
return true;
}
bool dynarray_resize(dynarray_t *dynarray, size_t new_size)
{
assert(dynarray_is_valid(dynarray));
if (new_size <= dynarray->capacity)
return true;
value_type *new_data = realloc(dynarray->data, new_size * sizeof *new_data);
if (!new_data)
return false;
dynarray->data = new_data;
dynarray->size = new_size;
dynarray->capacity = new_size;
return true;
}
bool dynarray_insert(dynarray_t *dynarray, size_t position, value_type value)
{
assert(dynarray_is_valid(dynarray));
if (dynarray->size + 1 > dynarray->capacity) {
size_t new_capacity = dynarray->capacity ? dynarray->capacity * growth_factor : initial_capacity;
if (!dynarray_reserve(dynarray, new_capacity))
return false;
}
for (size_t i = dynarray->size; i > position; --i)
dynarray->data[i] = dynarray->data[i - 1];
dynarray->data[position] = value;
dynarray->size++;
return true;
}
bool dynarray_push_front(dynarray_t *dynarray, value_type value)
{
assert(dynarray_is_valid(dynarray));
return dynarray_insert(dynarray, 0, value);
}
bool dynarray_push_back(dynarray_t *dynarray, value_type value)
{
assert(dynarray_is_valid(dynarray));
return dynarray_insert(dynarray, dynarray->size, value);
}
bool dynarray_insert_sorted(dynarray_t *dynarray, value_type value)
{
assert(dynarray_is_valid(dynarray));
if (!dynarray_get_size(dynarray) || value < *dynarray_front(dynarray))
return dynarray_push_front(dynarray, value);
if (value > *dynarray_back(dynarray))
return dynarray_push_back(dynarray, value);
size_t insert_pos = 0;
for (; insert_pos < dynarray->size && value > dynarray->data[insert_pos]; ++insert_pos);
return dynarray_insert(dynarray, insert_pos, value);
}
void dynarray_print(dynarray_t const *dynarray)
{
assert(dynarray_is_valid(dynarray));
for (size_t i = 0; i < dynarray->size; ++i) {
printf(conversion_specifier, dynarray->data[i]);
if (i + 1 < dynarray->size)
printf(", ");
}
}
void dynarray_sort(dynarray_t *dynarray) // insertion sort
{
assert(dynarray_is_valid(dynarray));
for (size_t i = 1; i < dynarray->size; i++) {
value_type key = dynarray->data[i];
size_t k = i - 1;
for (; k >= 0 && dynarray->data[k] > key; --k)
dynarray->data[k + 1] = dynarray->data[k];
dynarray->data[k + 1] = key;
}
}
void dynarray_free(dynarray_t *dynarray)
{
assert(dynarray_is_valid(dynarray));
free(dynarray->data);
dynarray->size = dynarray->capacity = 0;
dynarray->data = NULL;
}
int main(void)
{
dynarray_t arr = dynarray_create();
if (!dynarray_is_valid(&arr)) {
fputs("Not enough memory. :(\n\n", stderr);
return EXIT_FAILURE;
}
int result = EXIT_FAILURE;
for (value_type i = 2; i < 15; i += 2) {
if (!dynarray_push_back(&arr, i))
goto error_exit;
}
dynarray_print(&arr);
putchar('\n');
for (value_type i = 1; i < 14; i += 2) {
if (i != 7) {
if (!dynarray_push_front(&arr, i))
goto error_exit;
}
}
dynarray_print(&arr);
putchar('\n');
dynarray_sort(&arr);
dynarray_print(&arr);
putchar('\n');
if (!dynarray_insert_sorted(&arr, 0))
goto error_exit;
dynarray_print(&arr);
putchar('\n');
if (!dynarray_insert_sorted(&arr, 15))
goto error_exit;
dynarray_print(&arr);
putchar('\n');
if (!dynarray_insert_sorted(&arr, 7))
goto error_exit;
dynarray_print(&arr);
putchar('\n');
result = EXIT_SUCCESS;
error_exit:
result == EXIT_FAILURE && fputs("Not enough memory. :(\n\n", stderr);
dynarray_free(&arr);
return result;
}
Output:
2, 4, 6, 8, 10, 12, 14
13, 11, 9, 5, 3, 1, 2, 4, 6, 8, 10, 12, 14
1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14
0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14
0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
Todo:
dynarray_insert_range()
dynarray_create_init() from iterator pair
dynarray_from_file()
dynarray_copy()
dynarray_begin()
dynarray_end()
...
You make some mistakes:
1) int* pointerToArray[] is a pointer to pointer(s). You should use int* pointerToArray.
2) *(*pointerToArray+*count)=*count; is dereferencing pointerToArray two times, you should use *(pointerToArray + *count) = *count;.
3) dynamicArrayis already a pointer, you should not use the &operator to get its address. Then counterFunction(&dynamicArray, &counter);should be converted in counterFunction(dynamicArray, &counter);.
Finally, your code should look like:
#include <stdio.h>
#include <stdlib.h>
static void counterFunction(int * pointerToArray, int * count){
while (*count < 10) {
*(pointerToArray + *count) = *count;
*count += 1;
}
}
static int * writeSortedToArray(){
//I need to store 1000 numbers at this point
int * dynamicArray = malloc(100 * sizeof(int));
int counter = 0;
counterFunction(dynamicArray, &counter);
// as suggested, finally release the array
free(dynamicArray);
return 0;
}
int main(){
writeSortedToArray();
return 0;
}
static void counterFunction(int array[], int* count)
{
ptrdiff_t i;
for (i = *count; i < 10; i++)
array[i] = i;
*count = i;
}
static int *writeSortedToArray(void)
{
//I need to store 1000 numbers at this point
int *dynamicArray;
int counter;
dynamicArray = calloc(sizeof(*dynamicArray) * 1000);
counter = 0;
counterFunction(dynamicArray, &counter);
/* counter == 10 */
return dynamicArray;
}
First of all, if a function always returns 0, it should be void (except main(), for its own reasons). Although you probably didn't want to return 0, and instead return the array.
The counter function doesn't need to know that the array is dynamic. It can just accept any array, and use it with array notation.
I changed to a for loop, because it's more natural.
You don't need to pass a pointer to the array, and in fact you shouldn't, because then the compiler could notice the difference between a pointer to an array and a pointer to a pointer, and complain.
I don't get the purpose of your code, but this code is just the corrected version of your code.
Remember to free(dynamicArray); at some point.
Wrong use of pointer here. Your Dynamicarray from the WriteSortedToArray is already an adress so you do not need to pass it as an adress.
This should work :
static void counterFunction(int* pointerToArray, int count){
while (count < 10)
{
pointerToArray[count] = count;
count++;
}
}
static int* writeSortedToArray(void){
int* dynamicArray = malloc(1000 * sizeof(int));
int counter = 0;
counterFunction(dynamicArray, counter);
return 0;
}
If you want to keep the value of your counter when exiting your counterFunction which is 10, do this instead :
static void counterFunction(int* pointerToArray, int *count){
while (*count < 10)
{
pointerToArray[*count] = *count;
*count++;
}
}
static int* writeSortedToArray(void){
int* dynamicArray = malloc(1000 * sizeof(int));
int counter = 0;
counterFunction(dynamicArray, &counter);
return 0;
}
You should always free your memory using the free function to avoid memory leak issues.
free(dynamicArray)

Kruskal Algorithm (set division)

I have a problem to understand Kruskal Algorithm. Here is the code
#include <stdio.h>
#define MAX_VERTICLES 100
#define INF 1000
int parent[MAX_VERTICLES];
int num[MAX_VERTICLES];
void setInit(int n) {
int i;
for (i = 0; i < n; i++) {
parent[i] = -1;
num[i] = 1;
}
}
int setFind(int vertex) {
int p, s, i = -1;
for (i = vertex;(p = parent[i]) >= 0; i = p)
;
s = i;
for (i = vertex;(p = parent[i]) >= 0; i=p)
parent[i]=s;
return s;
}
void setUnion(int s1, int s2) {
if (num[s1] < num[s2]) {
parent[s1]=s2;
num[s2]+=num[s1];
}
else {
parent[s2] = s1;
num[s1] += num[s2];
}
}
typedef struct {
int key;
int u;
int v;
}element;
#define MAX_ELEMENT 100
typedef struct {
element heap[MAX_ELEMENT];
int heap_size;
}HeapType;
void init(HeapType *h) {
h->heap_size = 0;
}
void printHeap(HeapType *h) {
int i;
int level = 1;
printf("\n==========");
for (i = 1; i <= h->heap_size;i++) {
if (i = level) {
printf("\n");
level *= 2;
}
printf("\t%d", h->heap[i].key);
}
printf("\n==========");
}
void insertMinHeap(HeapType *h, element item) {
int i;
i = ++(h->heap_size);
while ((i != 1) && (item.key < h->heap[i / 2].key)){
h->heap[i] = h->heap[i / 2];
i /= 2;
}
h->heap[i] = item;
}
element deleteMinHeap(HeapType *h) {
int parent, child;
element item, temp;
item = h->heap[1];
temp = h->heap[(h->heap_size)--];
parent = 1;
child = 2;
while (child <= h->heap_size) {
if ((child < h->heap_size) && (h->heap[child].key > h->heap[child + 1].key))
child++;
if (temp.key <= h->heap[child].key) break;
h->heap[parent] = h->heap[child];
parent = child;
child *=2;
}
h->heap[parent] = temp;
return item;
}
void insertHeapEdge(HeapType *h, int u, int v, int weight) {
element e;
e.u = u;
e.v = v;
e.key = weight;
insertMinHeap(h, e);
}
void insertAllEdges(HeapType *h){
insertHeapEdge(h, 0, 1, 13);
insertHeapEdge(h, 1, 2, 36);
insertHeapEdge(h, 2, 3, 12);
insertHeapEdge(h, 2, 4, 28);
insertHeapEdge(h, 3, 5, 32);
insertHeapEdge(h, 4, 5, 14);
insertHeapEdge(h, 0, 5, 19);
insertHeapEdge(h, 0, 6, 23);
insertHeapEdge(h, 1, 6, 15);
insertHeapEdge(h, 5, 6, 20);
}
void kruskal(int n) {
int edge_accepted = 0;
HeapType h;
int uset, vset;
element e;
init(&h);
insertAllEdges(&h);
setInit(n);
while (edge_accepted<(n-1)){
e = deleteMinHeap(&h);
uset = setFind(e.u);
vset = setFind(e.v);
if (uset != vset) {
printf("(%d,%d) %d \n", e.u, e.v, e.key);
edge_accepted++;
setUnion(uset, vset);
}7
}
}
void main(){
kruskal(7);
getchar();
}
I cannot understand how setFind and setUnion functions work.(the other things are fine)
Somebody can explain the algorithms explicitly, please?
The algorithm by Kruskal (which aims at the generation of a minimum spanning tree) needs subroutines for finding the connected component for a given vertex and the possibility to merge connected components.
Apparently, parent[i] stores one single vertex which can be followed until no parent is possible; the node which is reached this way is the root of the connected component - this node can be found via setFind; num[i] represents the number of children defined by this relation. Thus, the connected components are represented implicity.
The function setUnion aims at merging the smaller connected component into the larger one by attaching the root of one connected component to the other component and updating the number of children.

How to modify the priority of a value in a max-heap?

I am writing a max-heap, which can change the priority/value. However, I have problems to understand what is wrong in my code.
I have followed this as reference: ref
This is my code (I have hide some functions since it not the focus here)
static void swap(MAX_HEAP *heap, int i, int j);
static void swim(MAX_HEAP *heap, int k);
static void sink(MAX_HEAP *heap, int k);
void swap(MAX_HEAP *heap, int i, int j) {
HEAP_ELEM s;
int k;
s = heap->binary_heap[i];
k = heap->keys[s.fu];
heap->binary_heap[i] = heap->binary_heap[j];
heap->keys[k] = heap->keys[heap->binary_heap[j].fu];
heap->keys[heap->binary_heap[j].fu] = k;
heap->binary_heap[j] = s;
}
void swim(MAX_HEAP *heap, int k) {
int m;
m = k / 2.0;
while (k > 1 && heap->binary_heap[m].priority < heap->binary_heap[k].priority) {
swap(heap, k, m);
k = m;
m = k / 2.0;
}
}
void sink(MAX_HEAP *heap, int k) {
int j;
while (2 * k <= heap->n) {
j = 2 * k;
if (j < heap->n && heap->binary_heap[j].priority < heap->binary_heap[j + 1].priority)
j++;
if (!(heap->binary_heap[k].priority < heap->binary_heap[j].priority))
break;
swap(heap, k, j);
k = j;
}
}
MAX_HEAP *create_maxheap(int capacity) {
int i;
MAX_HEAP *ret;
ret = (MAX_HEAP*) malloc(sizeof (MAX_HEAP));
ret->n = 0;
ret->binary_heap = (HEAP_ELEM*) malloc(sizeof (HEAP_ELEM) * (capacity + 1));
ret->binary_heap[0].fu = 0;
ret->binary_heap[0].priority = 0;
ret->max = capacity;
ret->keys = (int*) malloc(sizeof (int) * (capacity + 1));
for (i = 0; i <= capacity + 1; i++) {
ret->keys[i] = -1;
}
return ret;
}
HEAP_ELEM get_maxheap(MAX_HEAP *heap) {
HEAP_ELEM ret;
if (heap->n == 0) {
return;
}
ret = heap->binary_heap[1];
heap->keys[ret.fu] = -1;
swap(heap, 1, heap->n);
heap->n--;
sink(heap, 1);
return ret;
}
void insert_maxheap(MAX_HEAP *heap, int fu, int p) {
if (heap->n + 1 >= heap->max) {
int i;
heap->max *= 2;
heap->keys = (int*) realloc(heap->keys, sizeof (int) * (heap->max + 1));
heap->binary_heap = (HEAP_ELEM*) realloc(heap->binary_heap, sizeof (HEAP_ELEM) * (heap->max + 1));
for (i = heap->n+1; i < heap->max + 1; i++) {
heap->keys[i] = -1;
}
}
heap->n++;
heap->binary_heap[heap->n].fu = fu;
heap->binary_heap[heap->n].priority = p;
heap->keys[fu] = heap->n;
swim(heap, heap->n);
}
void modify_maxheap(MAX_HEAP *heap, int fu, int p) {
int i;
i = heap->keys[fu];
int old;
if (i == -1) {
insert_maxheap(heap, fu, p);
return;
}
old = heap->binary_heap[i].priority;
heap->binary_heap[i].fu = fu;
heap->binary_heap[i].priority = p;
heap->keys[fu] = i;
if (old < p) {
/* we need to bubble up*/
swim(heap, i);
} else if (old > p) {
//we need to bubble down
sink(heap, i);
}
}
When I have the following execution, it gives bad results... what is wrong here? For instance...
int main(int argc, char** argv) {
MAX_HEAP *heap, *heap2;
HEAP_ELEM he;
heap = create_maxheap(3);
modify_maxheap(heap, 1, 7);
modify_maxheap(heap, 2, 10);
modify_maxheap(heap, 3, 78);
modify_maxheap(heap, 4, 3);
modify_maxheap(heap, 5, 45);
printf("heap 1\n\n");
while(heap->n > 0) {
he = get_maxheap(heap);
printf("..fu: %d; value: %d\n", he.fu, he.priority);
}
printf("max size of heap1: %d\n", heap->max);
printf("\n\n");
heap2 = create_maxheap(10);
modify_maxheap(heap2, 3, 90);
modify_maxheap(heap2, 1, 7);
modify_maxheap(heap2, 2, 10);
modify_maxheap(heap2, 3, 9);
modify_maxheap(heap2, 3, 92);
modify_maxheap(heap2, 4, 3);
modify_maxheap(heap2, 3, 90);
modify_maxheap(heap2, 1, 99);
modify_maxheap(heap2, 5, 45);
modify_maxheap(heap2, 1, 89);
printf("heap 2\n\n");
while(heap2->n > 0) {
he = get_maxheap(heap2);
printf("fu: %d; value: %d\n", he.fu, he.priority);
}
return (EXIT_SUCCESS);
}
Note that I am using an array to store the indices of HEAP_ELEM in order to know the position of a HEAP_ELEM (which has as primary key the "fu" and change its priority. This is my output:
heap 1
..fu: 3; value: 78
..fu: 5; value: 45
..fu: 2; value: 10
..fu: 1; value: 7
..fu: 4; value: 3
max size of heap1: 6
heap 2
fu: 1; value: 99
fu: 3; value: 90
fu: 1; value: 89
fu: 5; value: 45
fu: 4; value: 3
I have changed my modify_maxheap function and it worked:
void modify_maxheap(MAX_HEAP *heap, int fu, int p) {
int i;
i = heap->keys[fu];
if (i == -1) {
insert_maxheap(heap, fu, p);
return;
}
heap->binary_heap[i].priority = p;
swim(heap, i);
sink(heap, i);
}
The reason is that we have to bubble-up and bubble-down in case of any modification to guarantee the heap condition. I hope it can serve as base for someone.

Resources