1) replace your if-else-cascade in
void fa_z(FILE *fp)
with a switch-statement.
2) replace the switch-statement in
void fa_z(FILE *fp)
with an array or dictionary
*
and no case-distinction at all.
3) sort the result of
void fa_z(FILE *fp)
by frequency.
4) build a huffman-tree from the frequency-results.
5) iterate the input-file byte-by-byte and build a compressed outputstream by replacing the input-bytes by their bit-representation that results from walking the huffman-tree to the according input-byte-value.
6) save the huffman-tree along with the compressed outputstream in a file.
7) build the decompression-function.
Edit:
*
: and use the value of the input-byte as the array-index / as the dictionary-key instead of having manually assigned indices for all different input-byte-values.
The duplicate replacement suggestion of points 1+2 isn't meant seriously. But you should use switch-statements (not in this case!) instead of very long if-else if-statements whenever the predicate is suitable for the switch-statement.
Further reading:
http://en.wikipedia.org/wiki/Huffman_coding[
^]
https://www.siggraph.org/education/materials/HyperGraph/video/mpeg/mpegfaq/huffman_tutorial.html[
^]
Another Edit:
Solution 2 demonstrates what I meant by the note above marked with
*