Implementación de la cola prioritaria en C. (para Huffman Coding) -- ampo con compression campo con priority-queue camp codereview Relacionados El problema

Priority queue implementation on C. (For Huffman Coding)


2
vote

problema

Español

Intento implementar los códigos Huffman en C. y, dado que mi intento anterior falló, decidí acercarme al problema de manera más responsable. ¡Así que estoy solicitando comentarios sobre mi implementación de la cola prioritaria en C. En primer lugar, ¡el diseño de estructuras e interfaces es importante para mí! Además, ¿qué tan fácil sería implementar un árbol Huffman usando esta estructura? Y, por supuesto, ¿qué pasa con la descomposición?

priority_queue.h

  #ifndef PRIORITY_QUEUE #define PRIORITY_QUEUE #include <stdlib.h> struct pq_node {     unsigned long frequency;     struct pq_node *parent;  //Pointers for Huffman tree     struct pq_node *left;     struct pq_node *right;     char symbol; };  struct priority_queue {     struct pq_node *heap_on_array;     size_t size;     size_t capacity; };  void init_queue(struct priority_queue **pq, size_t capacity);  void shift_up(struct priority_queue **pq, int i);  // i - index  void shift_down(struct priority_queue **pq, size_t i);  // i - index  struct pq_node extract_min(struct priority_queue **pq);  void insert(struct priority_queue **pq, char symbol);  void insert_element(struct priority_queue **pq, char symbol, unsigned long frequency);  void node_swap(struct pq_node *first, struct pq_node *second);   

priority_queue.c

  BigDecimal orderPrice = order.getSide() == Side.ASK ? calcAskPrice(order) : calcBidPrice(order) 0  
Original en ingles

I trying to implement Huffman Codes on C. And, since my previous attempt failed, I decided to approach the issue more responsibly. So I'm asking for feedback on my implementation of the priority queue on C. First of all, the design of structures and interfaces is important to me! Also, how easy would it be to implement a Huffman tree using this structure? And of course, what about decomposition?

priority_queue.h

#ifndef PRIORITY_QUEUE #define PRIORITY_QUEUE #include <stdlib.h> struct pq_node {     unsigned long frequency;     struct pq_node *parent;  //Pointers for Huffman tree     struct pq_node *left;     struct pq_node *right;     char symbol; };  struct priority_queue {     struct pq_node *heap_on_array;     size_t size;     size_t capacity; };  void init_queue(struct priority_queue **pq, size_t capacity);  void shift_up(struct priority_queue **pq, int i);  // i - index  void shift_down(struct priority_queue **pq, size_t i);  // i - index  struct pq_node extract_min(struct priority_queue **pq);  void insert(struct priority_queue **pq, char symbol);  void insert_element(struct priority_queue **pq, char symbol, unsigned long frequency);  void node_swap(struct pq_node *first, struct pq_node *second); 

priority_queue.c

#include "priority_queue.h" void init_queue(struct priority_queue **pq, size_t capacity) {     (*pq) = malloc(sizeof(struct priority_queue));     (*pq)->heap_on_array = malloc(sizeof(struct pq_node) * capacity);     (*pq)->capacity = capacity;     (*pq)->size = 0; };  void shift_up(struct priority_queue **pq, int i) {     while ((*pq)->heap_on_array[i].frequency < (*pq)->heap_on_array[(i-1)/2].frequency)     {         node_swap(&((*pq)->heap_on_array[i]), &((*pq)->heap_on_array[(i-1)/2]));         i = (i - 1) / 2;     } }  void shift_down(struct priority_queue **pq, size_t i) {     while ((2 * i + 1) < (*pq)->size)     {         size_t left = 2 * i + 1;         size_t right = 2 * i + 2;         size_t j = left;         if((right < (*pq)->size) && ((*pq)->heap_on_array[right].frequency < (*pq)->heap_on_array[left].frequency))         {             j = right;         }         if((*pq)->heap_on_array[i].frequency <= (*pq)->heap_on_array[j].frequency)         {             break;         }         node_swap(&((*pq)->heap_on_array[i]), &((*pq)->heap_on_array[j]));         i = j;     } }  struct pq_node extract_min(struct priority_queue **pq) {     struct pq_node tmp = (*pq)->heap_on_array[0];     (*pq)->heap_on_array[0] = (*pq)->heap_on_array[(*pq)->size - 1];     (*pq)->size--;     shift_down(pq, 0);     return tmp; }  void insert(struct priority_queue **pq, char symbol) {     for(size_t i = 0; i < (*pq)->size; ++i)     {         if((*pq)->heap_on_array[i].symbol == symbol)         {             (*pq)->heap_on_array[i].frequency++;             shift_down(pq, i);             return;         }     }          if((*pq)->size == (*pq)->capacity)     {         (*pq)->heap_on_array = reallocarray((*pq)->heap_on_array, (*pq)->size * 2, sizeof(struct pq_node));         (*pq)->capacity = (*pq)->capacity * 2;     }     (*pq)->size++;     (*pq)->heap_on_array[(*pq)->size - 1].symbol = symbol;     (*pq)->heap_on_array[(*pq)->size - 1].frequency = 1;     shift_up(pq, (*pq)->size - 1); }  void insert_element(struct priority_queue **pq, char symbol, unsigned long frequency) {     for(size_t i = 0; i < (*pq)->size; ++i)     {         if((*pq)->heap_on_array[i].symbol == symbol)         {             (*pq)->heap_on_array[i].frequency = frequency;             shift_down(pq, i);             return;         }     }      if((*pq)->size == (*pq)->capacity)     {         (*pq)->heap_on_array = reallocarray((*pq)->heap_on_array, (*pq)->size * 2, sizeof(struct pq_node));         (*pq)->capacity = (*pq)->capacity * 2;     }     (*pq)->size++;     (*pq)->heap_on_array[(*pq)->size - 1].symbol = symbol;     (*pq)->heap_on_array[(*pq)->size - 1].frequency = frequency;     shift_up(pq, (*pq)->size - 1); }  void node_swap(struct pq_node *first, struct pq_node *second) {     struct pq_node tmp = *first;     *first = *second;     *second = tmp; } ``` 
        

