chefwink
chefwink

Reputation: 47

Priority queue in ascending order

In C language, How would I Go about printing my code in ascending order? I have asked some questions on stack earlier today, and I am still a little confused. My code currently reads a file and uses a priority queue to print the frequencies of each character in the file, however I need it to print out the characters in ascending order, while my project just prints them in the order of the ASCII table.

Here is my code:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>

struct pair //struct to store frequency and value 
{
    int frequency;
    char value;
};

struct Qnode
{
    struct pair nodeValue;
    struct Qnode *next;
    struct Qnode *left, *right;
};

 void popQueue(struct Qnode **front)
{
    struct Qnode *pop = *front;

    *front = (*front) -> next;

    free(pop);
}

void pushQueue(struct Qnode **front, struct Qnode *newQnode)
{
    struct Qnode *n1 = *front;
    struct Qnode *n2 = newQnode;
    
    if (!(*front))
    {
        (*front) = newQnode;
    }
    else{

        if((*front)->nodeValue.frequency < newQnode->nodeValue.frequency)
        {
            n2->next = *front;
            *front = n2;
        }
        else
        {
            while(n1->next != NULL && (n1->nodeValue).frequency < (newQnode->nodeValue).frequency)
            {
                n1 = n1->next;
            }

            n2->next = n1->next;
            n1->next = n2;
        }
    }
    
    //newQnode->next = front;
   // front = newQnode;

}

/*
struct Qnode *newNode(struct pair Pairs)
{
    struct Qnode *temp = (struct Qnode*)malloc(sizeof(struct Qnode));

    temp->left = temp->right = NULL;
    temp->nodeValue = Pairs;
    temp->frequency = frequency;

}
*/

struct Qnode *createQnode(struct pair Pairs)
{
    struct Qnode *p = malloc(sizeof(struct Qnode));

    p->next=NULL;
    p->nodeValue = Pairs;

    return p;
}

void printQueue(struct Qnode **front)
{
    struct Qnode *nodePtr = *front;
    while (nodePtr != NULL)
    {
    
            printf("%c: %d\n", (nodePtr->nodeValue).value,(nodePtr->nodeValue).frequency);
            nodePtr = nodePtr->next;
    
    }
}



int main(int argc, char *argv[]) //command line takes in the file of text
{
    struct pair table[128]; //set to 128 because these are the main characters
    

    int fd; // file descriptor for opening file
    char buffer[1]; // buffer for reading through files bytes

    fd = open(argv[1], O_RDONLY); // open a file in read mode
    
    for(int j = 0; j < 128; j++)//for loop to initialize the array of pair (struct)
    {
        table[j].value = j; // table with index j sets the struct char value to equal the index
        table[j].frequency = 0; // then the table will initialize the frequency to be 0
    }

    while((read(fd, buffer, 1)) > 0) // read each character and count frequency
    {
          int k = buffer[0]; //index k is equal to buffer[0] with integer mask becasue each letter has a ASCII number.
          table[k].frequency++; //using the struct pair table with index k to count the frequency of each character in text file
    }

   struct Qnode *pq = NULL; //initialize priority queue Qnode struct

    for (int i = 32; i < 128; i++) // for loop to print the values of the ASCII tabe 
    {
        struct Qnode *new = createQnode(table[i]); //create new node frome struct pair
        pushQueue(&pq, new); //insert node into priority queue
    }

        printQueue(&pq); // print queue to screen
        popQueue(&pq); // remove pop each element from queue
    
        close(fd); // close the file

    
    
    return 0; //end of code
} 

Here is my output:

./frequencyNew freqCount.txt
m: 13
: 0
~: 0
}: 0
|: 0
{: 0
z: 0
y: 0
x: 0
w: 0
v: 0
u: 0
t: 0
s: 0
r: 0
q: 0
p: 0
o: 0
n: 10
l: 12
k: 11
0: 10
j: 10
i: 9
h: 8
g: 7
f: 6
e: 5
d: 4
c: 3
b: 2
a: 1
`: 0
_: 0
^: 0
]: 0
\: 0
[: 0
Z: 0
Y: 0
X: 0
W: 0
V: 0
U: 0
T: 0
S: 0
R: 0
Q: 0
P: 0
O: 0
N: 0
M: 0
L: 0
K: 0
J: 0
I: 0
H: 0
G: 0
F: 0
E: 0
D: 0
C: 0
B: 0
A: 0
@: 0
?: 0
>: 0
=: 0
<: 0
;: 0
:: 0
9: 1
8: 2
7: 3
6: 4
5: 5
4: 6
3: 7
2: 8
1: 9
 : 0
/: 0
.: 0
-: 0
,: 0
+: 0
*: 0
): 0
(: 0
': 0
&: 0
%: 0
$: 0
#: 0
": 0
!: 0

Upvotes: 0

Views: 291

Answers (2)

dulngix
dulngix

Reputation: 424

Please change the two lines in the pushQueue function

  • at 41 Line

chanage

if((*front)->nodeValue.frequency < newQnode->nodeValue.frequency)

to

if((*front)->nodeValue.frequency > newQnode->nodeValue.frequency)
  • 48 line

change

while(n1->next != NULL && (n1->nodeValue).frequency < (newQnode->nodeValue).frequency)

to

while(n1->next != NULL && (n1->next->nodeValue).frequency < (newQnode->nodeValue).frequency)

Upvotes: 0

Ted Lyngmo
Ted Lyngmo

Reputation: 117238

I suggest that you simplify it:

  • Create an array of all the letters and the count for each letter.
  • Read one letter at a time from the file and increase the count for that letter.
  • After the whole file has been read, use qsort to sort the table.

Example:

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

// A struct to store a letter and its count
typedef struct {
    unsigned char letter;
    unsigned long count;
} letter_count_t;

// A function to compare two `letter_count_t`s to use with qsort:
int letter_count_t_comp(const void *vlhs, const void *vrhs) {
    const letter_count_t* lhs = vlhs;
    const letter_count_t* rhs = vrhs;

    if(lhs->count < rhs->count) return -1;
    if(lhs->count > rhs->count) return 1;
    return 0;
}

int main(int argc, char* argv[]) {
    if(argc != 2) return 1;

    // make a table of letter counts
    letter_count_t lc[1 << CHAR_BIT];  // very often 256

    // Assign a letter and count to each `letter_count_t` in the table:
    for(unsigned ch = 0; ch < (1 << CHAR_BIT); ++ch) {
        lc[ch].letter = ch;
        lc[ch].count = 0;
    }

    FILE *fp = fopen(argv[1], "r");
    if(fp) {
        int ch;

        // Read the file and increase the count for each letter
        while((ch = fgetc(fp)) != EOF) {
            ++lc[(unsigned char)ch].count;
        }
        fclose(fp);

        // Sort the table:
        qsort(lc, 1 << CHAR_BIT, sizeof *lc, letter_count_t_comp);

        // Display the result
        for(ch = 0; ch < (1 << CHAR_BIT); ++ch) {
            if(lc[ch].count) { // Skip letters that didn't occur in the file
                printf("%c %lu\n", isgraph(lc[ch].letter) ? lc[ch].letter : ' ', 
                                   lc[ch].count);
            }
        }
    }
}

Upvotes: 2

Related Questions