一步一步写算法(之哈夫曼树 下)

来源:互联网 发布:淘宝炉石卡包为何便宜 编辑:程序博客网 时间:2024/05/21 05:38

原贴地址:http://blog.csdn.net/feixiaoxing/article/details/6963136

【 声明:版权所有,欢迎转载,请勿用于商业用途。  联系信箱:feixiaoxing @163.com】


    前面说到了哈夫曼树的创建,那下面一个重要的环节就是哈夫曼树的排序问题。但是由于排序的内容是数据结构,因此形式上说,我们需要采用通用数据排序算法,这在我之前的博客里面已经涉及到了(通用算法设计)。所以,我们所要做的就是编写compare和swap两个函数。通用冒泡代码如下所示,

[cpp] view plaincopy
  1. void bubble_sort(void* array[], int length, int (*compare)(void*, void*), void(*swap)(void**, void**))  
  2. {  
  3.     int outer;  
  4.     int inner;  
  5.       
  6.     for(outer = length -1; outer >0; outer --){  
  7.         for(inner = 0; inner < outer; inner ++){  
  8.             if(compare(array[inner], array[inner + 1]))  
  9.                 swap(&array[inner], &array[inner + 1]);  
  10.         }  
  11.     }  
  12.       
  13.     return;  
  14. }  

    compare和swap代码如下所示,

[cpp] view plaincopy
  1. int compare (void* a, void* b)  
  2. {  
  3.     HUFFMAN_NODE* node1 = (HUFFMAN_NODE*)a;  
  4.     HUFFMAN_NODE* node2 = (HUFFMAN_NODE*)b;  
  5.   
  6.     return node1->frequence > node2->frequence ? 1 : 0;  
  7. }  
  8.   
  9. void swap(void** a, void** b)  
  10. {  
  11.     HUFFMAN_NODE* median;  
  12.     HUFFMAN_NODE** node1 = (HUFFMAN_NODE**)a;  
  13.     HUFFMAN_NODE** node2 = (HUFFMAN_NODE**)b;  
  14.   
  15.     median = *node1;  
  16.     *node1 = *node2;  
  17.     *node2 = median;  
  18. }  

    有了创建函数和排序函数,那么哈夫曼树就可以创建了,

[cpp] view plaincopy
  1. HUFFMAN_NODE* create_huffman_tree(HUFFMAN_NODE* huffmanNode[], int length)  
  2. {  
  3.     HUFFMAN_NODE* head = NULL;  
  4.   
  5.     if(NULL == huffmanNode ||  length <= 1)  
  6.         return NULL;  
  7.   
  8.     while(length > 1){  
  9.         bubble_sort((void**)huffmanNode, length, compare, swap);  
  10.         head = create_new_node('\0',  huffmanNode[0]->frequence + huffmanNode[1]->frequence);  
  11.         assert(NULL != head);  
  12.   
  13.         head->left = huffmanNode[0];  
  14.         head->right = huffmanNode[1];  
  15.         huffmanNode[0]->parent = head;  
  16.         huffmanNode[0]->symbol = 1;  
  17.         huffmanNode[1]->parent = head;  
  18.         huffmanNode[1]->symbol = 0;  
  19.   
  20.         memmove(&huffmanNode[0], &huffmanNode[2], sizeof(HUFFMAN_NODE*) * (length -2));  
  21.         huffmanNode[length -2] = head;  
  22.         length --;  
  23.     }  
  24.   
  25.     return head;  
  26. }  
    上面的代码完整了写出了huffman树的创建过程,那么我们怎么知道符号的编码是多少呢?这其实不难,因为根节点都知道了,我们只要按照自下而上的顺序遍历节点就可以打印出编码,只不过编码是逆序的而已,

[cpp] view plaincopy
  1. void print_code_for_str(HUFFMAN_NODE* pNode, HUFFMAN_NODE* head)  
  2. {  
  3.     if(NULL == pNode || NULL == head)  
  4.         return;  
  5.   
  6.     while(head != pNode){  
  7.         printf("%d", pNode->symbol);  
  8.         pNode = pNode->parent;  
  9.     }  
  10.   
  11.     return;  
  12. }  

    如果对代码本身还有怀疑,可以编译一个测试用例验证一下,

[cpp] view plaincopy
  1. void test()  
  2. {  
  3.     HUFFMAN_NODE* node1 = NULL;  
  4.     HUFFMAN_NODE* node2 = NULL;  
  5.     HUFFMAN_NODE* node3 = NULL;  
  6.     HUFFMAN_NODE* node4 = NULL;  
  7.   
  8.     HUFFMAN_NODE* test[] = {node1 = create_new_node('a', 0.1),  
  9.         node2 = create_new_node('b', 0.2),  
  10.         node3 = create_new_node('c', 0.3),  
  11.         node4 = create_new_node('d', 0.4),  
  12.     };  
  13.   
  14.     HUFFMAN_NODE* head = create_huffman_tree(test, sizeof(test)/sizeof(HUFFMAN_NODE*));  
  15.     print_code_for_str(node1, head);  
  16.     print_code_for_str(node2, head);  
  17.     print_code_for_str(node3, head);  
  18.     print_code_for_str(node4, head);  
  19. }  


总结:

    (1)哈夫曼树不复杂,如果手算可以成功,那么编程应该也没有什么问题

    (2)复杂算法都是由小算法搭积木而成的,朋友们应该在基本算法上打下坚实的基础

    (3)算法注意复用,这里就用到了原来讲到的通用算法内容



0 0