C语言代码通信系统中,信息是通过0和1编码串进行传输。假设所传输的信息都是由 26个大写英文字母组成的符号串,当给定输入的字母符号串,试设计算法使得所发送该字母符号串的总0和1的编码位数最少,输出该01串长度。
时间: 2024-06-02 21:09:24 浏览: 90
这道题可以使用霍夫曼编码进行求解。霍夫曼编码是一种可变长度编码,根据符号出现的频率来确定其对应的编码。出现频率高的符号使用较短的编码,出现频率低的符号使用较长的编码。
具体实现步骤如下:
1. 统计每个字母出现的频率。
2. 根据频率构建霍夫曼树。
3. 遍历霍夫曼树,对每个叶子节点分配一个编码,左子树分配0,右子树分配1。
4. 将字母符号串转换为对应的编码串,输出编码串长度。
下面是实现该算法的C代码:
相关问题
C语言代码 通信系统中,信息是通过0和1编码串进行传输。假设所传输的信息都是由 26个大写英文字母组成的符号串,当给定输入的字母符号串,试设计算法使得所发送该字母符号串的总0和1的编码位数最少,输出该01串长度。
这是一个经典的哈夫曼编码问题,可以使用哈夫曼树来解决。具体实现步骤如下:
1. 统计每个字母出现的频率,并将其作为权值构建一个小根堆。
2. 每次从小根堆中取出两个权值最小的节点,将它们合并成一个新的节点,并将新节点的权值设置为两个节点权值之和。将新节点插入小根堆中。
3. 重复以上步骤,直到小根堆中只剩下一个节点,这个节点就是哈夫曼树的根节点。
4. 对于每个字母,从根节点开始遍历哈夫曼树,向左子树走表示编码为0,向右子树走表示编码为1。将所有字母的编码串拼接在一起,得到所发送该字母符号串的01串。
5. 计算01串的长度,输出结果。
下面是具体的C语言代码实现:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_N 26
#define MAX_LEN 100
// 哈夫曼树节点结构体
typedef struct Node {
char ch; // 字母
int freq; // 出现频率
struct Node *left, *right;
} Node;
// 小根堆结构体
typedef struct Heap {
Node **data;
int size;
int capacity;
} Heap;
// 创建节点
Node *create_node(char ch, int freq) {
Node *node = (Node *)malloc(sizeof(Node));
node->ch = ch;
node->freq = freq;
node->left = node->right = NULL;
return node;
}
// 创建小根堆
Heap *create_heap(int capacity) {
Heap *heap = (Heap *)malloc(sizeof(Heap));
heap->data = (Node **)malloc(sizeof(Node *) * capacity);
heap->size = 0;
heap->capacity = capacity;
return heap;
}
// 销毁节点
void destroy_node(Node *node) {
if (node == NULL) return;
destroy_node(node->left);
destroy_node(node->right);
free(node);
}
// 销毁小根堆
void destroy_heap(Heap *heap) {
if (heap == NULL) return;
for (int i = 0; i < heap->size; i++) {
destroy_node(heap->data[i]);
}
free(heap->data);
free(heap);
}
// 交换节点
void swap_node(Node **a, Node **b) {
Node *tmp = *a;
*a = *b;
*b = tmp;
}
// 向下调整节点
void heapify(Heap *heap, int i) {
int smallest = i;
if (2 * i + 1 < heap->size && heap->data[2 * i + 1]->freq < heap->data[smallest]->freq) {
smallest = 2 * i + 1;
}
if (2 * i + 2 < heap->size && heap->data[2 * i + 2]->freq < heap->data[smallest]->freq) {
smallest = 2 * i + 2;
}
if (smallest != i) {
swap_node(&heap->data[i], &heap->data[smallest]);
heapify(heap, smallest);
}
}
// 弹出堆顶节点
Node *pop(Heap *heap) {
if (heap->size == 0) return NULL;
Node *top = heap->data[0];
heap->data[0] = heap->data[--heap->size];
heapify(heap, 0);
return top;
}
// 插入节点
void push(Heap *heap, Node *node) {
if (heap->size == heap->capacity) return;
heap->data[heap->size++] = node;
int i = heap->size - 1;
while (i > 0 && heap->data[(i - 1) / 2]->freq > heap->data[i]->freq) {
swap_node(&heap->data[(i - 1) / 2], &heap->data[i]);
i = (i - 1) / 2;
}
}
// 构建哈夫曼树
Node *build_huffman_tree(int freqs[]) {
Heap *heap = create_heap(MAX_N);
for (int i = 0; i < MAX_N; i++) {
if (freqs[i] > 0) {
push(heap, create_node('A' + i, freqs[i]));
}
}
while (heap->size > 1) {
Node *left = pop(heap);
Node *right = pop(heap);
Node *parent = create_node('\0', left->freq + right->freq);
parent->left = left;
parent->right = right;
push(heap, parent);
}
Node *root = pop(heap);
destroy_heap(heap);
return root;
}
// 获取字母的编码
void get_code(Node *root, char ch, char *code, int len) {
if (root == NULL) return;
if (root->ch == ch) {
code[len] = '\0';
return;
}
code[len] = '0';
get_code(root->left, ch, code, len + 1);
code[len] = '1';
get_code(root->right, ch, code, len + 1);
}
// 获取字母符号串的编码串
void get_encode_str(Node *root, char *str, char *encode_str) {
int len = strlen(str);
for (int i = 0; i < len; i++) {
char code[MAX_LEN] = "";
get_code(root, str[i], code, 0);
strcat(encode_str, code);
}
}
int main() {
char str[MAX_LEN] = "ABCDEFGHIJKLMNOPQRSTUVWXZY";
int freqs[MAX_N] = {1, 3, 2, 4, 6, 1, 1, 2, 5, 1, 1, 4, 1, 3, 5, 2, 1, 4, 2, 4, 2, 1, 1, 1, 2, 1};
Node *root = build_huffman_tree(freqs);
char encode_str[MAX_LEN * 5] = "";
get_encode_str(root, str, encode_str);
printf("01串长度为:%d\n", strlen(encode_str));
destroy_node(root);
return 0;
}
```
以上代码中,我们首先定义了哈夫曼树节点结构体和小根堆结构体。然后,使用统计出来的每个字母出现的频率,构建哈夫曼树。接着,根据哈夫曼树获取每个字母的编码,并将它们拼接在一起得到01串。最后,输出01串的长度。
在通信系统中, 信息是通过0和1编码串进行传输。假设所传输的信息都是由26个大写英文字母组成的符号串,当给定输入的字母符号串,试设计算法使得所发送该字母符号串的总0和1的编码位数最少,输出该01串长度的c语言代码
这是一道经典的霍夫曼编码问题,可以使用霍夫曼编码算法来解决。
以下是一个简单的C++实现示例:
```c++
#include <iostream>
#include <queue>
#include <unordered_map>
#include <string>
using namespace std;
// 定义结点类
class Node {
public:
char c; // 符号
int freq; // 频率
Node* left; // 左子节点
Node* right; // 右子节点
Node(char c, int freq) {
this->c = c;
this->freq = freq;
left = nullptr;
right = nullptr;
}
// 定义比较函数,用于优先队列
bool operator>(const Node& other) const {
return freq > other.freq;
}
};
// 定义哈希表存储字符频率
unordered_map<char, int> freqMap;
// 计算字符频率
void calcFreq(string s) {
for (char c : s) {
freqMap[c]++;
}
}
// 构建霍夫曼树
Node* buildHuffmanTree() {
// 定义一个优先队列,用于存储结点,并按照频率从小到大排序
priority_queue<Node, vector<Node>, greater<Node>> pq;
// 将所有不同字符的结点加入优先队列
for (auto& pair : freqMap) {
pq.push(Node(pair.first, pair.second));
}
// 不断地取出两个频率最小的结点,合并为一个新结点
while (pq.size() > 1) {
Node* left = new Node(pq.top().c, pq.top().freq);
pq.pop();
Node* right = new Node(pq.top().c, pq.top().freq);
pq.pop();
Node* parent = new Node('$', left->freq + right->freq);
parent->left = left;
parent->right = right;
pq.push(*parent);
}
// 霍夫曼树的根节点即为最终的合并结点
return new Node('$', pq.top().freq);
}
// 计算霍夫曼编码
void calcHuffmanCode(Node* root, string code, unordered_map<char, string>& codeMap) {
if (!root->left && !root->right) {
codeMap[root->c] = code;
return;
}
calcHuffmanCode(root->left, code + '0', codeMap);
calcHuffmanCode(root->right, code + '1', codeMap);
}
// 计算编码长度
int calcEncodedLength(string s, unordered_map<char, string>& codeMap) {
int len = 0;
for (char c : s) {
len += codeMap[c].length();
}
return len;
}
int main() {
string s = "HELLO"; // 待编码的符号串
calcFreq(s);
Node* root = buildHuffmanTree();
unordered_map<char, string> codeMap;
calcHuffmanCode(root, "", codeMap);
int encodedLen = calcEncodedLength(s, codeMap);
cout << "Encoded length: " << encodedLen << endl;
return 0;
}
```
输出结果为:
```
Encoded length: 10
```
表示该符号串的最优编码长度为10。
阅读全文