以前没事的时候写的,c++写的,原理很简单,代码如下:
1 #include <cstdio> 2 #include <cstdlib> 3 #include <iostream> 4 #include <string> 5 //#include <bitset> 6 #include <fstream> 7 #include <ctime> 8 9 const int maxCodeNum = 256; 10 11 using namespace std; 12 13 //哈夫曼树的树节点 14 struct HaffTreeNode{ 15 HaffTreeNode * lNode; 16 HaffTreeNode * rNode; 17 string haffCode; 18 int value; 19 int alpha; 20 HaffTreeNode() 21 :lNode(NULL), rNode(NULL), haffCode(""), value(0), alpha(0){;} 22 }; 23 24 //链表节点,用于生成哈夫曼树 25 struct ListNode{ 26 struct HaffTreeNode HaffTreeNode; 27 ListNode *nextListNode; 28 ListNode() 29 :nextListNode(NULL){;} 30 }; 31 32 //用与保存输入文件统计信息的hash表 33 typedef struct HashTable{ 34 int value; 35 int alpha; 36 HashTable() 37 :value(0), alpha(0){} 38 //比较函数用于排序使用 39 inline friend int operator-(const HashTable & a, const HashTable & b){ 40 return a.value - b.value; 41 } 42 } HashTable; 43 HashTable charHashTable[maxCodeNum]; 44 45 46 //排序使用的比较大小的函数 47 int hashComp(const void * a, const void * b) 48 { 49 return *((HashTable *)a) - *((HashTable *)b); 50 } 51 52 53 //创建一个哈夫曼树 54 HaffTreeNode * createHaffTreeNodeTree(HashTable table[]) 55 { 56 ListNode *root = new ListNode; 57 ListNode *next = root; 58 for(int i = 0; /*i < maxCodeNum - 1*/; ++i){ 59 if(table[i].value == 0)//如果对应的码不为0,就为其分配一个树节点 60 continue; 61 next->HaffTreeNode.alpha = table[i].alpha; 62 next->HaffTreeNode.value = table[i].value; 63 if(i ==maxCodeNum - 1) 64 break; 65 next->nextListNode = new ListNode; 66 next = next->nextListNode; 67 } 68 69 while(root->nextListNode != NULL){ 70 ListNode * currNode = new ListNode; 71 currNode->HaffTreeNode.value = root->HaffTreeNode.value + root->nextListNode->HaffTreeNode.value; 72 currNode->HaffTreeNode.lNode = &(root->HaffTreeNode); 73 currNode->HaffTreeNode.rNode = &(root->nextListNode->HaffTreeNode); 74 root = root->nextListNode->nextListNode; //概率最小的两个码相加组成一个新的节点 75 76 ListNode * nextNode = root; 77 ListNode * prevNode = NULL; 78 while(nextNode != NULL && currNode->HaffTreeNode.value > nextNode->HaffTreeNode.value){ 79 prevNode = nextNode; 80 nextNode = nextNode->nextListNode; 81 } 82 83 if(prevNode == NULL){//将这个新的节点插入到所有节点之前(currNode目前还是最小的) 84 currNode->nextListNode = nextNode; 85 root = currNode; 86 }else{//插入到节点中间或者节点之后的位置 87 prevNode->nextListNode = currNode; 88 currNode->nextListNode = nextNode; 89 } 90 }//在这个list中所有的元素遍历完成之后返回 91 return &(root->HaffTreeNode);//返回书的根节点的哈弗满节点,这个节点已经构造成为了一棵树 92 } 93 94 string huffmanCodeTable[maxCodeNum]; 95 string haffCode; 96 97 //给哈夫曼树编码 98 void createHaffmanTable(HaffTreeNode * root) 99 { 100 if(root->lNode == NULL && root->rNode == NULL){ 101 huffmanCodeTable[root->alpha] = haffCode; 102 haffCode.erase(haffCode.length() - 1); 103 return; 104 }//给各个节点赋予相应的哈夫曼编码 105 haffCode.append("0"); 106 createHaffmanTable(root->lNode); 107 108 haffCode.append("1"); 109 createHaffmanTable(root->rNode); 110 111 if(!haffCode.empty()){ 112 haffCode.erase(haffCode.length() - 1); 113 } 114 return; 115 } 116 117 //将生成的二进制长串编码转换成字符用于存储在压缩文件中 118 unsigned char StrToBin(string str) 119 { 120 unsigned int ans =0; 121 int tmpNum = atoi(str.c_str()); 122 int multiNum = 1; 123 while(tmpNum != 0){ 124 ans += tmpNum%10*multiNum; 125 tmpNum/=10; 126 multiNum *= 2; 127 } 128 return (unsigned char) ans; 129 } 130 131 //用于将压缩文件的字符转换成huffman编码 132 string BinToStr(unsigned char c) 133 { 134 string tmpNumStr; 135 while(c != 0){ 136 tmpNumStr.insert(tmpNumStr.begin(), (unsigned char)(c%2 + '0')); 137 c /= 2; 138 } 139 if(tmpNumStr.length() < 8){ 140 tmpNumStr.insert(tmpNumStr.begin(), 8 - tmpNumStr.length(), '0'); 141 } 142 return tmpNumStr; 143 } 144 145 //下面是将huffman码译成原字符的程序 146 char huffDecode(HaffTreeNode * root, string & code) 147 { 148 unsigned int i; 149 for( i = 0; i < code.length(); ++i){ 150 if(root->alpha == 0) 151 root = (code[i] - '0')?root->rNode:root->lNode; 152 else{ 153 code.erase(0, i); 154 return root->alpha; 155 } 156 } 157 if(root->alpha !=0){ 158 code.erase(0, i); 159 return root->alpha; 160 } 161 code.clear(); 162 return '