Reputation: 139
Actually i have to create huffman tree for that i need to sort the frequency and i am using qsort() function for that. But when i try to display the frequency it show still the same pattern (Not the sorted one). Here is my code:-
struct node
{
int value;
char letter; /* symbol */
struct node *left,*right; /* left and right subtrees */
};
typedef struct node Node;
//Given below is the frequency of all 27 alphabets
int englishLetterFrequencies [27] = {81, 15, 28, 43, 128, 23, 20, 61, 71, 2, 1, 40, 24, 69, 76, 20, 1, 61, 64, 91, 28, 10, 24, 1, 20, 1, 130};
here is my function where i try to build huffman (its inside the main() ):
/*builds the huffman tree and returns its address by reference*/
void buildHuffmanTree(Node **tree){
Node *temp;
Node *array[27];
int i, subTrees = 27;
int smallOne;
for (i=0;i<27;i++)
{
array[i] = malloc(sizeof(Node));
array[i]->value = englishLetterFrequencies[i];
array[i]->letter = i;
array[i]->left = NULL;
array[i]->right = NULL;
}
smallOne=sorting(array); //this function is responsible for sorting. I HAVE QSORT() CALL IN THIS FUNCTION
return;
}
see its function definition :
int sorting(Node *array[])
{
int smaller;
int i = 0; int d,p;
printf("the array frequency is \n");
for(d=0;d < 27;d++)
printf("%d ",*array[d]);
// sorting of arrays
qsort(array,27,sizeof(*array),&cmpfunc);
//////////////////////////
printf("\n the sorted array frequency is \n");
for(p=0;p < 27;p++)
printf("%d ",*array[p]);
return smaller;
}
whereas the cmpfunc() is here like this //PROBABLY MISTAKE IS HERE
int cmpfunc (const void * a, const void * b)
{
return ( ((Node *)a)->value - ((Node *)b)->value );
}
Any idea why it don't sort the arrays ?
Upvotes: 0
Views: 1467
Reputation: 66234
Your comparator is wrong, and your assumption of how qsort
works isn't far behind it.
For sorting a pointer array of Node*
you need a comparator like this:
int cmpfunc (const void * a, const void * b)
{
const Node **lhs = (const Node **)a;
const Node **rhs = (const Node **)b;
return (*lhs)->value < (*rhs)->value ? -1
: ((*rhs)->value < (*lhs)->value);
}
Stripping all the extraneous junk out, including the sorting()
call and invoking qsort
directly...
#include <stdio.h>
#include <stdlib.h>
struct node
{
int value;
char letter; /* symbol */
struct node *left,*right; /* left and right subtrees */
};
typedef struct node Node;
static const int englishLetterFrequencies [27] =
{
81, 15, 28, 43, 128, 23,
20, 61, 71, 2, 1, 40, 24,
69, 76, 20, 1, 61, 64, 91,
28, 10, 24, 1, 20, 1, 130
};
int cmpfunc (const void * a, const void * b)
{
const Node **lhs = (const Node **)a;
const Node **rhs = (const Node **)b;
return (*lhs)->value < (*rhs)->value ? -1
: ((*rhs)->value < (*lhs)->value);
}
void buildHuffmanTree(Node **tree)
{
Node *array[27];
int i;
for (i=0;i<27;i++)
{
array[i] = malloc(sizeof(*array[i]));
array[i]->value = englishLetterFrequencies[i];
array[i]->letter = (char)i;
array[i]->left = NULL;
array[i]->right = NULL;
}
qsort(array, 27, sizeof(*array), cmpfunc);
for (i=0; i<27; ++i)
printf("array[%d]->value = %d\n", i, array[i]->value);
return;
}
int main()
{
buildHuffmanTree(NULL);
return 0;
}
Output
array[0]->value = 1
array[1]->value = 1
array[2]->value = 1
array[3]->value = 1
array[4]->value = 2
array[5]->value = 10
array[6]->value = 15
array[7]->value = 20
array[8]->value = 20
array[9]->value = 20
array[10]->value = 23
array[11]->value = 24
array[12]->value = 24
array[13]->value = 28
array[14]->value = 28
array[15]->value = 40
array[16]->value = 43
array[17]->value = 61
array[18]->value = 61
array[19]->value = 64
array[20]->value = 69
array[21]->value = 71
array[22]->value = 76
array[23]->value = 81
array[24]->value = 91
array[25]->value = 128
array[26]->value = 130
Spend some time learning how the algorithm works, and don't take shortcuts. You're going to need two comparator functions for what it looks like you're ultimately going to do (assuming I understand how you're planning on building your huffman tree).
Upvotes: 1
Reputation: 20954
return ( (*(int**)a) - (*(int**)b ));
This is casting a
and b
as "pointer-to-pointer-to-int", so by dereferencing them only once you then calculate the difference between two pointers. What you mean is:
return ( (*(Node **)a)->value - (*(Node **)b)->value );
because whilst **(int**)a
might work in this case it is massively confusing to anyone trying to understand the code.
Edit: sorry, I ended up missing a dereference there myself - fixed.
Also:
printf("%d ",*array[d]);
should be
printf("%d ",array[d]->value);
for the same reason.
Upvotes: 2