huffman树即Huffma编码的实现
自己写的Huffman树生成与Huffman编码实现 (实现了核心功能 ,打出了每个字符的huffman编码 其他的懒得实现了,有兴趣的朋友可以自己在我的基础增加功能 )
/* 原创文章 转载请附上原链接: https://www.cnblogs.com/jiujue/p/10325699.html */
### 硬核警告 递归 玩的可以在往下看 核心是递归实现 ¥_¥
上图:
上代码:(思路:通过递归将父亲的Huffman编码传给给孩子 孩子以此为基础进行在编码 )
1.头文件:(myHuffmanHead.h)
1 #pragma once 2 3 #pragma warning(disable :4996) 4 #include<stdio.h> 5 #include<stdlib.h> 6 #include<string.h> 7 8 /* 9 huffmanTree : 思路 10 注:每个关键字为一个节点 整个数据使用链表存储 11 节点内容 : 关键字 ,出现次数 ,编码 , 下一个节点。 12 13 将 关键字的出现频率作为权值来生成HuffmanTree 然后进行Huffman code 14 //1.获取关键字频率 15 1.1 获取输入 并 记录 关键字 出现次数 16 17 2.生成HuffmanTree 18 19 20 3.根据huffmanTree 进行HuffmanCode 并打印每个关键字的 Huffman编码 21 tips : 左 0 ; 右 1 22 */ 23 24 typedef struct nodehuffmantree { 25 26 char key; 27 int frequency; 28 29 char *code; 30 31 int isCoded; 32 33 struct nodehuffmantree * next; 34 struct nodehuffmantree *lchild, *rchild; 35 36 }nodeHuffmanTree_t; 37 38 int myStrCat(char *des, char *str); 39 40 int changeCode(char *strParent, char *strKid, char needAppend, char *tempspace); 41 42 int linkCode(nodeHuffmanTree_t *headLinkList, char *input); 43 44 int printLinkList(nodeHuffmanTree_t *head); 45 46 int makeBranch(nodeHuffmanTree_t **spaceSave, int spaceSize, int t1, int t2); 47 48 nodeHuffmanTree_t* isExitence(nodeHuffmanTree_t* head, char inputTemp); 49 50 int creatHuffmanTree(nodeHuffmanTree_t *headLinkList, nodeHuffmanTree_t **headhuffmanTree); 51 52 nodeHuffmanTree_t ** getSpaceSave(nodeHuffmanTree_t *headLinkList); 53 54 int huffmanCode(nodeHuffmanTree_t *headLinkList, nodeHuffmanTree_t *headhuffmanTree);
2主函数入口:(source_1.c)
1 #include"myHuffmanHead.h" 2 3 4 int main() 5 { 6 7 nodeHuffmanTree_t *head = NULL; 8 nodeHuffmanTree_t *headTree = NULL; 9 char *needcode; 10 printf("please input : \n"); 11 12 obtainIput(&head, &needcode); 13 14 creatHuffmanTree(head, &headTree); 15 16 huffmanCode(head, headTree); 17 18 printLinkList(head); 19 20 //linkCode(head, needcode); 21 22 system("pause"); 23 return 0; 24 }
10.获取输入:(obtainIput.c)
1 #include"myHuffmanHead.h" 2 3 4 int obtainIput(nodeHuffmanTree_t **head,char **input) 5 { 6 char tempInput; 7 nodeHuffmanTree_t **t1 = head; 8 nodeHuffmanTree_t *t2 = NULL; 9 10 tempInput = getc(stdin); 11 *input = tempInput; 12 while (tempInput !='\n') 13 { 14 if (!(t2= isExitence( (*head), tempInput))) 15 { 16 nodeHuffmanTree_t *nodeTempHuffman = (nodeHuffmanTree_t *)malloc(sizeof(nodeHuffmanTree_t)); 17 18 (*t1) = nodeTempHuffman; 19 20 nodeTempHuffman->key = tempInput; 21 nodeTempHuffman->frequency = 1; 22 nodeTempHuffman->next = NULL; 23 nodeTempHuffman->lchild = NULL; 24 nodeTempHuffman->rchild = NULL; 25 nodeTempHuffman->isCoded = 0; 26 t1 = &((*t1)->next); 27 tempInput = getc(stdin); 28 } 29 else 30 { 31 t2->frequency++ ; 32 tempInput = getc(stdin); 33 continue; 34 } 35 } 36 return 0; 37 }
3.创建一个Huffman树:(creatHuffmanTree.c)
1 #include"myHuffmanHead.h" 2 3 4 /* 5 1.1 先遍历 链表 计算有几个需要编码 6 1.2 创建一个空间 来存储 需要被编码的节点 并在每次编码后将编码后的过的删除 替换成 parent 7 */ 8 9 static nodeHuffmanTree_t **spaceSave = NULL; 10 11 12 nodeHuffmanTree_t ** getSpaceSave(nodeHuffmanTree_t *headLinkList) 13 { 14 nodeHuffmanTree_t *t1 = headLinkList; 15 16 int n = 0; 17 int i = 1; 18 19 while (t1 != NULL) 20 { 21 n++; 22 t1 = t1->next; 23 } 24 25 spaceSave = (nodeHuffmanTree_t*)malloc(sizeof(nodeHuffmanTree_t*)*n + 1); 26 27 t1 = headLinkList; 28 29 while (i < n + 1) 30 { 31 spaceSave[i] = t1; 32 ++i; 33 t1 = t1->next; 34 } 35 36 (int)spaceSave[0] = n; 37 38 return n; 39 } 40 41 int creatHuffmanTree(nodeHuffmanTree_t *headLinkList, nodeHuffmanTree_t **headhuffmanTree) 42 { 43 //nodeHuffmanTree_t **spaceSave = NULL; 44 45 int n = getSpaceSave(headLinkList); 46 int n2 = (int)spaceSave[0]; 47 48 while (n2 > 1) 49 { 50 51 int t1, t2; 52 53 getMinTwo(spaceSave, n, &t1, &t2); 54 55 56 makeBranch(spaceSave, n, t1, t2); 57 58 n2--; 59 } 60 61 while (n >= 1) 62 { 63 if (spaceSave[n] != NULL) 64 { 65 *headhuffmanTree = spaceSave[n]; 66 break; 67 } 68 else 69 { 70 n--; 71 } 72 } 73 74 return 0; 75 }
5.实现对huffman树的Huffman编码:
(huffmanCode.c)//先后顺序以代码为主 &_&
1 #include"myHuffmanHead.h" 2 3 4 5 /* 6 7 递归 每次向下递归是 向左递归 传0 向右传1 8 每次接受并改掉 '\0' 为传的 0或1 然后追加 '\0'; 9 每次传个n来记录编码空间长度 n+1 10 11 */ 12 int huffmanCode(nodeHuffmanTree_t *headLinkList, nodeHuffmanTree_t *headhuffmanTree) 13 { 14 headhuffmanTree->code = (char*)malloc(2); 15 16 *(headhuffmanTree->code) = '\0'; 17 18 huffmanCode_(headhuffmanTree, headhuffmanTree->lchild, '0', 1); 19 huffmanCode_(headhuffmanTree, headhuffmanTree->rchild, '1', 1); 20 } 21 22 int huffmanCode_(nodeHuffmanTree_t *parenthuffmanTree, nodeHuffmanTree_t *nexthuffmanTree, char tempCode, int layer) 23 { 24 if (NULL == nexthuffmanTree) 25 { 26 return 0; 27 } 28 else 29 { 30 char *tempSpace = (char*)malloc(sizeof(parenthuffmanTree->code)); 31 32 nexthuffmanTree->code = (char*)malloc(layer+2); 33 34 changeCode(parenthuffmanTree->code, nexthuffmanTree->code, tempCode, tempSpace); 35 36 huffmanCode_(nexthuffmanTree, nexthuffmanTree->lchild, '0', layer + 1); 37 38 huffmanCode_(nexthuffmanTree, nexthuffmanTree->rchild, '1', layer + 1); 39 40 } 41 }
5.1.获取一个最小key的节点是个子功能:(getMinTwo.c)
1 #include"myHuffmanHead.h" 2 3 4 static int flag = 0; 5 6 int getMinTwo(nodeHuffmanTree_t **spaceSave,int spaceSize ,int *t1, int *t2) 7 { 8 9 int i = 0; 10 int j = 0; 11 12 while (i<2) 13 { 14 int min = 1; 15 j = 0; 16 17 while (j+1 < spaceSize) 18 { 19 if (NULL==spaceSave[1 + j]) 20 { 21 j++; 22 continue; 23 } 24 if (0 == spaceSave[1 + j]->isCoded) 25 { 26 min = 1 + j; 27 break; 28 } 29 else 30 { 31 j++; 32 } 33 } 34 35 for (j= 0; j < spaceSize; ++j) 36 { 37 if (NULL == spaceSave[min] || NULL == spaceSave[1 + j]) 38 { 39 continue; 40 } 41 if (spaceSave[min]->frequency > spaceSave[1 + j]->frequency && spaceSave[1 + j]->isCoded !=1) 42 { 43 min = 1 + j; 44 } 45 } 46 47 spaceSave[min]->isCoded = 1; 48 49 if (0 == flag) 50 { 51 *t1 = min; 52 flag++; 53 } 54 else 55 { 56 *t2 = min; 57 flag--; 58 } 59 60 i++; 61 } 62 63 64 }
5.2.判断是否已经编码:(isExitence.c)
1 #include"myHuffmanHead.h" 2 3 4 nodeHuffmanTree_t* isExitence(nodeHuffmanTree_t* head, char inputTemp) 5 { 6 int i = 0; 7 8 if (NULL == head) 9 { 10 return NULL; 11 } 12 else 13 { 14 15 16 if((head->key==inputTemp)) 17 { 18 return head; 19 } 20 else 21 { 22 isExitence(head->next, inputTemp); 23 } 24 } 25 }
5.3.创建分支:(makebranch.c)
1 #include"myHuffmanHead.h" 2 3 int makeBranch(nodeHuffmanTree_t **spaceSave, int spaceSize, int t1, int t2) 4 { 5 6 nodeHuffmanTree_t *newNode = (nodeHuffmanTree_t*)malloc(sizeof(nodeHuffmanTree_t)); 7 8 newNode->frequency = spaceSave[t1]->frequency + spaceSave[t2]->frequency; 9 newNode->isCoded = 0; 10 11 newNode->lchild = spaceSave[t1]; 12 newNode->rchild = spaceSave[t2]; 13 14 spaceSave[t1] = newNode; 15 spaceSave[t2] = NULL; 16 17 }
5.4.实现拼接孩子的编码:(changeCode.c)
1 #include"myHuffmanHead.h" 2 3 4 int changeCode(char *strParent, char *strKid, char needAppend, char *tempspace) 5 { 6 strcpy(tempspace, strParent); 7 8 char *tempP = tempspace; 9 10 while (1) 11 { 12 if (*tempP == '\0') 13 { 14 *tempP = needAppend; 15 16 *(tempP + 1) = '\0'; 17 18 strcpy(strKid, tempspace); 19 20 break; 21 } 22 else 23 { 24 ++tempP; 25 } 26 } 27 return 0; 28 }
5.5.拼接Huffman编码:(myStrCat.c)
1 #include"myHuffmanHead.h" 2 3 int myStrCat(char *des, char *str) 4 { 5 char *needCatP = des; 6 7 while (1) 8 { 9 if (*needCatP == '\0') 10 { 11 *needCatP = str; 12 13 *(needCatP + 1) = '\0'; 14 15 break; 16 } 17 else 18 { 19 ++needCatP; 20 } 21 } 22 return 0; 23 }
6.打印huffman编码:(printLinkList.c)
1 #include"myHuffmanHead.h" 2 3 int printLinkList(nodeHuffmanTree_t *head) 4 { 5 printf(" Key\t Frequncy\t HuffmanCode\n\n"); 6 while (head != NULL) 7 { 8 printf(" %c\t %d\t %s\n", head->key, head->frequency, head->code); 9 10 head = head->next; 11 } 12 }
结语:有问题欢迎提在下方 ,本人在校学生,时间较为充裕, 有时间会回复的。
/* 原创文章 转载请附上原链接: https://www.cnblogs.com/jiujue/p/10325699.html */