/* Huffman coding is widely used in video audio and image compression. * It can greatly reduce the size of files. The following codes show the * basic principle of huffman coding. * by: double; version:0.1;date:2009-08-01 */ #include "/usr/c/head.h" #define INT_MAX ((int)(~0U >> 1)) #define MAX 100 typedef struct huffman_tree_node { unsigned int weight; unsigned int parent, lchild, rchild; }huffman_tree_node, *huffman_tree; typedef char ** huffman_code; status get_child(huffman_tree p, int n, int *c1, int *c2) { int i, temp, m, min; m = 0; min = INT_MAX; for (i = 1; i < n; ++i) if (p[i].parent == 0 && min > p[i].weight) { /* Here, "p" is a pointer variable, inertia made me write "min > p->weight" at some time in the past. * So, I should open my eyes. */ m = i; min = p[i].weight; } *c1 = m; m = 0; min = INT_MAX; for (i = 1; i < n; ++i) if (p[i].parent == 0 && min > p[i].weight && i != *c1) { m = i; min = p[i].weight; } *c2 = m; if (*c1 > *c2) { temp = *c1; *c1 = *c2; *c2 = temp; } return OK; } status huffman_coding(huffman_tree *HT, huffman_code *HC, int *w, int n) { int i, m, c1, c2, start, c, f; huffman_tree p; char * cd; m = 2 * n - 1; *HT = (huffman_tree)malloc(sizeof(huffman_tree_node) * (m + 1)); if (!(*HT)) exit(OVERFLOW); /* There is close contact between the following "for" statement. * once, I wrote the first for loops like this: "for (i = 0, p = *HT + 1; i < n; ++i, ++p, ++w)". * and the second for loops keep the same like the following. Gcc (version 4.0 in FC4) worked normally * when compiling. But when I executed, FC4 reported a segmentation fault.It is strange that, * in Visual C++ 6.0 and FC10 no faults are reported even if there is indeed a cross-border error. */ for (i = 1, p = *HT + 1; i <= n; ++i, ++p, ++w) { p->weight = *w; p->parent = p->lchild = p->rchild = 0; } for (; i <= m; ++i, ++p) p->weight = p->parent = p->lchild = p->rchild = 0; for (i = n + 1; i <= m; ++i) { get_child(*HT, i, &c1, &c2); (*HT)[i].lchild = c1; (*HT)[i].rchild = c2; (*HT)[i].weight = (*HT)[c1].weight + (*HT)[c2].weight; (*HT)[c1].parent = (*HT)[c2].parent = i; } *HC = (huffman_code)malloc(sizeof(char *) * (n + 1)); if (!(*HC)) exit(OVERFLOW); cd = (char *)malloc(sizeof(char) * n); if (!cd) exit(OVERFLOW); cd[n - 1] = '/0'; for (i = 1; i <= n; ++i) { start = n - 1 ; for (c = i, f = (*HT)[i].parent; f != 0; c = f, f = (*HT)[f].parent) { if ((*HT)[f].lchild == c) cd[--start] = '0'; else cd[--start] = '1'; } (*HC)[i] = (char *)malloc(sizeof(char) * (n - start)); if (!(*HC)[i]) exit(OVERFLOW); strcpy((*HC)[i], cd + start); } free(cd); /* After malloc , a clear free is needed.*/ return OK; } status print_code(huffman_code HC, int n) { int i; for (i = 1; i <= n; ++i) printf("%s/n", HC[i]); return OK; } int main(void) { huffman_tree HT; huffman_code HC; int temp, n, weight[MAX], i; printf("How many:"); SCAN_INT(n, temp); if (n <= 1 || n > MAX - 1) { printf("No need or input error!/n"); exit(ERROR); } for (i = 1; i <= n; ++i) { printf("No.%d:", i); SCAN_INT(weight[i], temp); } huffman_coding(&HT, &HC, weight + 1, n); printf("The huffman code are:/n"); print_code(HC, n); return 0; }