Lista de respuestas

4
 
vote
  • Evite los punteros dobles. Son absolutamente injustificados en todas las funciones (excepto init , pero vea abajo).

  • Prefiero devolver un valor a un efecto secundario. En el código del cliente, que supongo que está a lo largo de las líneas de

        struct priority_queue * pq;   init_queue(&pq, capacity);   

    Tengo que leer la fuente de init_queue para ver que hay un efecto secundario de modificar el parámetro que pasé. Compararlo con una asignación clara:

        struct priority_queue * pq;   pq = init_queue(capacity);   
  • SIEMPRE PRUEBA LO QUE malloc devuelve, y devuelva NULL inmediatamente si falla. Ídem para reallocarray .

    también, el ciego

        (*pq)->heap_on_array = reallocarray((*pq)->heap_on_array, (*pq)->size * 2, sizeof(struct pq_node));   

    conduce a una pérdida de memoria en caso de falla: se pierde el puntero al bloque original, y no puede ser 99887776655443310 D. Típicamente uno lo haría

      BigDecimal orderPrice = order.getSide().ifAsk(calcAskPrice(order)).ifBid(calcBidPrice(order)).elseFail() 1  
  • Sin bucles desnudos. Cada bucle implementa un algoritmo importante, y merece un nombre. En su caso, el bucle inicial de BigDecimal orderPrice = order.getSide().ifAsk(calcAskPrice(order)).ifBid(calcBidPrice(order)).elseFail() 2 es seguramente

      BigDecimal orderPrice = order.getSide().ifAsk(calcAskPrice(order)).ifBid(calcBidPrice(order)).elseFail() 3  
  • seco. BigDecimal orderPrice = order.getSide().ifAsk(calcAskPrice(order)).ifBid(calcBidPrice(order)).elseFail() 4 y BigDecimal orderPrice = order.getSide().ifAsk(calcAskPrice(order)).ifBid(calcBidPrice(order)).elseFail() 5 son sospechosamente similares. La única diferencia está en el tratamiento de BigDecimal orderPrice = order.getSide().ifAsk(calcAskPrice(order)).ifBid(calcBidPrice(order)).elseFail() 6 . La funcionalidad común se facturará en una función.

 
  • Avoid double pointers. They are absolutely unwarranted in all the functions (except init, but see below).

  • Prefer returning a value to a side effect. In the client code, which I presume is along the lines of

      struct priority_queue * pq;   init_queue(&pq, capacity); 

    I have to read the source of init_queue to see that there is a side effect of modifying the parameter I passed. Compare it to a clear assignment:

      struct priority_queue * pq;   pq = init_queue(capacity); 
  • Always test what malloc returns, and return NULL immediately if it fails. Ditto for reallocarray.

    Also, the blind

      (*pq)->heap_on_array = reallocarray((*pq)->heap_on_array, (*pq)->size * 2, sizeof(struct pq_node)); 

    leads to a memory leak in case of failure: the pointer to the original block is lost, and it cannot be freed. Typically one would

      temp = reallocarray(...);   if (temp == NULL) {       // handle_error, e.g. free(pq->heap_on_array);       return;   }   pq->heap_on_array = temp; 
  • No naked loops. Every loop implements an important algorithm, and deserves a name. In your case, the initial loop of insert_* is surely

      pq_node * find(priority_queue * pq, char symbol); 
  • DRY. insert and insert_element are suspiciously similar. The only difference is in treating frequency. The common functionality shall be factored out into a function.

 
 
 
 
2
 
vote

en la función:

  BigDecimal orderPrice = order.getSide().ifAsk(calcAskPrice(order)).ifBid(calcBidPrice(order)).elseFail() 7  

Después de la preparación final de cierre "}" hay un punto y coma ';'. Esto se traduce en la salida del compilador:

  BigDecimal orderPrice = order.getSide().ifAsk(calcAskPrice(order)).ifBid(calcBidPrice(order)).elseFail() 8  

También hay algunas advertencias sobre las conversiones implícitas.

Al compilar, siempre habilite las advertencias, luego corrija esas advertencias.

Para BigDecimal orderPrice = order.getSide().ifAsk(calcAskPrice(order)).ifBid(calcBidPrice(order)).elseFail() 9 , a un uso mínimo:

  init0  

NOTA: Otros compiladores utilizan diferentes opciones para producir los mismos resultados.

El archivo: init1 Falta la declaración:

  init2  

al final del archivo. ¡Así que no compila!

 

in function:

void init_queue(struct priority_queue **pq, size_t capacity) 

after the final closing brace '}' there is a semicolon ';'. This results in the compiler outputting:

untitled1.c:41:2: warning: ISO C does not allow extra xe2x80x98;xe2x80x99 outside of a function [-Wpedantic] 

There are also some warnings about implicit conversions.

When compiling, always enable the warnings, then fix those warnings.

for gcc, at a minimum use:

-Wall -Wextra -Wconversion -pedantic -std=gnu11  

Note: other compilers use different options to produce the same results.

the file: priority_queue.h is missing the statement:

#endif 

at the end of the file. So it does not compile!

 
 

Relacionados problema

0  Cola de prioridad mínima utilizando la lista vinculada individualmente  ( Minimum priority queue using singly linked list ) 
He escrito este código para la cola prioritaria utilizando una lista de enlaces individuales. Quiero mejorar este código. ¿Hay algún otro método para escribir...

1  El algoritmo de Dijkstra no es lo suficientemente optimizado  ( Dijkstras algorithm not optimized enough ) 
Estaba intentando una pregunta sobre el alcance 2 más corto de Hackerrank-Dijkstra, al enviar mis programas en los casos de prueba 3/7. Uno de los casos de pr...

0  Un simulador de juego de tarjeta simple  ( A simple card game simulator ) 
Esta es una pregunta de tarea, y he escrito el código, pero no estaba seguro de si había elegido la estructura de datos correctos para este trabajo y la compl...

0  Comparación de nodos usando la cola prioritaria para el algoritmo de ruta más corto de DIJKSTRA  ( Node comparison using priority queue for dijkstras shortest path algorithm ) 
En lugar de usar un MinHeap que me permitirá cambiar las prioridades de vértice. Estoy usando la biblioteca Java 9988777665544331 . Aquí es cómo he imple...

1  Cola de prioridad mínima usando un montón  ( Minimum priority queue using heap ) 
Después de obtener sugerencias para cola máxima prioridad he escrito el programa para un mínimo Cola de prioridad. Ayúdame a mejorar este código. #includ...

11  Líneas más largas usando la cola de prioridad  ( Longest lines using priority queue ) 
inspirado en un comentario en esta pregunta , pensé que ejercería mi C habilidades implementando algo como usando una cola prioritaria. La idea es poder in...

5  Comparando los solversadores de rompecabezas en Java  ( Comparing puzzle solvers in java ) 
Tengo este programa que resuelve un $ (n ^ 2 - 1) $ - rompecabezas para el general $ n $. Tengo tres solucionadores: BidirectionalBFSPathFinder AS...

4  ObservablepriorityQueue <t> implementación  ( Observablepriorityqueuet implementation ) 
Tengo un requisito en mi proyecto actual que necesitará una cola priorizada que admite la interfaz IOBServable. Por favor, notifíqueme cualquier problema con ...

5  Implementación de la cola prioritaria en C #  ( Priority queue implementation in c ) 
Mi aplicación tiene un hilo para el manejo de inserciones y actualizaciones de la base de datos. Los datos se añaden por otras roscas a una cola genérica en e...

4  Cola máxima de prioridad utilizando un montón  ( Maximum priority queue using heap ) 
He escrito este programa para la cola de prioridad máxima después de estudiar desde introducción al algoritmo . Quiero mejorar mi código. ¿Hay algún otro mét...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos