c语言静态三叉链表构造一棵Huffman树并求其编码
c语言 哈夫曼树哈夫曼编码
c语言哈夫曼树哈夫曼编码哈夫曼树(Huffman Tree)和哈夫曼编码(Huffman Coding)是由戴维·哈夫曼在1952年为数据压缩应用而发明的。
哈夫曼编码是一种前缀编码,即任何字符的编码都不是另一个字符的编码的前缀。
在编码学中,哈夫曼编码是一种可变长度编码,其中较常见或较频繁的字符使用较短的编码,而较少见或较不频繁的字符使用较长的编码。
这种编码是由哈夫曼树生成的,哈夫曼树是一种特殊的二叉树,其每个节点的权重等于其左子树和右子树的权重之和。
在C语言中实现哈夫曼树和哈夫曼编码可能涉及以下步骤:1、定义哈夫曼树的节点结构。
每个节点可能包括字符,权重(或频率),以及左孩子和右孩子的指针。
ctypedef struct huffman_node {char character;unsigned int frequency;struct huffman_node *left, *right;} huffman_node;2、创建哈夫曼树。
首先,你需要计算每个字符的频率,然后根据这些频率创建一个哈夫曼树。
这个过程可能涉及使用优先队列(最小堆)来找出频率最小的两个节点,然后将它们合并为一个新的节点,新节点的频率是这两个节点的频率之和。
然后,将新节点放回队列中,重复这个过程直到队列中只剩下一个节点,这个节点就是你的哈夫曼树的根节点。
3、使用哈夫曼树生成哈夫曼编码。
从根节点开始,对于每个字符,左子树代表0,右子树代表1。
你可以遍历哈夫曼树,为每个字符生成其对应的哈夫曼编码。
4、实现解码。
给定一个哈夫曼编码,你可以通过遍历哈夫曼树来解码它。
对于每个位,如果是0,你跟随左子树,如果是1,你跟随右子树。
当你到达一个叶节点时,你就找到了对应的字符。
以上只是一个大致的步骤,具体的实现可能会根据你的需求和具体情况有所不同。
c语言哈夫曼树的构造及编码
c语言哈夫曼树的构造及编码一、哈夫曼树概述哈夫曼树是一种特殊的二叉树,它的构建基于贪心算法。
它的主要应用是在数据压缩和编码中,可以将频率高的字符用较短的编码表示,从而减小数据存储和传输时所需的空间和时间。
二、哈夫曼树的构造1. 哈夫曼树的定义哈夫曼树是一棵带权路径长度最短的二叉树。
带权路径长度是指所有叶子节点到根节点之间路径长度与其权值乘积之和。
2. 构造步骤(1) 将待编码字符按照出现频率从小到大排序。
(2) 取出两个权值最小的节点作为左右子节点,构建一棵新的二叉树。
(3) 将新构建的二叉树加入到原来排序后队列中。
(4) 重复上述步骤,直到队列只剩下一个节点,该节点即为哈夫曼树的根节点。
3. C语言代码实现以下代码实现了一个简单版哈夫曼树构造函数:```ctypedef struct TreeNode {int weight; // 权重值struct TreeNode *leftChild; // 左子节点指针struct TreeNode *rightChild; // 右子节点指针} TreeNode;// 构造哈夫曼树函数TreeNode* createHuffmanTree(int* weights, int n) {// 根据权值数组构建节点队列,每个节点都是一棵单独的二叉树TreeNode** nodes = (TreeNode**)malloc(sizeof(TreeNode*) * n);for (int i = 0; i < n; i++) {nodes[i] = (TreeNode*)malloc(sizeof(TreeNode));nodes[i]->weight = weights[i];nodes[i]->leftChild = NULL;nodes[i]->rightChild = NULL;}// 构建哈夫曼树while (n > 1) {int minIndex1 = -1, minIndex2 = -1;for (int i = 0; i < n; i++) {if (nodes[i] != NULL) {if (minIndex1 == -1 || nodes[i]->weight < nodes[minIndex1]->weight) {minIndex2 = minIndex1;minIndex1 = i;} else if (minIndex2 == -1 || nodes[i]->weight < nodes[minIndex2]->weight) {minIndex2 = i;}}}TreeNode* newNode =(TreeNode*)malloc(sizeof(TreeNode));newNode->weight = nodes[minIndex1]->weight + nodes[minIndex2]->weight;newNode->leftChild = nodes[minIndex1];newNode->rightChild = nodes[minIndex2];// 将新构建的二叉树加入到原来排序后队列中nodes[minIndex1] = newNode;nodes[minIndex2] = NULL;n--;}return nodes[minIndex1];}```三、哈夫曼编码1. 哈夫曼编码的定义哈夫曼编码是一种前缀编码方式,它将每个字符的编码表示为二进制串。
c语言构建哈夫曼树(附运行结果图)
#include<string.h>#include<stdlib.h>#include<stdio.h>int m,s1,s2;typedef struct {unsigned int weight;unsigned int parent,lchild,rchild;}HTNode,*HuffmanTree; //动态分配数组存储哈夫曼树typedef char *HuffmanCode; //动态分配数组存储哈夫曼编码表void Select(HuffmanTree HT,int n) {int i,j;for(i = 1;i <= n;i++)if(!HT[i].parent){s1 = i;break;}for(j = i+1;j <= n;j++)if(!HT[j].parent){s2 = j;break;}for(i = 1;i <= n;i++)if((HT[s1].weight>HT[i].weight)&&(!HT[i].parent)&&(s2!=i))s1=i;for(j = 1;j <= n;j++)if((HT[s2].weight>HT[j].weight)&&(!HT[j].parent)&&(s1!=j))s2=j;}void HuffmanCoding(HuffmanTree &HT, HuffmanCode HC[], int *w, int n) { // 算法6.13// w存放n个字符的权值(均>0),构造哈夫曼树HT,// 并求出n个字符的哈夫曼编码HCint i, j;char *cd;int p;int cdlen;if (n<=1) return;m = 2 * n - 1;HT = (HuffmanTree)malloc((m+1) * sizeof(HTNode)); // 0号单元未用for (i=1; i<=n; i++) { //初始化HT[i].weight=w[i-1];HT[i].parent=0;HT[i].lchild=0;HT[i].rchild=0;}for (i=n+1; i<=m; i++) { //初始化HT[i].weight=0;HT[i].parent=0;HT[i].lchild=0;HT[i].rchild=0;}puts("\n哈夫曼树的构造过程如下所示:");printf("HT初态:\n 结点weight parent lchild rchild");for (i=1; i<=m; i++)printf("\n%4d%8d%8d%8d%8d",i,HT[i].weight,HT[i].parent,HT[i].lchild, HT[i].rchild);for (i=n+1; i<=m; i++) { // 建哈夫曼树// 在HT[1..i-1]中选择parent为0且weight最小的两个结点,// 其序号分别为s1和s2。
哈夫曼树及哈夫曼编码的算法实现c语言
哈夫曼树及哈夫曼编码的算法实现c语言1.引言1.1 概述哈夫曼树及哈夫曼编码是数据压缩和编码中常用的重要算法。
哈夫曼树由大卫·哈夫曼于1952年提出,用于根据字符出现的频率构建一种最优的前缀编码方式。
而哈夫曼编码则是根据哈夫曼树构建的编码表将字符进行编码的过程。
在现代通信和计算机领域,数据传输和存储中往往需要大量的空间。
为了有效利用有限的资源,减少数据的存储和传输成本,数据压缩成为一个重要的技术。
而哈夫曼树及哈夫曼编码正是数据压缩中常用的技术之一。
哈夫曼树的概念及原理是基于字符的频率和概率进行构建的。
在哈夫曼树中,字符出现频率越高的节点越接近根节点,出现频率越低的节点离根节点越远。
这种构建方式保证了哈夫曼树的最优性,即最小化编码的总长度。
哈夫曼编码的算法实现是根据哈夫曼树构建的编码表进行的。
编码表中,每个字符都与一段二进制编码相对应。
在进行数据压缩和解压缩时,通过查表的方式将字符转化为相应的二进制编码,或将二进制编码解析为原始字符。
本文旨在介绍哈夫曼树及哈夫曼编码的概念和原理,并通过C语言实现算法。
通过深入理解哈夫曼树及哈夫曼编码的实现过程,可以更好地理解数据压缩和编码的原理,为后续的研究和应用提供基础。
接下来,我们将首先介绍哈夫曼树的概念和原理,然后详细讲解哈夫曼编码的算法实现。
最后,我们将总结哈夫曼树及哈夫曼编码的重要性,并提出对哈夫曼树和哈夫曼编码进一步研究的方向。
让我们一起深入探索哈夫曼树及哈夫曼编码的奥秘吧!1.2 文章结构文章结构部分的内容可以包括以下内容:文章结构部分主要介绍了本文的组织结构和各个章节的内容概述,以帮助读者更好地理解全文的逻辑结构和内容安排。
首先,本文包括引言、正文和结论三个部分。
引言部分主要对哈夫曼树及哈夫曼编码的算法实现进行了概述,包括相关的概念、原理和目的。
正文部分则深入介绍了哈夫曼树的概念和原理,以及哈夫曼编码的算法实现。
最后,结论部分对本文的主要内容进行了总结,并提出了对哈夫曼树和哈夫曼编码的进一步研究方向。
哈夫曼树的构造c语言代码
哈夫曼树的构造c语言代码哈夫曼树是一种特殊的二叉树,常被用于数据压缩中。
它的构造过程非常重要,接下来我将用c语言展示如何构造哈夫曼树。
首先,我们需要定义一个结构体作为节点:```struct Node{int weight;//权重int parent;//父节点在数组中的下标int lchild;//左子节点在数组中的下标int rchild;//右子节点在数组中的下标};```然后,我们需要读入数据,计算每个数据的权重,随后用一个数组存储节点信息:```int n;//数据个数int W[maxn];//存储每个数据的权重Node tree[maxn*2-1];//哈夫曼树```接下来,我们需要编写一个函数用来选择权值最小的两个节点,然后将它们合并成一个节点。
```int select_min(Node*tree,int n){int res=-1;int min=INT_MAX;for(int i=0;i<n;i++){if(tree[i].parent!=-1)continue;//跳过已经合并的节点if(tree[i].weight<min){min=tree[i].weight;res=i;}}return res;}void merge_node(Node*tree,int a,int b,int i){tree[a].parent=i;tree[b].parent=i;tree[i].weight=tree[a].weight+tree[b].weight;tree[i].lchild=a;tree[i].rchild=b;}```接下来,我们就可以开始构造哈夫曼树了。
我们先初始化每个节点,将它们都看成一个独立的树,然后选择最小的两个节点进行合并,直到最后只剩下一个树为止。
```void build_tree(Node*tree,int n,int*W){for(int i=0;i<n;i++){tree[i].weight=W[i];tree[i].parent=-1;tree[i].lchild=-1;tree[i].rchild=-1;}for(int i=n;i<(n<<1)-1;i++) {int a=select_min(tree,i);int b=select_min(tree,i);merge_node(tree,a,b,i);}}```最后,我们可以调用build_tree函数来构造哈夫曼树。
数据结构c+python代码6:哈夫曼树构造及编码
数据结构c+python代码6:哈夫曼树构造及编码⾸先介绍⼀下什么是哈夫曼树?给定N个权值作为N个叶⼦结点,构造⼀棵⼆叉树,若该树的带权路径长度达到最⼩,称这样的⼆叉树为最优⼆叉树,也称为哈夫曼树(Huffman Tree)。
哈夫曼树是带权路径长度最短的树,权值较⼤的结点离根较近。
哈夫曼树⼜称为最优树.1、路径和路径长度在⼀棵树中,从⼀个结点往下可以达到的孩⼦或孙⼦结点之间的通路,称为路径。
通路中分⽀的数⽬称为路径长度。
若规定根结点的层数为1,则从根结点到第L层结点的路径长度为L-1。
2、结点的权及带权路径长度哈夫曼树哈夫曼树(3张)若将树中结点赋给⼀个有着某种含义的数值,则这个数值称为该结点的权。
结点的带权路径长度为:从根结点到该结点之间的路径长度与该结点的权的乘积。
3、树的带权路径长度树的带权路径长度规定为所有叶⼦结点的带权路径长度之和,记为WPL。
哈夫曼树的构造假设有n个权值,则构造出的哈夫曼树有n个叶⼦结点。
n个权值分别设为 w1、w2、…、wn,则哈夫曼树的构造规则为:(1) 将w1、w2、…,wn看成是有n 棵树的森林(每棵树仅有⼀个结点);(2) 在森林中选出两个根结点的权值最⼩的树合并,作为⼀棵新树的左、右⼦树,且新树的根结点权值为其左、右⼦树根结点权值之和;(3)从森林中删除选取的两棵树,并将新树加⼊森林;(4)重复(2)、(3)步,直到森林中只剩⼀棵树为⽌,该树即为所求得的哈夫曼树。
c代码过程分析构造哈夫曼树算法的实现可以分成两⼤部分:1、初始化:⾸先动态申请2n个单元;然后循环2n-1次,从1号单元开始,依次将1⾄2n-1所有单元中的双亲、左孩⼦、右孩⼦的下标都初始化为0;最后再循环n次,输⼊前n个单元中叶⼦节点的权值。
2、创建树:循环n-1次,通过n-1次的选择、删除与合并来创建哈夫曼树。
选择是从当前森林中选择双亲为0且权值最⼩的两个树跟节点是s1和s2;删除是指将节点s1和s2的双亲改为⾮0;合并就是将s1和s2的权值和作为⼀个新节点的权值依次存⼊到数组的第n+1之后的单元中,同时记录这个新节点左孩⼦的下标为s1,右孩⼦的下标为s2。
用c语言实现哈夫曼编码
用c语言实现哈夫曼编码哈夫曼编码是一种用于无损数据压缩的熵编码算法。
以下是一个简单的使用C语言实现哈夫曼编码的例子。
这个例子只实现了编码过程,没有实现解码过程。
c复制代码#include<stdio.h>#include<stdlib.h>#include<string.h>// 节点结构体typedef struct Node {char data;int freq;struct Node *left, *right;} Node;// 创建新节点Node* newNode(char data, int freq) {Node* node = (Node*) malloc(sizeof(Node));node->data = data;node->freq = freq;node->left = node->right = NULL;return node;}// 计算前缀和int getSum(Node* root) {if (!root) return0;return root->freq + getSum(root->left) + getSum(root->right);}// 创建哈夫曼树Node* createHuffmanTree(char data[], int freq[], int size) { if (size == 0) return NULL;Node *left = newNode(data[size-1], freq[size-1]);Node *right = createHuffmanTree(data, freq, size-1);Node *top = newNode(0, getSum(right));top->left = left;top->right = right;return top;}// 打印哈夫曼编码void printHuffmanCode(Node* root, int n, char code[]) {if (!root) return;if (root->data != 0) printf("%c: ", root->data);code[n] = root->data;printHuffmanCode(root->left, n+1, code);printHuffmanCode(root->right, n+1, code);}int main() {char data[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g'};int freq[] = {5, 9, 12, 13, 16, 45};int size = sizeof(data)/sizeof(data[0]);Node* root = createHuffmanTree(data, freq, size);char code[256] = {0}; // 存放哈夫曼编码,初始为空字符串,表示没有编码,对应字符的编码为空字符串。
哈夫曼树编码c语言
以下是C语言实现哈夫曼树编码的示例代码:```c#include <stdio.h>#include <stdlib.h>// 定义结构体表示节点struct TreeNode {int val;struct TreeNode *left;struct TreeNode *right;};// 创建新节点struct TreeNode* newNode(int val) {struct TreeNode* node = (struct TreeNode*)malloc(sizeof(struct TreeNode));node->val = val;node->left = NULL;node->right = NULL;return node;}// 计算权值和int calculateWeightSum(struct TreeNode* root) {if (root == NULL) {return 0;}return root->val + calculateWeightSum(root->left) + calculateWeightSum(root->right);}// 构建哈夫曼树struct TreeNode* buildHuffmanTree(int** freq, int size) {// 创建频率数组int arr[size];for (int i = 0; i < size; i++) {arr[i] = freq[i][0];}// 构建哈夫曼树struct TreeNode* root = NULL;int index = 0;while (index < size) {int min1 = INT_MAX, min2 = INT_MAX;int min1Index = -1, min2Index = -1;for (int i = 0; i < size; i++) {if (arr[i] < min1 && arr[i] != 0) {min1 = arr[i];min1Index = i;}if (arr[i] < min2 && arr[i] != 0) {min2 = arr[i];min2Index = i;}}// 创建新节点作为左右子树,并加入频率数组中arr[min1Index] = 0;arr[min2Index] = 0;struct TreeNode* left = newNode(min1);struct TreeNode* right = newNode(min2);left->left = right;right->right = left;// 将左右子树作为新的根节点,并更新频率数组和根节点指针if (root == NULL) {root = left;} else {struct TreeNode* parent = root;while (parent->left != NULL) {parent = parent->left;}parent->left = left;left->parent = parent;while (parent->right != NULL) {parent = parent->right;}parent->right = right;right->parent = parent;}index += 2; // 跳过左右子树,继续寻找下一对最小的节点构建子树,直到遍历完所有节点为止。
哈夫曼树的构造代码
哈夫曼树的构造代码x#include<stdio.h>#include<malloc.h>//定义哈夫曼树节点typedef struct{tint weight;//权值tint lchild,rchild,parent;//子节点和双亲节点序号}HTNode;//定义哈夫曼树typedef struct{tHTNode *nodes;//节点数组tint length;//树的节点数}HuffmanTree;//创建哈夫曼树HuffmanTree *createHuffmanTree(int *set,int length){tint m,i,j,x1,x2;//m表示总节点数,x1和x2记录权值最小的两个节点tHuffmanTree *tree;tHTNode *node;tm=2*length-1;t//申请树的节点数组ttree=(HuffmanTree*)malloc(sizeof(HuffmanTree));tnode=(HTNode*)malloc(m*sizeof(HTNode));t//初始化tfor(i=0;i<m;i++)t{ttnode[i].parent=-1;ttnode[i].lchild=-1;ttnode[i].rchild=-1;ttif(i<length)tt{tttnode[i].weight=set[i];tt}ttelsetttnode[i].weight=0;t}t//建立哈夫曼树tfor(i=length;i<m;i++)t{tt//x1表示权值最小的节点序号,x2表示次最小节点的序号ttx1=0;ttx2=0;tt//找出权值最小的节点ttfor(j=0;j<i;j++)tt{tttif(node[j].parent==-1)ttt{ttttif((x1==0)||node[j].weight<node[x1].weight)tttt{tttttx1=j;tttt}ttt}tt}tt//找出权值次最小的节点ttfor(j=0;j<i;j++)tt{tttif(node[j].parent==-1)ttt{ttttif((x2==0)||node[j].weight<node[x2].weight&&x1!=j) tttt{tttttx2=j;tttt}ttt}tt}tt//建立一个新的节点ttnode[i].weight=node[x1].weight+node[x2].weight; ttnode[i].lchild=x1;ttnode[i].rchild=x2;ttnode[x1].parent=i;ttnode[x2].parent=i;t}ttree->nodes=node;ttree->length=m;treturn tree;}//打印哈夫曼树void printHuffmanTree(HuffmanTree *tree){tint i;tprintf('序号t权值t双亲t左孩子t右孩子');tfor(i=0;i<tree->length;i++)t{ttprintf('%dt%dt%dt%dt%d',i,tree->nodes[i].weight,tree->nodes[i].parent, ttttree->nodes[i].lchild,tree->nodes[i].rchild); t}}//释放哈夫曼树void clearHuffmanTree(HuffmanTree *tree){tif(tree==NULL)ttreturn;tfree(tree->nodes);tfree(tree);}int main(){tHuffmanTree *tree;tint set[7]={5,29,7,8,14,23,3};t//创建哈夫曼树ttree=createHuffmanTree(set,7);t//打印哈夫曼树tprintHuffmanTree(tree);t//释放哈夫曼树tclearHuffmanTree(tree);treturn 0; }。
哈夫曼编码详解(C语言实现)
哈夫曼编码详解(C语言实现)哈夫曼编码是一种常见的前缀编码方式,被广泛应用于数据压缩和传输中。
它是由大卫·哈夫曼(David A. Huffman)于1952年提出的,用于通过将不同的字符映射到不同长度的二进制码来实现数据的高效编码和解码。
1.统计字符频率:遍历待编码的文本,记录每个字符出现的频率。
2.构建哈夫曼树:根据字符频率构建哈夫曼树,其中出现频率越高的字符位于树的较低层,频率越低的字符位于树的较高层。
3.生成编码表:从哈夫曼树的根节点开始,遍历哈夫曼树的每个节点,为每个字符生成对应的编码。
在遍历过程中,从根节点到叶子节点的路径上的“0”表示向左,路径上的“1”表示向右。
4.进行编码:根据生成的编码表,将待编码的文本中的每个字符替换为对应的编码。
5.进行解码:根据生成的编码表和编码结果,将编码替换为原始字符。
下面是一个用C语言实现的简单哈夫曼编码示例:```c#include <stdio.h>#include <stdlib.h>#include <string.h>//定义哈夫曼树的节点结构体typedef struct HuffmanNodechar data; // 字符数据int freq; // 字符出现的频率struct HuffmanNode *left; // 左子节点struct HuffmanNode *right; // 右子节点} HuffmanNode;//定义编码表typedef structchar data; // 字符数据char *code; // 字符对应的编码} HuffmanCode;//统计字符频率int *countFrequency(char *text)int *frequency = (int *)calloc(256, sizeof(int)); int len = strlen(text);for (int i = 0; i < len; i++)frequency[(int)text[i]]++;}return frequency;//创建哈夫曼树HuffmanNode *createHuffmanTree(int *frequency)//初始化叶子节点HuffmanNode **leaves = (HuffmanNode **)malloc(256 * sizeof(HuffmanNode *));for (int i = 0; i < 256; i++)if (frequency[i] > 0)HuffmanNode *leaf = (HuffmanNode*)malloc(sizeof(HuffmanNode));leaf->data = (char)i;leaf->freq = frequency[i];leaf->left = NULL;leaf->right = NULL;leaves[i] = leaf;} elseleaves[i] = NULL;}}//构建哈夫曼树while (1)int min1 = -1, min2 = -1;for (int i = 0; i < 256; i++)if (leaves[i] != NULL)if (min1 == -1 , leaves[i]->freq < leaves[min1]->freq) min2 = min1;min1 = i;} else if (min2 == -1 , leaves[i]->freq < leaves[min2]->freq)min2 = i;}}}if (min2 == -1)break;}HuffmanNode *parent = (HuffmanNode*)malloc(sizeof(HuffmanNode));parent->data = 0;parent->freq = leaves[min1]->freq + leaves[min2]->freq;parent->left = leaves[min1];parent->right = leaves[min2];leaves[min1] = parent;leaves[min2] = NULL;}HuffmanNode *root = leaves[min1];free(leaves);return root;//生成编码表void generateHuffmanCode(HuffmanNode *root, HuffmanCode *huffmanCode, char *code, int depth)if (root->left == NULL && root->right == NULL)code[depth] = '\0';huffmanCode[root->data].data = root->data;huffmanCode[root->data].code = strdup(code);return;}if (root->left != NULL)code[depth] = '0';generateHuffmanCode(root->left, huffmanCode, code, depth + 1);}if (root->right != NULL)code[depth] = '1';generateHuffmanCode(root->right, huffmanCode, code, depth + 1);}//进行编码char *encodeText(char *text, HuffmanCode *huffmanCode)int len = strlen(text);int codeLen = 0;char *code = (char *)malloc(len * 8 * sizeof(char));for (int i = 0; i < len; i++)strcat(code + codeLen, huffmanCode[(int)text[i]].code);codeLen += strlen(huffmanCode[(int)text[i]].code);}return code;//进行解码char* decodeText(char* code, HuffmanNode* root) int len = strlen(code);char* text = (char*)malloc(len * sizeof(char)); int textLen = 0;HuffmanNode* node = root;for (int i = 0; i < len; i++)if (code[i] == '0')node = node->left;} elsenode = node->right;}if (node->left == NULL && node->right == NULL) text[textLen] = node->data;textLen++;node = root;}}text[textLen] = '\0';return text;int maichar *text = "Hello, World!";int *frequency = countFrequency(text);HuffmanNode *root = createHuffmanTree(frequency);HuffmanCode *huffmanCode = (HuffmanCode *)malloc(256 * sizeof(HuffmanCode));char code[256];generateHuffmanCode(root, huffmanCode, code, 0);char *encodedText = encodeText(text, huffmanCode);char *decodedText = decodeText(encodedText, root);printf("Original Text: %s\n", text);printf("Encoded Text: %s\n", encodedText);printf("Decoded Text: %s\n", decodedText);//释放内存free(frequency);free(root);for (int i = 0; i < 256; i++)if (huffmanCode[i].code != NULL)free(huffmanCode[i].code);}}free(huffmanCode);free(encodedText);free(decodedText);return 0;```上述的示例代码实现了一个简单的哈夫曼编码和解码过程。
c语言静态三叉链表构造一棵Huffman树并求其编码
课程设计题目:采用静态三叉链表构造一棵Huffman树并求其编码一课程设计应达到的目的:数据结构课程设计的目的是,为了让学生在学习《数据结构》课程的基础上深入理解数据结构的基本理论,掌握对数据结构的各种操作的算法设计方法,增强对基础知识和基本方法的综合运用能力,增强对算法的理解能力,提高软件设计能力,在实践中培养独立分析问题和解决问题的作风和能力,进一步深入巩固所学理论知识、使理论与实际相结合的重要实践环节。
本课程设计通过完成一些具有一定难度的程序的编写、调试、运行工作,掌握面向过程程序设计的基本方法,从而提高学生分析问题解决问题的能力。
课程设计是教学中很重要的一项实践环节,它可以帮助学生充分理解课堂教学中的内容,对提高学生的实践认识和实际动手能力都有很重要的实际意义。
学生应在规定的时间内,按照课程设计的要求,结合所学的理论知识,查找相关资料,完成好本次课程设计,提高程序编写的能力,为将来的实际工作取得一定的经验。
二课程设计题目及要求采用静态三叉链表构造一棵Huffman树并求其编码增加了权值的计算和Huffman树的输出并写入code文件三主函数及分析it学习网收集主程序代码Main.cpp#include<iostream.h>#include<string.h>#include"readFile.h"#include"HuffmanTree.h"int main(){char str[1000];cin>>str;HuffmanTree htree(str);htree.print();htree.writetoFile();readFile(htree.getstr1(),htree.gethufcodes(),htree.getleafNum());return 0;}HuffmanTree.h#include<iostream.h>#include<stdio.h>#include<string.h>template<class T>struct TriNode{T data;int parent,left,right;};class HuffmanTree{private:char str[1000]; //输入的字符串char str1[1000]; //哈弗曼叶子值int leafNum; //子叶结点个数TriNode<int> *huftree; // 哈弗曼的结点数组char **hufcodes; //哈弗曼编码数组void createHuffmanTree(int weight[],int n); //创建指定权值集合的哈弗曼树void getHuffmanCode(); //获得哈弗曼编码public:HuffmanTree(char str5[]);~HuffmanTree();void writetoFile(); //写入文件char** gethufcodes();char* getstr1();int getleafNum();void print();void print(int u);int getheight(int r);//得出r节点的深度};const Max_Weight=9999; // 默认最大权值/*******************************************************************/ HuffmanTree::HuffmanTree(char str5[]){strcpy(str,str5);int count=0,i,j,k=0;for(i=0;i<strlen(str);i++)//循环做出str1,将每个str里面的字符在str1里面扫描一遍,str中在str1没出现的字符放到str1中{for(j=0;j<count+1;j++)if(str[i]!=str1[j]) k++;//如果str中的字符在str1中扫描不等k++,k初值为0if(k==count+1)//如果k等于字符串str1的长度的话说明str[i]在str1中没出现,加到str1中str1[count++]=str[i];k=0;}str1[count]='\0';//将哈弗曼叶子字符数组最后一位置字符串结束符/********************************************************************/ int weight[100];for(i=0;i<count;i++)//初始化权值为0weight[i]=0;for(i=0;i<strlen(str);i++)//从第一个开始扫描str 让str的每一个字符和str1比较在str1中相等的地方让weight的值++for(j=0;j<count;j++){if(str[i]==str1[j]){weight[j]++;//weight中的每一位对应着str1中的每一位break;}}for(i=0;i<count;i++){cout<<str1[i]<<" ";}cout<<endl;for(i=0;i<count;i++){cout<<weight[i]<<" ";}cout<<endl;/********************************************************************/ createHuffmanTree(weight,count);getHuffmanCode();}/********************************************************************/void HuffmanTree::createHuffmanTree(int weight[],int n) //创建指定权值集合的哈弗曼树{leafNum=n;huftree=new TriNode<int>[2*n-1];int i;for(i=0;i<n;i++){huftree[i].data=weight[i];huftree[i].parent=huftree[i].left=huftree[i].right=-1;}for(i=0;i<n-1;i++){int min1,min2,x1,x2;min1=min2=Max_Weight;x1=x2=-1;for(int j=0;j<n+i;j++){if(huftree[j].data<min1&&huftree[j].parent==-1){min2=min1;x2=x1;min1=huftree[j].data;x1=j;}else if(huftree[j].data<min2&&huftree[j].parent==-1){min2=huftree[j].data;x2=j;}}huftree[x1].parent=n+i;huftree[x2].parent=n+i;huftree[n+i].data=huftree[x1].data+huftree[x2].data;huftree[n+i].parent=-1;huftree[n+i].left=x1;huftree[n+i].right=x2;}}void HuffmanTree::getHuffmanCode(){int n=leafNum;hufcodes=new char*[n];for(int i=0;i<n;i++){char *code=new char[n];code[n-1]='\0';int start=n-1;int child=i;int parent=huftree[child].parent;while(parent!=-1){start--;if(huftree[parent].left==child)code[start]='0';elsecode[start]='1';child=parent;parent=huftree[child].parent;}hufcodes[i]=code+start;}}/********************************************************************/int HuffmanTree::getheight(int r){int t=0;while(r!=-1){r=huftree[r].parent;t++;}return t;}/********************************************************************/void HuffmanTree::print(){cout<<"哈夫曼树节点数组: \n";print(2*leafNum-2);}/*******HuffmanTree************************************************************ */void HuffmanTree::print(int u)//递归打印哈弗曼tree,采用先序遍历{if(u!=-1)//判断是否有孩子{for(int e=1;e<getheight(u);e++)//循环小于高度,目的是为了确定该节点前有多少个空格{if(e==getheight(u)-1)//在循环的最后一位输出下面字符cout<<"|_____";else cout<<" ";//循环输出空格}cout<<huftree[u].data;//输出节点权值cout<<endl;print(huftree[u].left);//找它左子print(huftree[u].right);//找他右孩子}}/********************************************************************/ HuffmanTree::~HuffmanTree(){delete[] huftree;delete[] hufcodes;}/********************************************************************/void HuffmanTree::writetoFile(){FILE *fp;int i,j;fp=fopen("code.txt","w");//以读的方式创建文件for(i=0;i<strlen(str);i++)//扫描字符串str每一位与str1中的每一为比较若相等写入该位置的哈弗曼的编码for(j=0;j<leafNum;j++){if(str[i]==str1[j]) //主要目的是得出j值str1和weight和hafcodes的每一位都一一对应{fputs(hufcodes[j],fp);//写入文件cout<<hufcodes[j];//输出到屏幕}}cout<<endl;fclose(fp);cout<<"写入成功"<<endl;}/********************************************************************/char* HuffmanTree::getstr1()//str1访问器{return str1;}char** HuffmanTree::gethufcodes()//hufcodes访问器{return hufcodes;}int HuffmanTree::getleafNum()//leafNum访问器{return leafNum;}ReadFile.h#include<iostream.h>#include<stdio.h>#include<string.h>void readFile(char *str1,char **hufcodes,int leafNum)//带入参数哈弗曼节点字符串哈弗曼编码字符串数组,哈弗曼节点数{char str2[1000],str3[100];//这个方法的思想是,从文件读入哈弗曼编码过的文档读入到str2中int k=0,i=0,j,l,o=0,p=0;//然后从第一个字符开始取字符str2中的hufcodes[i]的长度和hufcodes[i]比较是否相等FILE *fp;// 若相等i=i+hufcodes[i]的长度继续读下面的知道str2读完fp=fopen("code.txt","r");while(!feof(fp))str2[k++]=fgetc(fp);fclose(fp);while(i<k-1){for(j=0;j<leafNum;j++){o=0;p=0;for(l=i;l<i+strlen(hufcodes[j]);l++)//复制str2中哈弗曼编码str3[p++]=str2[l];for(l=0;l<strlen(hufcodes[j]);l++)if(str3[l]!=hufcodes[j][l]) o++;if(o==0){cout<<str1[j];i=i+strlen(hufcodes[j]);break;}}}cout<<endl;}程序执行结果:14561四 主要参考文献写入到文件里的huffman 编码Huffman 树《数据结构(C++版)》叶核亚编著电子工业出版社五程序中出现的问题及解决方案程序原本采用三叉链表储存结构,但是由于实现方面有问题,所以现在采用静态三叉链表,静态三叉链表采用一个结构数组存储二叉树的所有结点,一个数组元素储存一个结点,每个结点存储其父母,孩子结点的下标,通过下标表示结点间的关系。
c语言实现哈夫曼编码
c语言实现哈夫曼编码一、概述哈夫曼编码是一种常用的无损数据压缩算法,其原理是基于字符的出现概率来构建编码表,从而实现数据的压缩。
本教程将介绍如何使用C语言实现哈夫曼编码算法。
二、算法原理哈夫曼编码算法的基本思想是:将字符按照出现概率的大小进行排序,然后构建一个树状结构,每个节点代表一个字符,节点的左子节点和右子节点分别代表字符的频率较小和较大的分支。
最终,通过路径进行解码即可还原出原始数据。
三、实现步骤1.统计字符频率,构建字符频率表;2.按照频率从小到大排序,构建哈夫曼树;3.根据哈夫曼树构建编码表,将字符映射为编码;4.实现解码过程,还原出原始数据。
四、代码实现下面是一个简单的C语言实现哈夫曼编码的示例代码:```c#include<stdio.h>#include<stdlib.h>#include<ctype.h>#defineMAX_CHARS1000//最大字符数#defineMAX_FREQ100//最大频率值//字符频率表intfreq[MAX_CHARS+1];//构建哈夫曼树函数structnode{charch;intfreq;structnode*left,*right;};structnode*build_huffman_tree(intfreq[],intn){structnode*root=(structnode*)malloc(sizeof(structnode));root->freq=freq[0];//根节点的频率为最小的频率值root->left=root->right=NULL;for(inti=1;i<=n;i++){if(freq[i]==root->freq){//如果当前字符的频率与根节点的频率相同,则添加到左子树或右子树中if(i<n&&freq[i]==freq[i+1]){//如果当前字符的频率与下一个字符的频率相同,则添加到左子树中root->left=(structnode*)malloc(sizeof(structnode));root->left->ch=i+'a';//左子节点的字符为当前字符的下一个字符(假设所有字符都是小写字母)root->left->left=root->left->right=NULL;//左子树为空树i++;//跳过下一个字符,继续寻找下一个不同的频率值}else{//如果当前字符的频率与下一个字符的频率不相同,则添加到右子树中root->right=(structnode*)malloc(sizeof(structnode));root->right->ch=i+'a';//右子节点的字符为当前字符root->right->left=root->right->right=NULL;//右子树为空树}}elseif(freq[i]<root->freq){//如果当前字符的频率小于根节点的频率,则添加到左子树中root->left=(structnode*)malloc(sizeof(structnode));root->left->ch=i+'a';//左子节点的字符为当前字符的下一个字符(假设所有字符都是小写字母)root->left->left=build_huffman_tree(freq,i);//子树的左孩子为当前字符构成的右子树节点和子哈夫曼树的左孩子合并得到的左孩子节点,这个步骤继续调用本函数,从而继续构建右子树的下一级和再下一级,最终实现三级左右子的嵌套式结构树型哈夫曼编码)注:这种思想并非标准的哈夫曼编码)//子树的右孩子为当前节点(即当前字符)构成的右子树节点和子哈夫曼树的右孩子节点合并得到的右孩子节点)注:这种思想并非标准的哈夫曼编码)//子树的左孩子为空树)注:这种思想并非标准的哈夫曼编码)根节点的频率是根节点的最小频率值(因为构建哈夫曼树的过程中总是从最小的频率值开始)根节点的左子树是构建出的三级左右子的嵌套式结构树型哈夫曼编码根节点的右子树为空树(假设所有字符都是小写字母)在添加左子节点后需要调用本函数构建右子树的下一级和再下一级来得到三级左右子的嵌套式结构。
huffman树及huffman编码的算法实现
huffman树及huffman编码的算法实现Huffman树是一种用于数据压缩的算法,它通过统计字符出现的频率来构建一个树形结构,从而实现对数据的编码和解码。
具体来说,Huffman编码是一种变长编码方式,将出现频率较高的字符用较短的编码表示,而出现频率较低的字符用较长的编码表示。
下面将介绍Huffman树的构建和编码算法的实现。
首先,我们需要统计字符串中每个字符出现的频率,并按照频率降序排列。
这可以通过读取字符串中的每个字符,利用一个哈希表来记录其出现的次数实现。
然后,我们将这些字符及其频率构建成一棵频率树,树的每个叶子节点代表一个字符,并带有相应的频率值。
接着,我们将这棵频率树转化为一棵Huffman树。
具体操作如下:1. 创建一个优先队列,并将频率树中的所有节点按照它们的频率值插入队列中。
2. 从优先队列中取出频率最低的两个节点,将它们合并成一个新的节点,并将新的节点插入到优先队列中。
3. 重复上述步骤,直到队列中只剩下一个节点,即根节点为止。
完成Huffman树的构建后,我们可以开始进行编码操作。
编码实际上是根据Huffman树的结构给每个字符分配一个唯一的二进制编码。
具体步骤如下:1. 从Huffman树的根节点出发,遍历整棵树,记录每个字符与根节点的路径。
路径的左分支表示编码为0,右分支表示编码为1。
2. 将每个字符及其相应的编码存储在一个哈希表中。
最后,我们可以根据Huffman编码对字符串进行压缩。
将字符串中的每个字符用相应的Huffman编码替换,将所有编码连在一起,即可得到压缩后的字符串。
反之,如果给出一个编码后的二进制字符串,我们可以通过解码树来还原原始的字符串。
以上是Huffman树及Huffman编码的算法实现的介绍。
通过构建Huffman树和根据编码表进行编码和解码,我们可以有效地压缩和解压数据,实现了数据的高效传输和存储。
c语言实现构造哈夫曼树代码
c语言实现构造哈夫曼树代码一、哈夫曼树简介哈夫曼树是一种特殊的二叉树,其每个叶子节点都对应一个权值,而非叶子节点则没有权值。
哈夫曼树的构造过程中,将权值较小的节点放在左子树,权值较大的节点放在右子树,这使得哈夫曼树的带权路径最短。
哈夫曼编码就是利用这种特性实现对数据进行压缩。
二、C语言实现构造哈夫曼树1. 定义结构体首先需要定义一个结构体来表示哈夫曼树中的节点。
结构体中包含了该节点的权值以及指向左右子节点的指针。
```typedef struct TreeNode {int weight;struct TreeNode *left;struct TreeNode *right;} TreeNode;2. 构造哈夫曼树接下来需要实现构造哈夫曼树的函数。
该函数接收一个数组作为输入,数组中存储了每个叶子节点的权值。
首先需要将数组中所有元素转化为TreeNode类型,并将它们存储在一个链表中。
```TreeNode *createTreeNodes(int weights[], int size) {TreeNode *nodes[size];for (int i = 0; i < size; i++) {nodes[i] = (TreeNode *)malloc(sizeof(TreeNode));nodes[i]->weight = weights[i];nodes[i]->left = NULL;nodes[i]->right = NULL;}return nodes;}```接下来,需要实现一个函数来找到权值最小的两个节点。
该函数接收一个链表作为输入,并返回该链表中权值最小的两个节点。
```void findMinNodes(TreeNode **nodes, int size, TreeNode**minNode1, TreeNode **minNode2) {*minNode1 = *minNode2 = NULL;for (int i = 0; i < size; i++) {if (*minNode1 == NULL || (*nodes)[i].weight <(*minNode1)->weight) {*minNode2 = *minNode1;*minNode1 = &(*nodes)[i];} else if (*minNode2 == NULL || (*nodes)[i].weight < (*minNode2)->weight) {*minNode2 = &(*nodes)[i];}}}```接下来,需要实现一个函数来构造哈夫曼树。
C语言—哈夫曼树编码器和译码器
C语言—哈夫曼树编码器和译码器#include <stdio.h>#include "stdlib.h"#define MAXBIT 10#define MAXVALUE 10000#define MAXLEAF 100#define MAXNODE MAXLEAF*2-1//定义哈夫曼树编码类型typedef struct {char bit[MAXBIT]; //存放叶子结点字符编码过后的二进制编码int start; //存放叶子结点二进制编码在bit[]数组里的起始数组位置int length; //存放二进制编码的位数}HFMCode;//定义哈夫曼树结点类型typedef struct {char data; //编码字符int weight; //哈夫曼树结点的权值int parent; //哈夫曼树结点的父结点int lchild; //哈夫曼树结点的左孩子int rchild; //哈夫曼树结点的右孩子}HFMNode;//构造哈夫曼树void createHFMTree(HFMNode hfmnode[MAXNODE],int n){int i,j,m1,m2,x1,x2;for(i=0;i<2*n-1;i++){hfmnode[i].weight=0;hfmnode[i].parent=-1;hfmnode[i].lchild=-1;hfmnode[i].rchild=-1;}for(i=0;i<n;i++){getchar();printf("请输入第%d片叶子的字符:",i+1);scanf("%c",&hfmnode[i].data);printf("请输入第%d片叶子的权重:",i+1);scanf("%d",&hfmnode[i].weight);}for(i=0;i<n-1;i++){m1=m2=MAXVALUE; //m1和m2分别用来存储叶子结点权值的最小值和次小值x1=x2=0; //x1和x2分别用来存储m1和m2的位置for(j=0;j<n+i;j++){if(hfmnode[j].weight<m1&&hfmnode[j].parent==-1){m2=m1;x2=x1;m1=hfmnode[j].weight;x1=j;}else if(hfmnode[j].weight<m2&&hfmnode[j].parent==-1){m2=hfmnode[j].weight;x2=j;}}hfmnode[x1].parent=n+i;hfmnode[x2].parent=n+i;hfmnode[n+i].weight=hfmnode[x1].weight+hfmnode[x2].weight;//父结点的权重是左孩子和右孩子的权重之和hfmnode[n+i].lchild=x1;hfmnode[n+i].rchild=x2;}}//显示叶子的编码字符和编码字符对应的二进制编码void showCode(HFMCode hfmcode[MAXNODE],HFMNodehfmnode[MAXNODE],int n){int i,j,k,c,p;HFMCode cd;for(i=0;i<n;i++){hfmcode[i].length=0; hfmcode[i].start=0;k=hfmcode[i].start;cd.start=n-1;c=i;p=hfmnode[c].parent;while(p!=-1){if(hfmnode[p].lchild==c) {cd.bit[cd.start]=0;}else{cd.bit[cd.start]=1;}cd.start--;c=p;p=hfmnode[c].parent;}for(j=cd.start+1;j<n;j++) {hfmcode[i].bit[k]=cd.bit[j];k++;hfmcode[i].length++; //length计算存放的二进制编码的位数}}for(i=0;i<n;i++) //输出每个叶子节点的哈夫曼编码{printf("第%d片叶子的编码是:",i+1);printf("%c\t",hfmnode[i].data);for(j=hfmcode[i].start;j<hfmcode[i].length;j++){printf("%d",hfmcode[i].bit[j]);}printf("\n");}}//输入字符串,得到二进制编码void compileCode(char str[],int n,HFMCode hfmcode[MAXLEAF],HFMNode hfmnode[MAXNODE]){int i,j,k;for(i=0;str[i]!='\0';i++){for(j=0;j<n;j++){if(str[i]==hfmnode[j].data){for(k=hfmcode[j].start;k<hfmcode[j].length;k++){printf("%d",hfmcode[j].bit[k]);}}}}printf("\n\n");}//输入二进制编码得到字符串void decompileCode(char num[],int n,HFMCode hfmcode[MAXLEAF],HFMNode hfmnode[MAXNODE]){int i,j;j=2*n-2; //哈夫曼树根结点的位置for(i=0;num[i]!='\0';i++){if(num[i]=='0'){j=hfmnode[j].lchild;}else if(num[i]=='1'){j=hfmnode[j].rchild;}if(j<n) //j大于等于n表示的都是除叶子结点以外的哈夫曼树结点{printf("%c",hfmnode[j].data);j=2*n-2;}}printf("\n");}//主函数void main(){HFMNode hfmnode[MAXNODE];HFMCode hfmcode[MAXLEAF];char str[100]; //存放输入的需要编译的的字符串char num[100]; //存放输入的需要编译的二进制字符串int n; //输入的叶子结点数//哈夫曼编码器printf("-----------------哈弗曼编码器------------------\n"); printf("请输入叶子结点数:");scanf("%d",&n);createHFMTree(hfmnode,n);showCode(hfmcode,hfmnode,n);//哈夫曼译码器printf("-----------------哈夫曼译码器------------------\n"); printf("请输入编码:\n");scanf("%s",str);compileCode(str,n,hfmcode,hfmnode);printf("请输入需要译码的数字:\n");scanf("%s",num);decompileCode(num,n,hfmcode,hfmnode); }。
哈夫曼树c语言编码
哈夫曼树c语言编码哈夫曼树是一种基于最优化原则构造的二叉树,它可以用于数据压缩和编码。
它的思想是根据字符出现频率构造一颗优化的二叉树,使得字符编码的长度越短越好。
在本文中,我们将基于C语言编写哈夫曼编码。
第一步是计算字符出现的频率。
我们可以先定义一个数组来保存每个字符在文本中出现的次数,然后根据遍历文本来统计每个字符的出现次数。
例如:int freq[256] = {0};char str[] = "hello world";for(int i = 0; i < strlen(str); i++){freq[str[i]]++;}这个代码片段将字符“hello world”分解为单个字符,并使用数组 freq 来保存字符出现的次数。
这将使我们能够计算出每个字符出现的频率。
第二步是创建哈夫曼树的节点。
我们可以使用以下结构体来定义它:struct node{char ch;int freq;struct node *left, *right;};typedef node* huffNode;这个结构体包含了节点的字符值,该字符在文本中出现的频率以及左右子节点的指针。
第三步是创建叶子节点。
我们可以创建一个数组来保存所有叶子节点:huffNode leafNodes[256];for(int i = 0; i < 256; i++){if(freq[i] > 0){huffNode leaf = (huffNode)malloc(sizeof(node));leaf->ch = (char)i;leaf->freq = freq[i];leaf->left = NULL;leaf->right = NULL;leafNodes[i] = leaf;}}我们使用上述代码创建所有的叶子节点,并将其保存在数组leafNodes 中。
这将为构建哈夫曼树做好准备。
构造一棵哈夫曼树并输出叶子结点的哈夫曼编码
构造一棵哈夫曼树并输出叶子结点的哈夫曼编码1. 前言哈夫曼树是一种经典的树形结构,通常用于数据压缩和编码。
在哈夫曼树中,叶子结点代表不同的字符或符号,而内部结点则代表字符的频率或权重。
构造哈夫曼树的过程可以通过贪心算法来实现,这个过程非常有趣而且具有一定的挑战性。
本文将通过详细的步骤来介绍如何构造一棵哈夫曼树,并输出叶子结点的哈夫曼编码。
2. 基本概念在构造哈夫曼树之前,我们首先需要了解一些基本概念:- 哈夫曼树:由n个叶子结点构成的二叉树,具有最小的带权路径长度,即具有最小的总路径长度。
- 叶子结点:树中没有子结点的结点,代表字符或符号。
- 带权路径长度:从根结点到叶子结点的路径长度与叶子结点的权重(频率)的乘积之和。
- 哈夫曼编码:叶子结点的路径可以表示为0和1的序列,用来表示字符或符号。
3. 构造哈夫曼树的步骤下面,我们将通过详细的步骤来构造一棵哈夫曼树,并输出叶子结点的哈夫曼编码:3.1 初始化我们需要准备一组具有权重的叶子结点,代表不同的字符或符号。
每个叶子结点的权重可以根据字符在文本中出现的频率来确定。
3.2 构造哈夫曼树接下来,我们通过以下步骤来构造哈夫曼树:- 将所有的叶子结点按照权重从小到大进行排序。
- 选取权重最小的两个叶子结点作为左右子结点,然后将它们合并为一个新的内部结点,其权重为两个子结点的权重之和。
- 将新得到的内部结点插入到已排序的叶子结点中,并重新排序。
- 重复以上步骤,直到所有的叶子结点都被合并为一个根结点。
3.3 输出叶子结点的哈夫曼编码一旦我们构造出了哈夫曼树,我们就可以通过以下步骤来输出叶子结点的哈夫曼编码:- 从根结点开始,沿着左子树走为0,沿着右子树走为1,直到达到叶子结点。
- 将叶子结点的路径上的0和1序列记录下来,即为该叶子结点的哈夫曼编码。
4. 示例为了更加直观地理解哈夫曼树的构造过程,我们来看一个简单的示例:假设我们有以下四个叶子结点:A(1),B(2),C(3),D(4)(括号内为权重)。
哈夫曼编码的C语言实现
哈夫曼编码的C语言实现一、大致思路输入信源符号的概率,构造哈夫曼树,从叶子结点到根结点进行编码二、编码实现#include <stdio.h>#define n 7 //leaf number#define m 2*n-1 //all numbertypedef struct{char ch;double weight;int left;int right;int parent;}Node;typedef struct{char ch;int codeis[50];int start;}Code;void HuffmanTree (Node node[],int number){int i,j,x1=0,x2=0;double m1,m2;for(i=0;i<n-1;i++){ //loop n-1m1=m2=1; //least probability p<1//m1 最小 m2第二小for(j=0;j<n+i;j++){if(node[j].weight <m1 && node[j].parent ==-1){m2=m1;x2=x1;m1=node[j].weight;x1=j;} //是最小的else if(node[j].weight <m2 &&node[j].parent ==-1){m2=node[j].weight;x2=j;}} //找结点node[x1].parent = number+i;node[x2].parent = number+i;node[number+i].weight = node[x1].weight + node[x2].weight;node[number+i].left = x1;node[number+i].right = x2;}//end for}int main(int argc, const char * argv[]) {double x[n]={0};printf("请输入%d个符号的概率",n);int i;for(i=0;i<n;i++){scanf("%lf",&x[i]);}Node node[2*n-1]; // 2*len-1 is the number of all nodefor(i=0;i<2*n-1;i++){node[i].weight = 0;node[i].left = -1;node[i].right = -1;node[i].parent = -1;} //initializefor(i=0;i<n;i++){node[i].weight=x[i];}Code code[n],tempcode; //save the code of leafHuffmanTree(node,n); //创建好了哈夫曼树//编码int p,c,j=0;for(i=0;i<n;i++){c=i;tempcode.start = n-1;p=node[c].parent;while(p!=-1){if(node[p].left == c)tempcode.codeis[tempcode.start] = 1; elsetempcode.codeis[tempcode.start] = 0; tempcode.start--;c=p;p=node[c].parent;} //end whilefor(j=tempcode.start+1;j<n;j++){code[i].codeis[j]=tempcode.codeis[j];}//保存下载刚才的结果code[i].start = tempcode.start;} //end forfor (i=0;i<n;i++){for (j=code[i].start+1;j<n;j++){printf("%d",code[i].codeis[j]);}printf("\n");}getchar();return 0;}三、总结1.创建了哈夫曼树,n是叶子结点数。
哈夫曼树的编码实现
哈夫曼树的编码实现#include<stdio.h>#include<string.h>#include<stdlib.h>//树结点定义typedef struct{int weight;int parent;int lchild;int rchild;}HTNode,*HuffmanTree;static char N[100];//⽤于保存正⽂//哈弗曼编码,char型⼆级指针typedef char **HuffmanCode;//封装最⼩权结点和次⼩权结点typedef struct{int s1;int s2;}MinCode;//函数声明void Error(char *message);HuffmanCode HuffmanCoding(HuffmanTree &HT,HuffmanCode HC,int *w,int n);MinCode Select(HuffmanTree HT,int n);//当输⼊1个结点时的错误提⽰void Error(char *message){fprintf(stderr,"Error:%s\n",message);exit(1);}//构造哈夫曼树HT,编码存放在HC中,w为权值,n为结点个数HuffmanCode HuffmanCoding(HuffmanTree &HT,HuffmanCode HC,int *w,int n){int i,s1=0,s2=0;HuffmanTree p;char *cd;int f,c,start,m;MinCode min;if(n<=1){Error("Code too small!");//只有⼀个结点不进⾏编码,直接exit(1)退出。
⾮return,如果return 会造成main函数HT[i]⽆值 }m=2*n-1;//哈弗曼编码需要开辟的结点⼤⼩为2n-1HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));//开辟哈夫曼树结点空间 m+1 。
C语言实现哈夫曼树的方法
C语⾔实现哈夫曼树的⽅法本⽂实例为⼤家分享了C语⾔实现哈夫曼树的具体代码,供⼤家参考,具体内容如下准备⼯作:1、定义⼀个结构体,表⽰⼀个节点。
其中,这个结构体有4个成员变量,分别表⽰是这个节点的权值,⽗节点及左右⼦节点的下标2、定义⼀个整形数组,⽤于存放各个节点的权值3、定义⼀个整形数组,⽤于存放哈夫曼编码,当然也可以定义⼀个整形数组来存放哈夫曼编码构建哈夫曼树:1、给这个哈夫曼树创建⼀个结构体数组,其中分配的空间是2 * n - 1,因为我们都知道哈夫曼树的性质有⼀个是:给定n个叶⼦节点,那么由这n个叶⼦节点构成的哈夫曼树⼀共含有2 * n - 1个节点。
2、结构体数组前⾯n个⽤于存放n个叶⼦节点,然后后⾯的n - 1个节点⽤于存放⽗节点。
这时候,我们需要遍历这个结构体数组,将所有的节点的进⾏初始化,即节点的权值就是结构体数组各个下标对应的值,然后节点的⽗节点及⼦节点的下标为-1,表⽰的是这个节点没有⽗节点,同时也没有⼦节点。
3、遍历数组,将获取数组中两个最⼩的叶⼦节点,然后将他们的权值合并构成⼀个新节点。
在这⼀步中,我们同时需要知道这两个最⼩节点在结构体数组中的下标,只有这样,我们才可以知道它的⽗节点的左右⼦节点的下标,在初始化⽗节点的时候需要⽤到。
4、如果已经进⾏了n - 1次数操作,表明已经构建完成了。
获取哈夫曼编码:1、由于我们将所有节点的权值都赋值给了⼀个数组,并且哈夫曼树中的节点的下标和这个数组的下标是⼀⼀对应的,那么我们只需要⾸先在数组中获取这个数字的下标,就表⽰他在哈夫满树中的下标也是这个,然后往它的⽗节点⽅向⾛,如果当前节点时它⽗节点的右⼦节点,那么就将1存放到数组arr2中,否则字符将0存放到数组arr2中。
重复这⼀步,直到当前的节点的⽗节点为空,及已经遍历到了根节点。
2、重复步骤⼀,存放数字的数组已经遍历完了,这时候已经将所有数字的哈夫曼编码都已经输出了#include<stdio.h>#define MAX_SIZE 1000typedef struct NODE Node;struct NODE{int weight;//节点的权值int parent,lchild,rchild;};/*初始化或者更改节点的信息,⽐如,如果这个节点是⼀个新节点,那么就需要将这个节点初始化成⼀个叶⼦节点,否则需要修改这个节点的⽗节点*/void initNode(Node &node,int weight,int parent,int lchild,int rchild){node.weight = weight;node.lchild = lchild;node.rchild = rchild;node.parent = parent;}/*1、有n个叶⼦节点,那么构建哈夫曼树的时候,需要分配n * 2 - 1个内存空间,前n个表⽰的是新输⼊的叶⼦节点,后⾯n - 1表⽰的是叶⼦节点的⽗节点2、遍历这个数组,将进⾏初始化,即给这些节点的权值赋值,并且将他的左右⼦节点、⽗节点赋初始值为-1,从⽽构建了n个叶⼦节点3、遍历数组,从⽽将从这个数组中跳出两个值最⼩的叶⼦节点,同时需要标记他们的下标,从⽽可以知道当前最⼩值节点的⽗节点的左右⼦节点的下标,⽅便下次寻找最⼩值的叶⼦结点的时候不会再找到已经找过的叶⼦节点4、将新节点插⼊到数组的最后。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
二 课程设计题目及要求
{
fputs(hufcodes[j],fp);//写入文件
cout<<hufcodes[j];//输出到屏幕
}
}
cout<<endl;
fclose(fp);
cout<<"写入成功"<<endl;
}
/********************************************************************/
break;
}
}
for(i=0;i<count;i++)
{
cout<<str1[i]<<" ";
}
cout<<endl;
for(i=0;i<count;i++)
{
cout<<weight[i]<<" ";
}
cout<<endl;
/********************************************************************/
{
leafNum=n;
huftree=new TriNode<int>[2*n-1];
int i;
for(i=0;i<n;i++)
{
huftree[i].data=weight[i];
huftree[i].parent=huftree[i].left=huftree[i].right=-1;
}
for(i=0;i<n-1;i++)
{
private:
char str[1000]; //输入的字符串
char str1[1000]; //哈弗曼叶子值
int leafNum; //子叶结点个数
TriNode<int> *huftree; //哈弗曼的结点数组
char **hufcodes; //哈弗曼编码数组
void createHuffmanTree(int weight[],int n); //创建指定权值集合的哈弗曼树
{
char *code=new char[n];
code[n-1]='\0';
int start=n-1;
int child=i;
int parent=huftree[child].parent;
while(parent!=-1)
{
start--;
if(huftree[parent].left==child)
createHuffmanTree(weight,count);
getHuffmanCode();
}
/********************************************************************/
void HuffmanTree::createHuffmanTree(int weight[],int n) //创建指定权值集合的哈弗曼树
{
if(u!=-1)//判断是否有孩子
{
for(int e=1;e<getheight(u);e++)//循环小于高度,目的是为了确定该节点前有多少个空格
{
if(e==getheight(u)-1)//在循环的最后一位输出下面字符
cout<<"|_____";
else cout<<" ";//循环输出空格
code[start]='0';
else
code[start]='1';
child=parent;
parent=huftree[child].parent;
}
hufcodes[i]=code+start;
}
}
/********************************************************************/
{
int min1,min2,x1,x2;
min1=min2=Max_Weight;
x1=x2=-1;
for(int j=0;ቤተ መጻሕፍቲ ባይዱ<n+i;j++)
{
if(huftree[j].data<min1&&huftree[j].parent==-1)
{
min2=min1;
x2=x1;
min1=huftree[j].data;
{
return leafNum;
}
ReadFile.h
#include<iostream.h>
#include<stdio.h>
#include<string.h>
void readFile(char *str1,char **hufcodes,int leafNum)//带入参数哈弗曼节点字符串哈弗曼编码字符串数组,哈弗曼节点数
char* HuffmanTree::getstr1()//str1访问器
{
return str1;
}
char** HuffmanTree::gethufcodes()//hufcodes访问器
{
return hufcodes;
}
int HuffmanTree::getleafNum()//leafNum访问器
void print();
void print(int u);
int getheight(int r);//得出r节点的深度
};
const Max_Weight=9999; //默认最大权值
/*******************************************************************/
{
for(j=0;j<count+1;j++)
if(str[i]!=str1[j]) k++;//如果str中的字符在str1中扫描不等k++,k初值为0
if(k==count+1)//如果k等于字符串str1的长度的话说明str[i]在str1中没出现,加到str1中
str1[count++]=str[i];
void getHuffmanCode(); //获得哈弗曼编码
public:
HuffmanTree(char str5[]);
~HuffmanTree();
void writetoFile(); //写入文件
char** gethufcodes();
char* getstr1();
int getleafNum();
{
FILE *fp;
int i,j;
fp=fopen("code.txt","w");//以读的方式创建文件
for(i=0;i<strlen(str);i++)//扫描字符串str每一位与str1中的每一为比较若相等写入该位置的哈弗曼的编码
for(j=0;j<leafNum;j++)
{
if(str[i]==str1[j]) //主要目的是得出j值str1和weight和hafcodes的每一位都一一对应
采用静态三叉链表构造一棵Huffman树并求其编码
增加了权值的计算和Huffman树的输出并写入code文件
三主函数及分析
it学习网收集
主程序代码
Main.cpp
#include<iostream.h>
#include<string.h>
#include"readFile.h"
return 0;
}
HuffmanTree.h
#include<iostream.h>
#include<stdio.h>
#include<string.h>
template<class T>
struct TriNode
{
T data;
int parent,left,right;
};
class HuffmanTree
weight[i]=0;
for(i=0;i<strlen(str);i++)//从第一个开始扫描str让str的每一个字符和str1比较在str1中相等的地方让weight的值++
for(j=0;j<count;j++)
{
if(str[i]==str1[j])
{
weight[j]++;//weight中的每一位对应着str1中的每一位
课程设计题目:
采用静态三叉链表构造一棵Huffman树并求其编码
一 课程设计应达到的目的:
数据结构课程设计的目的是,为了让学生在学习 《数据结构》 课程的基础上深入理解数据结构的基本理论,掌握对数据结构的各种操作的算法设计方法,增强对基础知识和基本方法的综合运用能力,增强对算法的理解能力,提高软件设计能力,在实践中培养独立分析问题和解决问题的作风和能力,进一步深入巩固所学理论知识、使理论与实际相结合的重要实践环节。本课程设计通过完成一些具有一定难度的程序的编写、调试、运行工作,掌握面向过程程序设计的基本方法,从而提高学生分析问题解决问题的能力。