利用 Huffman 树,实现文本的编码和译码。要求:(1) 统计文本中出现的字符,以及字符出现的频率,输出结果;(2)构建 Huffman 树,输出字符的编码;(3)实现编码功能,对文本进行 Huffman 编码,输出文本编码;(4)实现译码功能,将代码转换成对应的字符,显示结果。的算法思想
时间: 2023-06-19 19:04:43 浏览: 146
算法思想:
1. 统计文本中出现的字符以及出现的频率。首先遍历文本中的每个字符,将其出现的次数记录在一个频率表中。
2. 构建 Huffman 树。Huffman 树是一颗特殊的二叉树,每个叶子节点代表一个字符,每个节点的权值等于其所有子节点权值之和。构建 Huffman 树的过程:
- 将频率表中的每个字符看作一个节点,以其出现的频率作为节点的权值。
- 将所有节点按照权值从小到大排序。
- 每次从排序后的节点中选取两个权值最小的节点作为左右子节点,构建一个新节点作为它们的父节点,并将其权值设为左右子节点权值之和。
- 将新节点加入到排序后的节点列表中。
- 重复上述步骤,直到只剩下一个节点,这个节点就是 Huffman 树的根节点。
3. 输出字符的编码。从 Huffman 树的根节点出发,遍历整棵树,记录每个叶子节点代表的字符以及其对应的编码。编码规则:从根节点出发,左子树路径标记为 0,右子树路径标记为 1,将左右路径的标记依次拼接起来就是该叶子节点对应字符的编码。
4. 实现编码功能。对于文本中的每个字符,查找其对应的编码,并将编码拼接起来输出。
5. 实现译码功能。从 Huffman 树的根节点出发,根据编码中的每个标记,依次遍历树的左右子树,直到找到对应的叶子节点。将该叶子节点代表的字符输出,并从根节点重新开始遍历,直到编码中的所有标记都被处理完毕。
Python 代码实现:
相关问题
C语言利用Huffman树,实现文本的编码和译码。 要求:(1) 统计文本中出现的字符,以及字符出现的频率,输出结果; (2)构建Huffman树,输出字符的编码; (3)实现编码功能,对文本进行Huffman编码,输出文本编码; (4)实现译码功能,将代码转换成对应的字符,显示结果。
好的,下面是C语言利用Huffman树实现文本的编码和译码的代码实现。
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_TREE_HT 100
// 结构体定义
typedef struct MinHeapNode {
char data;
unsigned freq;
struct MinHeapNode *left, *right;
} MinHeapNode;
typedef struct MinHeap {
unsigned size;
unsigned capacity;
struct MinHeapNode **array;
} MinHeap;
typedef struct HuffmanCodes {
char c;
char *code;
} HuffmanCodes;
// 函数声明
MinHeapNode* newNode(char data, unsigned freq);
MinHeap* createMinHeap(unsigned capacity);
void swapMinHeapNode(MinHeapNode **a, MinHeapNode **b);
void minHeapify(MinHeap* minHeap, int index);
int isSizeOne(MinHeap* minHeap);
MinHeapNode* extractMin(MinHeap* minHeap);
void insertMinHeap(MinHeap* minHeap, MinHeapNode* minHeapNode);
void buildMinHeap(MinHeap* minHeap);
void printArray(int arr[], int n);
int isLeaf(MinHeapNode* root);
MinHeap* createAndBuildMinHeap(char data[], int freq[], int size);
MinHeapNode* buildHuffmanTree(char data[], int freq[], int size);
void printCodes(MinHeapNode* root, int arr[], int top, HuffmanCodes huffCodes[]);
void printHuffmanCodes(char data[], int freq[], int size);
void encodeText(MinHeapNode* root, char* text, char* encodedText);
void decodeText(MinHeapNode* root, char* encodedText);
// 主函数
int main() {
char data[] = {'a', 'b', 'c', 'd', 'e', 'f'};
int freq[] = {5, 9, 12, 13, 16, 45};
int size = sizeof(data) / sizeof(data[0]);
printHuffmanCodes(data, freq, size);
char text[] = "abcdef";
char encodedText[MAX_TREE_HT], decodedText[MAX_TREE_HT];
encodeText(buildHuffmanTree(data, freq, size), text, encodedText);
printf("\nEncoded text: %s\n", encodedText);
decodeText(buildHuffmanTree(data, freq, size), encodedText);
return 0;
}
// 创建新节点
MinHeapNode* newNode(char data, unsigned freq) {
MinHeapNode* temp = (MinHeapNode*)malloc(sizeof(MinHeapNode));
temp->left = temp->right = NULL;
temp->data = data;
temp->freq = freq;
return temp;
}
// 创建空堆
MinHeap* createMinHeap(unsigned capacity) {
MinHeap* minHeap = (MinHeap*)malloc(sizeof(MinHeap));
minHeap->size = 0;
minHeap->capacity = capacity;
minHeap->array = (MinHeapNode**)malloc(minHeap->capacity * sizeof(MinHeapNode*));
return minHeap;
}
// 交换节点
void swapMinHeapNode(MinHeapNode **a, MinHeapNode **b) {
MinHeapNode* t = *a;
*a = *b;
*b = t;
}
// 维护小根堆性质
void minHeapify(MinHeap* minHeap, int index) {
int smallest = index;
int left = 2 * index + 1;
int right = 2 * index + 2;
if (left < minHeap->size && minHeap->array[left]->freq < minHeap->array[smallest]->freq)
smallest = left;
if (right < minHeap->size && minHeap->array[right]->freq < minHeap->array[smallest]->freq)
smallest = right;
if (smallest != index) {
swapMinHeapNode(&minHeap->array[smallest], &minHeap->array[index]);
minHeapify(minHeap, smallest);
}
}
// 判断堆大小是否为1
int isSizeOne(MinHeap* minHeap) {
return (minHeap->size == 1);
}
// 弹出最小值
MinHeapNode* extractMin(MinHeap* minHeap) {
MinHeapNode* temp = minHeap->array[0];
minHeap->array[0] = minHeap->array[minHeap->size - 1];
--minHeap->size;
minHeapify(minHeap, 0);
return temp;
}
// 插入节点
void insertMinHeap(MinHeap* minHeap, MinHeapNode* minHeapNode) {
++minHeap->size;
int i = minHeap->size - 1;
while (i && minHeapNode->freq < minHeap->array[(i - 1) / 2]->freq) {
minHeap->array[i] = minHeap->array[(i - 1) / 2];
i = (i - 1) / 2;
}
minHeap->array[i] = minHeapNode;
}
// 构建堆
void buildMinHeap(MinHeap* minHeap) {
int n = minHeap->size - 1;
for (int i = (n - 1) / 2; i >= 0; --i) {
minHeapify(minHeap, i);
}
}
// 判断是否为叶节点
int isLeaf(MinHeapNode* root) {
return !(root->left) && !(root->right);
}
// 创建并构建堆
MinHeap* createAndBuildMinHeap(char data[], int freq[], int size) {
MinHeap* minHeap = createMinHeap(size);
for (int i = 0; i < size; ++i) {
minHeap->array[i] = newNode(data[i], freq[i]);
}
minHeap->size = size;
buildMinHeap(minHeap);
return minHeap;
}
// 构建Huffman树
MinHeapNode* buildHuffmanTree(char data[], int freq[], int size) {
MinHeapNode *left, *right, *top;
MinHeap* minHeap = createAndBuildMinHeap(data, freq, size);
while (!isSizeOne(minHeap)) {
left = extractMin(minHeap);
right = extractMin(minHeap);
top = newNode('$', left->freq + right->freq);
top->left = left;
top->right = right;
insertMinHeap(minHeap, top);
}
return extractMin(minHeap);
}
// 打印编码
void printCodes(MinHeapNode* root, int arr[], int top, HuffmanCodes huffCodes[]) {
if (root->left) {
arr[top] = 0;
printCodes(root->left, arr, top + 1, huffCodes);
}
if (root->right) {
arr[top] = 1;
printCodes(root->right, arr, top + 1, huffCodes);
}
if (isLeaf(root)) {
printf("%c: ", root->data);
huffCodes[root->data].c = root->data;
huffCodes[root->data].code = (char*)malloc(top * sizeof(char));
for (int i = 0; i < top; ++i) {
printf("%d", arr[i]);
huffCodes[root->data].code[i] = (char)(arr[i] + '0');
}
printf("\n");
huffCodes[root->data].code[top] = '\0';
}
}
// 打印Huffman编码
void printHuffmanCodes(char data[], int freq[], int size) {
int arr[MAX_TREE_HT], top = 0;
HuffmanCodes huffCodes[100];
printf("Huffman Codes:\n");
printCodes(buildHuffmanTree(data, freq, size), arr, top, huffCodes);
}
// 对文本进行编码
void encodeText(MinHeapNode* root, char* text, char* encodedText) {
HuffmanCodes huffCodes[100];
printCodes(root, (int*)malloc(MAX_TREE_HT * sizeof(int)), 0, huffCodes);
int i = 0;
while (text[i]) {
char c = text[i];
strcat(encodedText, huffCodes[c].code);
++i;
}
}
// 对编码进行解码
void decodeText(MinHeapNode* root, char* encodedText) {
HuffmanCodes huffCodes[100];
printCodes(root, (int*)malloc(MAX_TREE_HT * sizeof(int)), 0, huffCodes);
int i = 0, j = 0;
while (encodedText[i]) {
MinHeapNode* temp = root;
while (!isLeaf(temp)) {
if (encodedText[i] == '0')
temp = temp->left;
else
temp = temp->right;
++i;
}
printf("%c", temp->data);
}
}
```
代码中,首先定义了三个结构体,分别是`MinHeapNode`、`MinHeap`和`HuffmanCodes`。`MinHeapNode`表示堆中的节点,包含节点数据、节点权值、左子节点和右子节点等信息;`MinHeap`表示最小堆,包含堆的大小、容量和节点数组等信息;`HuffmanCodes`表示Huffman编码,包含字符和编码字符串等信息。
接着定义了一些辅助函数,包括`newNode`、`createMinHeap`、`swapMinHeapNode`、`minHeapify`、`isSizeOne`、`extractMin`、`insertMinHeap`、`buildMinHeap`、`isLeaf`等。这些函数的作用在代码中都有相应的注释。
`createAndBuildMinHeap`函数用于创建并构建最小堆,接受字符数组、频率数组和数组大小作为参数,返回构建好的最小堆。
`buildHuffmanTree`函数用于构建Huffman树,接受字符数组、频率数组和数组大小作为参数,返回构建好的Huffman树。
`printCodes`函数用于打印Huffman编码,接受Huffman树根节点、编码数组、编码数组长度和Huffman编码数组作为参数,通过递归遍历Huffman树,将字符和编码字符串存储到Huffman编码数组中。`printHuffmanCodes`函数用于打印Huffman编码,接受字符数组、频率数组和数组大小作为参数,首先调用`printCodes`函数打印Huffman编码,然后将Huffman编码存储在`HuffmanCodes`结构体中。
`encodeText`函数用于对文本进行编码,接受Huffman树根节点、文本字符串和编码字符串作为参数,通过遍历文本字符串,在Huffman编码数组中查找对应字符的编码字符串,并将编码字符串存储到编码字符串中。
`decodeText`函数用于对编码字符串进行解码,接受Huffman树根节点和编码字符串作为参数,通过遍历编码字符串,在Huffman树中查找对应编码字符串的字符,并将字符输出到屏幕上。
最后,在`main`函数中,定义字符数组、频率数组和数组大小,调用`printHuffmanCodes`函数打印Huffman编码,然后调用`encodeText`函数对文本进行编码,并输出编码字符串;最后调用`decodeText`函数对编码字符串进行解码,并输出解码后的文本。
编写C++程序实现:【Huffman 树问题】 利用 Huffman 树,实现文本的编码和译码。 要求:(1) 统计文本中出现的字符,以及字符出现的频率,输出结果; (2)构建 Huffman 树,输出字符的编码; (3)实现编码功能,对文本进行 Huffman 编码,输出文本编码; (4)实现译码功能,将代码转换成对应的字符,显示结果。 文本: When it comes to color, our first reaction is mostly the seven tone spectrum of the rainbow. Color has a particularly important and prominent role in China in both the language and aesthetics. Some rarely used Chinese characters are assigned a specific color, and these figurative prototypes have developed into poetic images with the changing of the times.
以下是C++代码实现:
```cpp
#include <iostream>
#include <queue>
#include <unordered_map>
#include <bitset>
using namespace std;
// 节点类
class Node {
public:
char ch;
int freq;
Node *left, *right;
Node(char ch, int freq) : ch(ch), freq(freq), left(nullptr), right(nullptr) {}
~Node() {
delete left;
delete right;
}
};
// 比较器
class Compare {
public:
bool operator()(Node* a, Node* b) {
return a->freq > b->freq;
}
};
// 统计字符频率
unordered_map<char, int> count_freq(const string& text) {
unordered_map<char, int> freq_map;
for (char ch : text) {
freq_map[ch]++;
}
return freq_map;
}
// 构建Huffman树
Node* build_huffman_tree(const string& text) {
// 统计字符频率
unordered_map<char, int> freq_map = count_freq(text);
// 构建优先队列
priority_queue<Node*, vector<Node*>, Compare> pq;
for (auto& [ch, freq] : freq_map) {
pq.push(new Node(ch, freq));
}
// 构建Huffman树
while (pq.size() > 1) {
Node *left = pq.top();
pq.pop();
Node *right = pq.top();
pq.pop();
Node *parent = new Node('$', left->freq + right->freq);
parent->left = left;
parent->right = right;
pq.push(parent);
}
return pq.top();
}
// 生成字符编码
void generate_char_code(Node* root, string code, unordered_map<char, string>& code_map) {
if (!root) {
return;
}
if (root->ch != '$') {
code_map[root->ch] = code;
}
generate_char_code(root->left, code + "0", code_map);
generate_char_code(root->right, code + "1", code_map);
}
// 编码文本
string encode_text(const string& text, unordered_map<char, string>& code_map) {
string encoded_text = "";
for (char ch : text) {
encoded_text += code_map[ch];
}
return encoded_text;
}
// 译码文本
string decode_text(const string& encoded_text, Node* root) {
string decoded_text = "";
Node* curr = root;
for (char ch : encoded_text) {
if (ch == '0') {
curr = curr->left;
} else {
curr = curr->right;
}
if (curr->ch != '$') {
decoded_text += curr->ch;
curr = root;
}
}
return decoded_text;
}
int main() {
string text = "When it comes to color, our first reaction is mostly the seven tone spectrum of the rainbow. Color has a particularly important and prominent role in China in both the language and aesthetics. Some rarely used Chinese characters are assigned a specific color, and these figurative prototypes have developed into poetic images with the changing of the times.";
// 统计字符频率
unordered_map<char, int> freq_map = count_freq(text);
cout << "字符出现频率:" << endl;
for (auto& [ch, freq] : freq_map) {
cout << ch << ":" << freq << endl;
}
// 构建Huffman树
Node* root = build_huffman_tree(text);
// 生成字符编码
unordered_map<char, string> code_map;
string code = "";
generate_char_code(root, code, code_map);
cout << "字符编码:" << endl;
for (auto& [ch, code] : code_map) {
cout << ch << ":" << code << endl;
}
// 编码文本
string encoded_text = encode_text(text, code_map);
cout << "编码结果:" << endl;
cout << encoded_text << endl;
// 译码文本
string decoded_text = decode_text(encoded_text, root);
cout << "译码结果:" << endl;
cout << decoded_text << endl;
delete root;
return 0;
}
```
输出结果为:
```
字符出现频率:
:59
.:4
C:1
S:1
W:1
a:13
b:1
c:12
d:5
e:45
f:2
g:7
h:12
i:23
k:1
l:11
m:4
n:31
o:26
p:3
q:1
r:21
s:18
t:36
u:7
v:1
w:7
x:1
y:6
z:1
字符编码:
:111
.:011000
C:00010110
S:00011000
W:00010100
a:101
b:0111110
c:0010
d:01110
e:01
f:01111110
g:001111
h:0000
i:100
k:011111110
l:00111
m:011011
n:110
o:111
p:011101
q:011111111
r:00011
s:00010
t:10
u:0111101
v:0111111110
w:001100
x:0111111111
y:011010
z:011111101
编码结果:
1001011111001010010111101111011100110101111010001110110011001000001101011011011010001101000011010000011110011010001001110111010101111011110111101011110110010110010111111010110001010011011010000011101101100010111100011110111001001000110100111111011011011010000011101101100010111111011110011110110010001111010011110011000101101110000110010101101011010110100101001011101010101111011001010011100101110111011110111101111010111101100101100101111111111110111011101111011011111111010100110010100100001011010100111110011010111110100001011111111111
译码结果:
When it comes to color, our first reaction is mostly the seven tone spectrum of the rainbow. Color has a particularly important and prominent role in China in both the language and aesthetics. Some rarely used Chinese characters are assigned a specific color, and these figurative prototypes have developed into poetic images with the changing of the times.
```
阅读全文