Trouble creating a descending heap sort in C - c

void heapSort(int list[], int last)
{
// Local Declarations
int sorted;
int holdData;
int walker;
// Statements
for (walker = 1; walker <= last; walker++)
reheapUp (list, walker);
// Min Heap created. Now to sort!
sorted = last;
while (sorted > 0)
{
holdData = list[0];
list[0] = list[sorted];
list[sorted] = holdData;
sorted--;
reheapDown (list, 0, sorted, moves, comparisons);
}
return;
}
void reheapUp (int heap[], int newNode)
{
// Local Declarations
int parent;
int hold;
// Create a min heap
// Statements
if (newNode)
{
parent = (newNode - 1) / 2;
if (heap[newNode] > heap[parent]) // Only change made from ascending order
{
hold = heap[parent];
heap[parent] = heap[newNode];
heap[newNode] = hold;
reheapUp (heap, parent);
}
}
return;
}
void reheapDown (int heap[], int root, int last)
{
// Local Declarations
int hold;
int leftKey;
int rightKey;
int largeChildKey;
int largeChildIndex;
// Statements
if ((root * 2 + 1) <= last)
{
// There is atleast one child
leftKey = heap[root * 2 + 1];
if ((root * 2 + 2) <= last) {
rightKey = heap[root * 2 + 2];
}
else
rightKey = -1;
// Determine which child is larger
if (leftKey > rightKey)
{
largeChildKey = leftKey;
largeChildIndex = root * 2 + 1;
}
else
{
largeChildKey = rightKey;
largeChildIndex = root * 2 + 2;
}
// Test if root > large subtree
if (heap[root] < heap[largeChildIndex])
{
// parent < child
hold = heap[root];
heap[root] = heap[largeChildIndex];
heap[largeChildIndex] = hold;
reheapDown(heap, largeChildIndex, last);
}
}
return;
}
I got ascending order to heap sort to function by creating a max heap. I read that to create a descending order heap sort I need to create a min heap which I did as shown by changing heap[newNode] < heap[parent] to heap[newNode] > heap[parent] as shown in the code. However, it is still out order. Therefore, I wanted to do what are the other steps? Do I need to alter reheapDown somehow as well?

You need to change all value comparisons you make like heap[root] < heap[largeChildIndex] you didn't mention you changed.

First of all you need to change every comparison operators accordingly, just take them all and think of the problem.
Secondly you only have to reheapUp to (last/2) to create the heap, because the key at (last/2+1) doesn't have any childs.
And I made some heap-sort in C before and I had way less lines of code, and only had one "heapify" function. You might want to look at your code and try to simplify things.
EDIT : if you want some inspiration here is what I did
void fixHeap(int position,int length)
{
int child = (2*position)+1;
int temp;
while (child<=length)
{
if (child<length && vector[child]<vector[child+1])
{
child++;
}
if (vector[position]<vector[child])
{
temp = vector[position];
vector[position] = vector[child];
vector[child] = temp;
position = child;
child = (2*position)+1;
}
else
{
return;
}
}
}
void heapSort(int vector[],int N)
{
int counter;
int temp;
for (counter=(N-1)/2; counter>=0; counter--)
{
fixHeap(counter,N-1);
}
for (counter=N-1; counter>0; counter--)
{
temp = vector[counter];
vector[counter] = vector[0];
vector[0] = temp;
fixHeap(0,counter-1);
}
}

Here is heap sort using min heap implementation. Have a look, if it helps!
#include "stdafx.h"
#define LEFT(i) (2 * (i))
#define RIGHT(i) (((2 * (i)) + 1))
#define PARENT(i) ((i) / 2))
void print_heap(int input[], int n)
{
int i;
printf("Printing heap: \n");
for (i = 0; i < n; i++)
printf("%d ", input[i]);
printf("\n");
}
void swap_nodes(int *a, int *b)
{
int tmp;
tmp = *a;
*a = *b;
*b = tmp;
}
void min_heapify(int input[], int i, int n)
{
int least;
int l = LEFT(i + 1) - 1; // Get 0 based array index
int r = RIGHT(i + 1) - 1; // Get 0 based array index
if (l < n && input[l] < input[i]) {
least = l;
} else {
least = i;
}
if (r < n && input[r] < input[least]) {
least = r;
}
if (least != i) {
swap_nodes(&input[i], &input[least]);
min_heapify(input, least, n);
}
}
void heapify(int input[], int n)
{
for (int i = n/2; i >= 0; i--)
min_heapify(input, i, n);
}
void heap_sort(int input[], int n)
{
heapify(input, n);
for (int i = n - 1; i >= 1; i--) {
swap_nodes(&input[0], &input[i]);
n = n - 1;
min_heapify(input, 0, n);
}
}
int _tmain(int argc, _TCHAR* argv[])
{
int input[] = {5, 3, 17, 10, 84, 19, 6, 22, 9, 1};
int n = sizeof(input) / sizeof(input[0]);
print_heap(input, n);
heap_sort(input, n);
print_heap(input, n);
return 0;
}

