由键盘输入一组整数作为权值序列,求huffman编码
时间: 2023-11-01 09:03:31 浏览: 134
Huffman编码是一种用于无损数据压缩的算法,在该算法中,使用出现频率较高的字符使用较短的编码,而出现频率较低的字符使用较长的编码,以此来减小存储或传输数据所需的字节数。
要求输入的一组整数作为权值序列,可以先根据每个整数出现的次数作为权值,构建一颗Huffman树来生成编码。
首先,统计输入的一组整数中每个整数出现的次数,得到每个整数的权值。然后,根据权值构建Huffman树。
构建Huffman树的具体步骤如下:
1. 将每个整数作为树的叶子节点,节点的权值为出现的次数。
2. 将所有的叶子节点按照权值从小到大进行排序。
3. 取出权值最小的两个节点,将它们作为左右子节点创建一个新的父节点。
4. 将新创建的父节点的权值设置为两个子节点的权值之和。
5. 将新创建的父节点插入到已排序的节点列表中。
6. 重复步骤3~5,直到只剩下一个节点,此时这个节点就是Huffman树的根节点。
7. 通过树的路径来得到每个整数的Huffman编码。遍历树的路径,向左走为0,向右走为1,直到达到叶子节点,将路径上的0和1依次拼接起来就是整数的Huffman编码。
最后,根据构建好的Huffman树,将每个整数的Huffman编码输出即可。
需要注意的是,如果输入的一组整数中只有一个整数或者有些整数没有出现,那么对应的Huffman编码可能会出现问题。
相关问题
c语言【问题描述】 输入哈夫曼字符序列,构造哈夫曼树,并计算哈夫曼编码 【输入形式】 第一行输入整数n,表示n个字符(n>1并且不大于10); 后续输入n行哈夫曼字符及其权值(字符和权值以逗号分隔)。 【输出形式】 输出哈夫曼树的顺序存储形式(数据之间以空格分隔) 输出哈夫曼编码 【样例输入】 7 a,10 c,1 e,15 i,12 s,3 t,4 w,13 【样例输出】 HuffTable: a 10 9 -1 -1 c 1 7 -1 -1 e 15 11 -1 -1 i 12 10 -1 -1 s 3 7 -1 -1 t 4 8 -1 -1 w 13 10 -1 -1 0 4 8 1 4 0 8 9 5 7 0 18 11 8 0 0 25 12 3 6 0 33 12 2 9 0 58 -1 10 11 HuffCode: a:111 c:11010 e:10 i:00 s:11011 t:1100 w:01
以下是C语言实现的代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_N 10 // 最大字符数
#define MAX_TREE_SIZE (2 * MAX_N - 1) // 最大哈夫曼树节点数
#define MAX_CODE_LEN 20 // 最大编码长度
// 哈夫曼树节点结构体
typedef struct {
int weight; // 权值
int parent; // 双亲节点下标
int left; // 左孩子节点下标
int right; // 右孩子节点下标
} HTNode;
// 哈夫曼编码结构体
typedef struct {
char ch; // 字符
char code[MAX_CODE_LEN + 1]; // 编码
} CodeNode;
void huffmanEncoding(int n, char chList[], int weightList[]);
void createHuffmanTree(HTNode huffTree[], int n);
void selectTwoMinWeight(HTNode huffTree[], int n, int* pMin1, int* pMin2);
void huffmanCoding(HTNode huffTree[], int n, CodeNode codeList[]);
void printHuffTable(HTNode huffTree[], int n);
void printHuffCode(CodeNode codeList[], int n);
int main() {
int n, i, weight;
char chList[MAX_N];
// 输入n和每个字符的权值
scanf("%d", &n);
int weightList[n];
for (i = 0; i < n; i++) {
getchar(); // 读入空格
scanf("%c,%d", &chList[i], &weightList[i]);
}
huffmanEncoding(n, chList, weightList);
return 0;
}
// 哈夫曼编码
void huffmanEncoding(int n, char chList[], int weightList[]) {
HTNode huffTree[MAX_TREE_SIZE];
CodeNode codeList[MAX_N];
int i;
createHuffmanTree(huffTree, n);
huffmanCoding(huffTree, n, codeList);
printHuffTable(huffTree, n);
printHuffCode(codeList, n);
}
// 构造哈夫曼树
void createHuffmanTree(HTNode huffTree[], int n) {
int i, m, min1, min2;
// 初始化哈夫曼树节点
for (i = 0; i < 2 * n - 1; i++) {
huffTree[i].weight = 0;
huffTree[i].parent = -1;
huffTree[i].left = -1;
huffTree[i].right = -1;
}
// 输入每个节点的权值
for (i = 0; i < n; i++) {
huffTree[i].weight = weightList[i];
}
// 构造哈夫曼树
m = 2 * n - 1;
for (i = n; i < m; i++) {
selectTwoMinWeight(huffTree, i, &min1, &min2);
huffTree[min1].parent = i;
huffTree[min2].parent = i;
huffTree[i].left = min1;
huffTree[i].right = min2;
huffTree[i].weight = huffTree[min1].weight + huffTree[min2].weight;
}
}
// 选择权值最小的两个节点
void selectTwoMinWeight(HTNode huffTree[], int n, int* pMin1, int* pMin2) {
int i, min1, min2;
min1 = min2 = -1;
for (i = 0; i < n; i++) {
if (huffTree[i].parent == -1) {
if (min1 == -1 || huffTree[i].weight < huffTree[min1].weight) {
min2 = min1;
min1 = i;
} else if (min2 == -1 || huffTree[i].weight < huffTree[min2].weight) {
min2 = i;
}
}
}
*pMin1 = min1;
*pMin2 = min2;
}
// 哈夫曼编码
void huffmanCoding(HTNode huffTree[], int n, CodeNode codeList[]) {
int i, j, parent, current;
char code[MAX_CODE_LEN + 1];
// 初始化编码表
for (i = 0; i < n; i++) {
codeList[i].ch = chList[i];
codeList[i].code[0] = '\0';
}
// 从叶子节点向根节点遍历
for (i = 0; i < n; i++) {
current = i;
parent = huffTree[current].parent;
while (parent != -1) {
if (huffTree[parent].left == current) {
strcat(code, "0");
} else {
strcat(code, "1");
}
current = parent;
parent = huffTree[current].parent;
}
strrev(code); // 将编码反转
strcpy(codeList[i].code, code);
code[0] = '\0';
}
}
// 输出哈夫曼表
void printHuffTable(HTNode huffTree[], int n) {
int i;
printf("HuffTable:");
for (i = 0; i < n; i++) {
printf(" %c %d %d %d %d", chList[i], huffTree[i].weight, huffTree[i].parent, huffTree[i].left, huffTree[i].right);
}
printf(" %d %d %d %d %d\n", huffTree[n].weight, huffTree[n].parent, huffTree[n].left, huffTree[n].right, 0);
}
// 输出哈夫曼编码
void printHuffCode(CodeNode codeList[], int n) {
int i;
printf("HuffCode:");
for (i = 0; i < n; i++) {
printf(" %c:%s", codeList[i].ch, codeList[i].code);
}
printf("\n");
}
```
哈夫曼编码 要求: (1)根据所给定的图,实现下列函数编写: (2)用户输入结点个数,结点名称和权值,请构建哈夫曼树,进行哈夫曼编码 (3)用户输入一串字符,实现编码;用户输入编码,实现译码。
好的,我会按照您的要求回答问题。
首先,我需要说明一下,作为一个 AI 模型,我并没有直接的编程能力,无法直接进行程序的编写和执行。但我可以提供一些思路和算法,帮助您完成这个问题。
对于您提出的问题,我们可以按照以下步骤进行处理:
1. 构建哈夫曼树
哈夫曼树是一种特殊的二叉树,它的构建需要依据给定的权值,按照从小到大的顺序构建一棵树。具体步骤如下:
- 将所有的结点按照权值从小到大排序,每个结点可以看做一棵只有根节点的树。
- 从排好序的结点列表中,选取权值最小的两个结点,将它们合并成一棵新的树,根节点的权值为两个子节点的权值之和,左子树为权值较小的子节点,右子树为权值较大的子节点。
- 将新生成的树插入到排好序的结点列表中,删除原来的两个子节点,重新排序。
- 重复上述步骤,直到只剩下一棵树,即为哈夫曼树。
2. 进行哈夫曼编码
哈夫曼编码是一种前缀编码,即每个字符的编码都是一串 0 和 1 的序列,且每个字符的编码都不是另一个字符编码的前缀。具体步骤如下:
- 从哈夫曼树的根节点开始,遍历整棵树。每次遍历到左子树,就在当前编码序列的末尾添加一个 0,每次遍历到右子树,就在当前编码序列的末尾添加一个 1。
- 当遍历到叶子结点时,记录下该叶子结点对应的字符和编码序列。
- 对于每个字符的编码,可以将整个编码序列压缩成一个整数,方便存储和传输。
3. 进行哈夫曼译码
哈夫曼译码是将一串编码序列解码成原来的字符序列。具体步骤如下:
- 从哈夫曼树的根节点开始,遍历整棵树。每次读入一个编码位,如果是 0,就遍历左子树,如果是 1,就遍历右子树,直到遍历到叶子结点。
- 当遍历到叶子结点时,输出该叶子结点对应的字符,然后重新回到根节点,继续读入下一个编码位,直到读完整个编码序列。
实现上述算法的具体代码,可以参考下面的示例:
```python
class Node:
def __init__(self, name, weight):
self.name = name
self.weight = weight
self.left = None
self.right = None
def build_huffman_tree(nodes):
while len(nodes) > 1:
node1 = nodes.pop(0)
node2 = nodes.pop(0)
parent = Node("", node1.weight + node2.weight)
parent.left = node1
parent.right = node2
nodes.append(parent)
nodes.sort(key=lambda x: x.weight)
return nodes[0]
def build_huffman_code(node, prefix="", code={}):
if node.left is None and node.right is None:
code[node.name] = prefix
else:
build_huffman_code(node.left, prefix + "0", code)
build_huffman_code(node.right, prefix + "1", code)
def encode_huffman(code, text):
encoded_text = ""
for c in text:
encoded_text += code[c]
return int(encoded_text, 2)
def decode_huffman(root, code, encoded_text):
decoded_text = ""
node = root
for bit in bin(encoded_text)[2:]:
if bit == '0':
node = node.left
else:
node = node.right
if node.left is None and node.right is None:
decoded_text += node.name
node = root
return decoded_text
# 测试代码
nodes = [Node('A', 2), Node('B', 3), Node('C', 7), Node('D', 10)]
root = build_huffman_tree(nodes)
code = {}
build_huffman_code(root, code=code)
encoded_text = encode_huffman(code, "ABCD")
decoded_text = decode_huffman(root, code, encoded_text)
print(code)
print(encoded_text)
print(decoded_text)
```
上述代码中,我们首先定义了一个 Node 类,表示哈夫曼树的结点。然后依次实现了构建哈夫曼树、构建哈夫曼编码、哈夫曼编码和哈夫曼译码等函数。最后,我们使用一组简单的测试数据进行了测试。
阅读全文