Related

Why does the point crash when free it?

In the following code, the result is ok, but the code will be crash when executing finish, and increase one error: Heap corruption detected, the free list is damaged at 0x600000008f50
int *mergeSort(int *a,int count) {
int leftCount = count / 2;
int rightCount = count - leftCount;
int *leftData = getData(a, 0, leftCount);
int *rightData = getData(a, leftCount, count);
int *sortedLeftData = mergeSort(leftData, leftCount);
int *sortedRightData = mergeSort(rightData, rightCount);
int *resultData = mergeData(sortedLeftData, sortedRightData, leftCount,
rightCount);
return resultData;
}
int *getData(int *a,int from, int to) {
if (from > to) { return nil; }
int *res = malloc(to - from + 1);
for (int index = from; index < to; index ++) {
int value = a[index];
res[index-from] = value;
}
return res;
}
int *mergeData(int *a, int *b, int acount, int bcount) {
int *result = malloc(acount + bcount);
int aindex,bindex,rindex;
aindex = bindex = rindex = 0;
while (aindex < acount | bindex < bcount) {
int value,avalue = INT_MAX,bvalue = INT_MAX;
if (aindex < acount) { avalue = a[aindex]; }
if (bindex < bcount) { bvalue = b[bindex]; }
// get value from a point.
if (avalue <= bvalue) {
value = avalue;
aindex ++;
}else {
// get value from b point.
value = bvalue;
bindex ++;
}
result[rindex] = value;
rindex ++;
}
return result;
}
I don't understand why does crash when free the point, any answer will helpfull, thanks.
All of your allocations are too small, and thus you are overflowing your buffers.
The malloc function allocates the requested number of bytes. You need to multiply the number of elements you require by sizeof(int) if your elements are int type. e.g.
int *result = malloc((acount + bcount) * sizeof(int));
Other potential problems I spotted while reading your code are:
Using the bitwise-or operator instead of logical-or:
while (aindex < acount | bindex < bcount)
// ^ should be ||
You never free your temporary buffers, thus your program will blow out memory by leaking like crazy. You must free leftData, rightData, sortedLeftData and sortedRightData in the mergeSort function after you are finished with them.
Note that merge sort actually does not require so much allocation. Doing so will have a huge impact on performance. An efficient implementation only requires a single additional buffer for scratch operations, which can be allocated at the beginning.
I did implementation merge sort use single buffer, as the following code:
void mergeSort(int *a, int count) {
int *tempBuffer = malloc(count * sizeof(int));
mergeSortWithBuffer(a, 0, 0, count - 1,tempBuffer);
free(tempBuffer);
}
void mergeSortWithBuffer(int *a, int leftStart, int rightStart, int end, int *tempBuffer) {
int leftCount = rightStart - leftStart;
int rightCount = end - rightStart + 1;
if (leftCount + rightCount <= 1) { return; }
if (leftCount != 0) {
// left dichotomy
int lls = leftStart;
int lrs = leftStart + leftCount/2;
int lnd = rightStart - 1;
mergeSortWithBuffer(a, lls, lrs, lnd,tempBuffer);
}
if (rightCount != 0) {
// right dichotomy
int rls = rightStart;
int rrs = rightStart + rightCount/2;
int rnd = end;
mergeSortWithBuffer(a, rls, rrs, rnd,tempBuffer);
}
mergeData(a, leftStart, rightStart, end, tempBuffer);
}
void mergeData(int *a, int leftStart, int rightStart, int end,int *tempBuffer) {
int leftCount = rightStart - leftStart;
int rightCount = end - rightStart + 1;
int lindex,rindex;
lindex = rindex = 0;
while (lindex < leftCount || rindex < rightCount) {
int lv = INT_MAX,rv = INT_MAX;
if (lindex < leftCount) { lv = a[leftStart + lindex]; }
if (rindex < rightCount) { rv = a[rightStart + rindex]; }
if (lv <= rv) {
tempBuffer[leftStart + lindex + rindex] = lv;
lindex ++;
}else {
tempBuffer[leftStart + lindex + rindex] = rv;
rindex ++;
}
}
for (int index = 0; index < end - leftStart + 1; index ++) {
a[leftStart + index] = tempBuffer[leftStart + index];
}
}
I thought the mergeData function can replace data in the point a each other without the temp buffer, but the logic is too complex and the efficient is not fast, so i add the temp buffer in this function.
Would you have better suggestions if you have willing?

Counting swaps in Quicksort in C

I am trying to count the number of swaps that occur in my quicksort in C. However, I am getting values that are incorrect and not sure where I went wrong. I am using a structures as my arrays to be sorted.
struct anArray{
int numbers[maxSize];
int swaps;
};
/* Partition function */
int partition(struct anArray *array, int start, int end){
if(start == end){
return start;
}
int pivot = array->numbers[end];
int low = start - 1;
int high = end;
for(;;){
do{
low++;
} while(array->numbers[low] < pivot);
do{
high--;
} while(array->numbers[high] > pivot);
/* Detector for when the cells meet */
if(low >= high){
swap(array, low, end);
return low;
}
}
/* Swapping the values */
swap(array, low, high);
}
This is my partition function used to "separate" the arrays.
void quickSort(struct anArray *array, int start, int end){
if(end - start <= 0){ return; }
else{
int pivot = array->numbers[end];
int partitionPoint = partition(array, start, end);
quickSort(array, start, partitionPoint - 1);
quickSort(array, partitionPoint + 1, end);
}
}
This is my quicksorting function. It's a recursive function.
My swap function increments counter by 1 every time it's called.
In my main, I set
myArray->swaps = counter;
But the number of times the swaps occurs isn't right. For example, if I sort an array that goes from 1 to 9, the number of swaps should be 0 but I get 9. I've tried incrementing counter when it's in the partition function only but it gives me the same result.
Is there something wrong with my partition function?
Thank you very much
Edit 1:
Here's my swap function.
void swap(struct anArray *array, int first, int second){
int temp = array->numbers[first];
array->numbers[first] = array->numbers[second];
array->numbers[second] = temp;
counter++;
}
I've tried using
void swap(struct anArray *array, int first, int second, int swapCount)
and then have swapCount be array->swaps when calling the swap function, and incrementing it by 1 but it gives me the same answer.
Here's a part of my main.
int main(){
struct anArray *ascending = (struct anArray*)malloc(10 * sizeof(struct anArray));
int ascend[maxSize] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
initArray(ascending, ascend);
quickSort(ascending, 0, maxSize - 1);
ascending->swaps = counter;
printf("Test: Unique random values\nSorted: [ ");
for(int i = 0; i < maxSize; i++){
printf("%i ", ascending->numbers[i]);
}
printf("]\nSwaps: %i\nComps: \n\n", ascending->swaps);
The other parts of my main are just other arrays to be sorted. The initArray is used to set the values of array->numbers and also reset array->swaps to 0.
Your quicksort code seems pretty good. I didn't examine it rigorously, but it passed a simple test, so I didn't investigate further. (Edit: Based on your feedback, I created a third version in my second update that shows that the sort has an issue for larger data inputs).
The main bug was the malloc at the top of main. We do not want an array of the struct anArray:
struct anArray *ascending = malloc(10 * sizeof(struct anArray));
That is, we do not want (e.g.) 10 structs, we want a single struct and to fill in 10 ints that go into the numbers field that is in that single struct.
The initArray function was not posted, so I had to guess/deduce what it might be. Based on the above bug, I'm not sure that numbers would have been initialized correctly.
From the code fragments posted, I was able to piece together a whole program. I've created two versions:
One with the bugs annotated [but not fixed] that compiles cleanly.
And, a second that is fully cleaned up, working, and generalized for arbitrary array sizes [please pardon the gratuitous style cleanup]
Here is [something close to] your original code with the bugs annotated:
#include <stdio.h>
#include <stdlib.h>
// NOTE/BUG: this was not defined and _fixed_ defines should be all caps
#define maxSize 10
struct anArray {
int numbers[maxSize];
int swaps;
};
int counter;
void
initArray(struct anArray *array,const int *src)
{
for (int idx = 0; idx < maxSize; ++idx)
array->numbers[idx] = src[idx];
array->swaps = 0;
}
void
swap(struct anArray *array, int first, int second)
{
int temp = array->numbers[first];
array->numbers[first] = array->numbers[second];
array->numbers[second] = temp;
counter++;
}
/* Partition function */
int
partition(struct anArray *array, int start, int end)
{
if (start == end) {
return start;
}
int pivot = array->numbers[end];
int low = start - 1;
int high = end;
for (;;) {
do {
low++;
} while (array->numbers[low] < pivot);
do {
high--;
} while (array->numbers[high] > pivot);
/* Detector for when the cells meet */
if (low >= high) {
swap(array, low, end);
return low;
}
}
/* Swapping the values */
swap(array, low, high);
}
void
quickSort(struct anArray *array, int start, int end)
{
if (end - start <= 0) {
return;
}
else {
// NOTE/BUG: pivot is _not_ used
int pivot = array->numbers[end];
int partitionPoint = partition(array, start, end);
quickSort(array, start, partitionPoint - 1);
quickSort(array, partitionPoint + 1, end);
}
}
int
main(void)
{
// NOTE/BUG: we do _not_ want an array of the struct, but an array of int
// that is allocated for "number" _inside_ the struct
struct anArray *ascending = malloc(10 * sizeof(struct anArray));
int ascend[maxSize] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
// NOTE/BUG: this was not defined
initArray(ascending, ascend);
quickSort(ascending, 0, maxSize - 1);
ascending->swaps = counter;
printf("Test: Unique random values\nSorted: [ ");
for (int i = 0; i < maxSize; i++) {
printf("%i ", ascending->numbers[i]);
}
printf("]\nSwaps: %i\nComps: \n\n", ascending->swaps);
return 0;
}
Here is a cleaned up and working version. I've generalized it so it can take an arbitrarily long array. I've also done a bit of style and code cleanup:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int *numbers;
int size;
int swaps;
} Array;
Array *
initArray(const int *src,int size)
{
Array *array = malloc(sizeof(Array));
array->numbers = malloc(size * sizeof(int));
array->size = size;
// store in reverse order so the sort will actually do something
for (int idx = 0; idx < size; ++idx)
array->numbers[size - 1 - idx] = src[idx];
array->swaps = 0;
return array;
}
void
freeArray(Array *array)
{
free(array->numbers);
free(array);
}
void
swap(Array *array, int first, int second)
{
int temp = array->numbers[first];
array->numbers[first] = array->numbers[second];
array->numbers[second] = temp;
array->swaps += 1;
}
/* Partition function */
int
partition(Array *array, int start, int end)
{
if (start == end)
return start;
int pivot = array->numbers[end];
int low = start - 1;
int high = end;
for (;;) {
do {
low++;
} while (array->numbers[low] < pivot);
do {
high--;
} while (array->numbers[high] > pivot);
/* Detector for when the cells meet */
if (low >= high) {
swap(array, low, end);
return low;
}
}
/* Swapping the values */
swap(array, low, high);
}
void
quickSort(Array *array, int start, int end)
{
if (end - start <= 0)
return;
//int pivot = array->numbers[end];
int partitionPoint = partition(array, start, end);
quickSort(array, start, partitionPoint - 1);
quickSort(array, partitionPoint + 1, end);
}
int
main(void)
{
// NOTE/BUG: we do _not_ want an array of the struct, but an array of int
// that is allocated for "number" _inside_ the struct
int original[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int size = sizeof(original) / sizeof(original[0]);
Array *ascending = initArray(original, size);
quickSort(ascending, 0, ascending->size - 1);
printf("Test: Unique random values\nSorted: [ ");
for (int i = 0; i < ascending->size; i++) {
int expected = original[i];
int actual = ascending->numbers[i];
printf("%d%s ", actual, (actual == expected) ? "" : "???");
}
printf("]\nSwaps: %i\nComps: \n\n", ascending->swaps);
freeArray(ascending);
return 0;
}
UPDATE:
What does the line int size = sizeof(original) / sizeof(original[0]); do exactly?
Does it give me an integer for size which I set to be the size of how many numbers I can hold in an array?
Yes, that is common/idiomatic trick to get the count of the number of elements of a fixed size array:
int array[] = { 1, 2, 3 };
size_t count = sizeof(array) / sizeof(array[0]);
Here, sizeof(array) is 3 times the size [in bytes] of the individual elements [which are int, which is 4 bytes], so we have 3 * 4 or 12.
sizeof(array[0]) is the size of the single, first element of the array, which is [again] an int, so this is 4.
So, when we divide the two, we have 12 / 4 or 3, which is the number of elements.
If so, wouldn't the amount of numbers I can hold be really small if sizeof(original[0]) happens to be very large?
No, because of the division. It doesn't care how large the element size [in bytes] is, because the ratio always produces the number of elements.
The sizeof(arr) / sizeof(arr[0]) trick is useful to get the count when we do: int arr[] = { ... };
If we do:
#define ARRCOUNT 3
int arr[ARRCOUNT] = { 1, 2, 3 };
We already know the count (i.e. it is ARRCOUNT).
The [slight] advantage to the sizeof/sizeof trick is that if we had incorrectly defined ARRCOUNT as 4 by mistake, it would still compile, link, and run, but would produce incorrect results [because there were only 3 elements].
This is a common enough trick that we can define a generic macro [that we can reuse by putting it a .h file]:
#define ARRAY_COUNT(arr_) (sizeof(arr_) / sizeof(arr_))
UPDATE #2:
I've tried your code (even tried copying and pasting it) but my swaps is still showing 9 despite my array to be sorted is just going from { 1 to 10}. Not sure why this keeps occurring.
I believe [now] you have a bug in the sort itself.
I've produced another version that has much more extensive test data generation and comparison.
At a minimum, because of the way the tests are structured, the first element of the sorted array should always have a value of 1.
The test that fails is the one that does a random shuffle of the original array before sending it in to be sorted.
You can add other tests as needed. The array needn't be so large to show the problem. For example, the following single test is enough to produce the error:
bigtest(100,237,1);
Anyway, here is the enhanced diagnostic code:
#include <stdio.h>
#include <stdlib.h>
#define MAXLEN 60
typedef struct {
int *numbers;
int size;
int swaps;
} Array;
Array *
initArray(const int *src,int size,int randshuf)
{
int idx;
Array *array = malloc(sizeof(Array));
array->numbers = malloc(size * sizeof(int));
array->size = size;
array->swaps = 0;
// store in reverse order so the sort will actually do something
switch (randshuf) {
case 0: // reverse the numbers
for (idx = 0; idx < size; ++idx)
array->numbers[size - 1 - idx] = src[idx];
break;
default: // do _crude_ random shuffle
for (idx = 0; idx < size; ++idx)
array->numbers[idx] = 0;
for (idx = 0; idx < size; ++idx) {
while (1) {
int ridx = rand() % size;
if (array->numbers[ridx] == 0) {
array->numbers[ridx] = src[idx];
break;
}
}
}
break;
}
return array;
}
void
freeArray(Array *array)
{
free(array->numbers);
free(array);
}
void
swap(Array *array, int first, int second)
{
int temp = array->numbers[first];
array->numbers[first] = array->numbers[second];
array->numbers[second] = temp;
array->swaps += 1;
}
/* Partition function */
int
partition(Array *array, int start, int end)
{
if (start == end)
return start;
int pivot = array->numbers[end];
int low = start - 1;
int high = end;
for (;;) {
do {
low++;
} while (array->numbers[low] < pivot);
do {
high--;
} while (array->numbers[high] > pivot);
/* Detector for when the cells meet */
if (low >= high) {
swap(array, low, end);
return low;
}
}
/* Swapping the values */
swap(array, low, high);
}
void
quickSort(Array *array, int start, int end)
{
if (end - start <= 0)
return;
//int pivot = array->numbers[end];
int partitionPoint = partition(array, start, end);
quickSort(array, start, partitionPoint - 1);
quickSort(array, partitionPoint + 1, end);
}
void
print_orig(const int *orig,int count)
{
int len = 0;
printf("Test: Original numbers (%d):\n",count);
for (int idx = 0; idx < count; ++idx) {
len += printf(" %10d ", orig[idx]);
if (len >= MAXLEN) {
printf("\n");
len = 0;
}
}
if (len > 0)
printf("\n");
}
int
print_array(Array *array,const int *orig,const char *reason)
{
int len = 0;
int cmp;
int err = -1;
printf("Test: Array Values (%s):\n",reason);
for (int idx = 0; idx < array->size; ++idx) {
int actual = array->numbers[idx];
if (orig != NULL) {
int expected = orig[idx];
cmp = (actual == expected);
}
else
cmp = 1;
len += printf(" %10d%c", actual, cmp ? ' ' : '?');
if (len >= MAXLEN) {
printf("\n");
len = 0;
}
if (cmp)
continue;
if (err < 0)
err = idx;
}
if (orig != NULL)
printf("\nSwaps: %i\nComps: \n\n", array->swaps);
else {
if (len > 0)
printf("\n");
}
return err;
}
void
bigtest(int count,int randgap,int randshuf)
// count -- number of elements (negative means random)
// randgap -- gap between element values (negative means random)
// randshuf -- 0=simple reverse, 1=random shuffle
{
int *orig;
Array *array;
printf("\n");
for (int idx = 1; idx <= 80; ++idx)
printf("-");
printf("\n");
printf("COUNT: %d, RANDGAP: %d, RANDSHUF: %d\n",count,randgap,randshuf);
// get number of elements
if (count < 0)
count = (rand() % count) + 1;
// get element gap (e.g. 1 --> {1, 2, 3}, 2 --> { 1, 3, 5 }
if (randgap < 0)
randgap = (rand() % randgap) + 1;
printf("COUNT: %d, RANDGAP: %d, RANDSHUF: %d\n",count,randgap,randshuf);
// get original array
orig = malloc(sizeof(int) * count);
// fill in original array
do {
int val = 1;
// simple gap
if (randgap >= 0) {
if (randgap == 0)
randgap = 1;
for (int idx = 0; idx < count; ++idx, val += randgap)
orig[idx] = val;
break;
}
// random gap
int gap;
for (int idx = 0; idx < count; ++idx, val += gap) {
orig[idx] = val;
gap = (rand() % randgap) + 1;
}
} while (0);
print_orig(orig,count);
array = initArray(orig,count,randshuf);
print_array(array,NULL,"Shuffled");
quickSort(array, 0, array->size - 1);
print_array(array,orig,"Sorted");
freeArray(array);
free(orig);
}
int
main(void)
{
bigtest(10,0,0);
bigtest(-100,23,0);
bigtest(-1000,-2337,0);
bigtest(-1000,-2337,1);
return 0;
}

C - How to implement priority queue using binary heap with tie-breaker?

I have to implement a priority queue using binary heap in C for the university assignment. Program should get the n values from input, when value is 0, it should print the ID number(so, if task that was added as 5th element has the highest priority 7, print "5") and remove the highest-priority task from queue, and when value>0 it should add new node. To implement ID's and priority, I used arrays of structs.
The task would be quite simple, if not the fact that it should also print lower ID's if the priority of elements are the same...
I've done my research, but the only advice that I've managed to found is to modify the fragments of typical heap functions (insertkey, heapify) to also look for elements' ID. I've tried to do this, but I have no idea what went wrong - elements are still not sorted in the way I want them to be. I would be grateful for any piece of advice and tips!
Code:
#include <stdio.h>
#define SIZE 99999
int heapsize = 0;
int count = 0;
struct pqueue
{
int priority;
int id;
};
struct pqueue A[SIZE];
void swap(int *x, int *y)
{
int temp = *x;
*x = *y;
*y = temp;
}
void initializearray()
{
for(int i=0; i<SIZE; i++)
{
A[i].priority = 0;
A[i].id = 0;
}
}
void printheap(); //prototype of debugging function
int left(int i)
{
return (i * 2) + 1;
}
int right(int i)
{
return (i * 2) + 2;
}
int parent(int i)
{
return ((i - 1) / 2);
}
void insertkey(int z)
{
heapsize++;
int i = heapsize - 1;
A[i].priority = z;
count++;
A[i].id = count;
while (i != 0 && A[parent(i)].priority < A[i].priority)
{
swap(&A[i].priority, &A[parent(i)].priority);
swap(&A[i].id, &A[parent(i)].id);
i = parent(i);
}
i = heapsize-1;
while(i != 0 && A[parent(i)].priority == A[i].priority && A[parent(i)].id > A[i].id )
{
swap(&A[i].priority, &A[parent(i)].priority);
swap(&A[i].id, &A[parent(i)].id);
i = parent(i);
}
// printheap();
}
void maxheapify(int i)
{
int l = left(i);
int r = right(i);
int largest;
if (l <= heapsize && A[l].priority >= A[i].priority)
{
largest = l;
if(A[l].priority == A[i].priority)
{
if(A[l].id < A[i].id)
{
largest = l;
}
else
{
largest = i;
}
}
}
else
{
largest = i;
}
if (r <= heapsize && A[r].priority >= A[largest].priority)
{
largest = r;
if(A[r].priority == A[largest].priority)
{
if(A[r].id < A[largest].id)
{
largest = r;
}
}
}
if (largest != i)
{
swap(&A[i].priority, &A[largest].priority);
swap(&A[i].id, &A[largest].id);
maxheapify(largest);
}
}
int extractmax()
{
int max = A[0].id;
A[0].priority = A[heapsize-1].priority;
A[0].id = A[heapsize-1].id;
heapsize--;
//printheap();
maxheapify(0);
return max;
}
void printheap() // debug function
{
for(int i = 0; i < heapsize; i++)
{
printf("prio %d id %d \n", A[i].priority, A[i].id);
}
}
int main()
{
int n;
int z;
initializearray();
scanf("%d", &n);
for(int i=0; i<n; i++)
{
scanf("%d", &z);
if(z != 0)
{
insertkey(z);
}
else
{
int local = extractmax();
if(local != 0 && heapsize+1 != 0)
{
printf("%d\n", local);
// printheap();
}
}
}
return 0;
}
Example input:
7
3 0 0 2 8 8 0
Output:
1
3
Example input (here comes the problem:)
10
1 1 1 1 2 0 0 0 0 0
Output:
5
3
2
4
1
Expected output:
5
1
2
3
4
Thank you for your time!
Instead of incorporating the logic directly into the heap implementation, write a comparison function that considers the id if the priorities are the same:
int pqless(const struct pqueue *a, const struct pqueue *b)
{
if (a->priority < b->priority) return 1;
if (a->priority > b->priority) return 0;
return (a->id > b->id);
}
This function returns true if a's priority is less than b's. If both priorities are equal, it returns true if a's id is smaller than b's.
Now update your heap code. Wherever you compare the priorities in the original code, now just call the function:
void insertkey(int z)
{
int i = heapsize++;
A[i].priority = z;
A[i].id = ++count;
while (i != 0 && pqless(&A[parent(i)], &A[i])) {
swap(&A[i].priority, &A[parent(i)].priority);
swap(&A[i].id, &A[parent(i)].id);
i = parent(i);
}
}
void maxheapify(int i)
{
int l = left(i);
int r = right(i);
int largest = i;
if (l <= heapsize && !pqless(&A[l], &A[i])) largest = l;
if (r <= heapsize && !pqless(&A[r], &A[largest]))largest = r;
if (largest != i) {
swap(&A[i].priority, &A[largest].priority);
swap(&A[i].id, &A[largest].id);
maxheapify(largest);
}
}

Dynamic Program in C

Hi Guys i have edited the questions.Here is my entire code.I have given basic amount of readability to my program.I hope u guys can understand the program.
#include<stdio.h>
#include<stdlib.h>
int Max_Min(int,int,int,int *, int *);
int *Max,Number;
int main()
{
int n1, n2,Maximum_Element=0,*Max;
int i = 0, j = 0;
scanf("%d",&Number);
Max =(int *) malloc(sizeof(int)*Number);//Array Max is created
for (int k = 0;k <(Number/2);k++)
{
scanf("%d", &n1);
scanf("%d", &n2);
Max[k] = Max_Min(0,1,0,&n1,&n2);//Passing integer elements n1,n2 with flag 0
}
Maximum_Element=Max_Min(1,1,((sizeof(Max)*Number)/8),Max,Min);//Passing array elements Max,Min with flag 1 to function Max_Min
printf("Maximum_Element=%d", Maximum_Element);
return 0;
}
int Max_Min(int flag,int Max_Min_flag,int length,int *n1,int *n2)//n1 and n2 should be able to handle array and integers
{
int i=0,j = 0,k1,k2,Min1 = 0, Min2 = 0,count=0, Not_Zero = 0,x=0,y=0, *New_Max = 0,*New_Min;
/*Recursive Loop for splitting the array elements and calling the array */
if (flag == 1)
{
New_Max = (int *)(malloc(sizeof(int)*length));
for (;i <= ((length) / 2);i = i + 2)//
{
k1 = n1[i];
j = i + 1;
if (j <= ((length + 1) / 2))
{
k2 = n1[j];
New_Max[count] = Max_Min(0, 1, 0, &k1, &k2);//It is passing integer elements with flag 0 to function Max_Min
count++;
}
}
New_Max[count] = n1[j + 1];
for (int i = 0;i < count + 1;i++)
{
**/* Problem is assigning Max[i]=New_Max[i] is not getting assigned*/**
Max[i] = New_Max[i];//Copying from New_Max to Max because New_Max will be overwritten,so possible chaunce of dataloss
Not_Zero++;
}
while ((sizeof(Max) / 4 - (Not_Zero))>0)
{
Max[Not_Zero] = 0;
Not_Zero++;
}
/*Logic for calling recursive functions based on the count*/
if (count > 1)
{
count--;
Max_Min(1, 1, count, Max, Min);//Calling Recursive function by Passing Entire Arrays with flag 1.
}
else if (count == 1 && Max[1] == 0)
{
*n1 = Max[0];
*n2 = Min[0];
}
else if (count == 1 && Max[2] == 0)
{
Max_Min(1, 1, count + 1, Max, Min);
count--;
}
}
/*Logic for Finding Maximum & Minimum element is present down*/
if (flag == 0)
{
printf("flag");
if (Max_Min_flag == 1)
{
if (*n1 > *n2)
{
}
else if ((*n1 < *n2) && Max_Min_flag == 1)
{
int temp = 0;
temp = *n1;//5
*n1 = *n2;//7
*n2 = temp;//5
}
}
else if (Max_Min_flag == 2)
{
if (*n1 > *n2)//7>2
{
int temp = 0;
temp = *n1;//2
*n1 = *n2;//2
*n2 = temp;//2,7
}
else if (*n1 < *n2)
{
}
}
}
return *n1;//7
}
Problem is assigning Max[i]=New_Max[i] in function Max_Min().It shows Run time error as "Access violation writing location 0x00000000."
First you need to #include <stdlib.h> to use malloc
You must declare your function before using it.
func must return int*.
Also in func "n", first "Max", and second "Max" needs to be the same variable. Rename "n" to "Max"
This is the code corrected with an extra printf;
#include <stdio.h>
#include <stdlib.h>
int *Max,Number=5;
int* func(int *Max)
{
for(int j=0;j<5;j++)
Max[j]=j;//Its not working in this line
return Max;
}
int main()
{
Max=(int *) malloc(sizeof(int)*Number);
for(int i=0;i<5;i++)
Max[i]=i;
int* x = func(Max);
for(int i=0;i<5;i++)
printf("%d", x[i]);
}
The following contains only minor adaptations of your code and it runs fine:
int *func(int *n);
int *Max,Number=5;
int main()
{
int *x,i;
Max=(int *) malloc(sizeof(int)*Number);
for(i=0;i<Number;i++)
Max[i]=i;
x=func(Max);
free(Max);
return(0);
}
int *func(int *n)
{
int j;
for (j=0;j<Number;j++)
n[j]=Number-j; // reverse the number, just to check
return Max;
}

Sort structure of arrays using qsort

I have a stucture containing two arrays: the row- and the column-index of a matrix. These indices are not order and I would like to sort them using qsort.
What I do not want to use
I am aware that this is easy if I have an array of structures. The could then looks as follows
// structure to store the row/column index
typedef struct Index {
int row;
int col;
} Index;
// function to compare two entries
int cmp(const void *a, const void *b){
Index *Ia = (Index *) a;
Index *Ib = (Index *) b;
if(Ia->row < Ib->row ) return -1;
if(Ia->row == Ib->row && Ia->col < Ib->col) return -1;
if(Ia->row == Ib->row && Ia->col == Ib->col) return 0;
if(Ia->row == Ib->row && Ia->col > Ib->col) return 1;
if(Ia->row > Ib->row ) return 1;
}
// main program
int main(void) {
int N = 3;
Index mat[N];
// fill the matrix with fictitious data
mat[0].row = 1; mat[0].col = 3;
mat[1].row = 0; mat[0].col = 2;
mat[2].row = 0; mat[0].col = 1;
// sort the "matrix": first ascending rows, then ascending columns
qsort(mat,N,sizeof(Index),cmp);
return 0;
}
What I do want to use
My program is constructed such that I do not have an array of structures, but I have a structure of arrays:
// define structure
typedef struct Matrix {
int* row;
int* col;
} Matrix;
// main program
int main(void) {
// define fictitious data
int row[3] = { 1 , 1 , 0 };
int col[3] = { 3 , 2 , 1 };
// define matrix
Sparse mat;
mat.row = row;
mat.col = col;
// sort
// ...?
return 0;
}
I want to sort the row/column index such as above. So far I copied the data to an array of structures, sorted, and copied back. However, the data-set I am using is so large that I want to avoid this.
Thanks!
Not an answer but a comment on the way you are using the compare() function in qsort(). It would be more efficient like this.
int cmp(const void *a, const void *b){
Index *Ia = (Index *) a;
Index *Ib = (Index *) b;
if(Ia->row < Ib->row) return -1;
if(Ia->row > Ib->row) return 1;
if(Ia->col < Ib->col) return -1;
if(Ia->col > Ib->col) return 1;
return 0;
}
If you don't want to use additional memory then you should write your qsort like below (I made only short tests):
Original source of qsort: http://en.wikibooks.org/wiki/Algorithm_Implementation/Sorting/Quicksort
#include <stdio.h>
typedef struct Matrix {
int* row;
int* col;
} Matrix;
int cmp(Matrix* m, int a, int b)
{
if( m->row[a] != m->row[b] )
return m->row[a] - m->row[b];
return m->col[a] - m->col[b];
}
void swap(Matrix *m, int l, int r)
{
int tmp;
tmp = m->row[l];
m->row[l] = m->row[r];
m->row[r] = tmp;
tmp = m->col[l];
m->col[l] = m->col[r];
m->col[r] = tmp;
}
void sort(Matrix* tab, int begin, int end)
{
if (end > begin) {
int pivot = begin;
int l = begin;
int r = end;
while(l < r) {
if (cmp(tab, l, pivot) <= 0) {
++l;
} else if ( cmp(tab, r, pivot) > 0 ) {
--r;
} else if ( l < r ) {
swap(tab, l, r);
}
}
--l;
swap(tab, begin, l);
sort(tab, begin, l);
sort(tab, r, end);
}
}
int main(void) {
const int N = 3;
Matrix matrix;
int row[N] = { 1 , 1 , 0 };
int col[N] = { 3 , 2 , 1 };
matrix.row = row;
matrix.col = col;
sort( &matrix, 0, N );
for(int i = 0; i < N; ++i)
printf("%d %d\n", matrix.row[i], matrix.col[i]);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
typedef struct Matrix {
int* row;
int* col;
} Matrix;
Matrix *mat_cmp;//see from the comparison function
int cmp(const void *a, const void *b){
int ia = *(int *)a;
int ib = *(int *)b;
int ra = mat_cmp->row[ia];
int rb = mat_cmp->row[ib];
if(ra == rb){
int ca = mat_cmp->col[ia];
int cb = mat_cmp->col[ib];
return (ca > cb) - (ca < cb);
} else
return (ra > rb) - (ra < rb);
}
#define N 3
int main(void) {
int row[N] = { 1 , 1 , 0 };
int col[N] = { 3 , 2 , 1 };
int i, index[N];
Matrix mat = { .row=row, .col=col};
for(i=0; i<N; ++i)
index[i] = i;//set index(0..N-1)
mat_cmp = &mat;
qsort(index, N, sizeof(*index), cmp);
for(i=0;i<N;i++){
printf("%d,%d\n", mat.row[index[i]], mat.col[index[i]]);
}
return 0;
}

Resources