-
Notifications
You must be signed in to change notification settings - Fork 16
Expand file tree
/
Copy pathhuffman.c
More file actions
170 lines (139 loc) · 4.26 KB
/
huffman.c
File metadata and controls
170 lines (139 loc) · 4.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
/**
* 霍夫曼编码实现 - C语言
* 基于最小堆构建霍夫曼树,生成最优前缀编码
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
// 霍夫曼树节点
typedef struct HuffmanNode {
char character;
int frequency;
struct HuffmanNode *left, *right;
} HuffmanNode;
// 最小堆结构
typedef struct {
int size;
int capacity;
HuffmanNode** array;
} MinHeap;
// 创建霍夫曼节点
HuffmanNode* createNode(char character, int frequency) {
HuffmanNode* node = (HuffmanNode*)malloc(sizeof(HuffmanNode));
node->character = character;
node->frequency = frequency;
node->left = node->right = NULL;
return node;
}
// 创建最小堆
MinHeap* createMinHeap(int capacity) {
MinHeap* heap = (MinHeap*)malloc(sizeof(MinHeap));
heap->size = 0;
heap->capacity = capacity;
heap->array = (HuffmanNode**)malloc(capacity * sizeof(HuffmanNode*));
return heap;
}
void swapNodes(HuffmanNode** a, HuffmanNode** b) {
HuffmanNode* temp = *a;
*a = *b;
*b = temp;
}
// 堆化:维护最小堆性质
void minHeapify(MinHeap* heap, int idx) {
int smallest = idx;
int left = 2 * idx + 1; // 左子节点
int right = 2 * idx + 2; // 右子节点
if (left < heap->size &&
heap->array[left]->frequency < heap->array[smallest]->frequency)
smallest = left;
if (right < heap->size &&
heap->array[right]->frequency < heap->array[smallest]->frequency)
smallest = right;
if (smallest != idx) {
swapNodes(&heap->array[smallest], &heap->array[idx]);
minHeapify(heap, smallest);
}
}
// 提取最小频率节点
HuffmanNode* extractMin(MinHeap* heap) {
HuffmanNode* temp = heap->array[0];
heap->array[0] = heap->array[heap->size - 1];
--heap->size;
minHeapify(heap, 0);
return temp;
}
void insertMinHeap(MinHeap* heap, HuffmanNode* node) {
++heap->size;
int i = heap->size - 1;
while (i && node->frequency < heap->array[(i - 1) / 2]->frequency) {
heap->array[i] = heap->array[(i - 1) / 2];
i = (i - 1) / 2;
}
heap->array[i] = node;
}
void buildMinHeap(MinHeap* heap) {
int n = heap->size - 1;
for (int i = (n - 1) / 2; i >= 0; --i)
minHeapify(heap, i);
}
// 打印霍夫曼编码(递归遍历树)
void printCodes(HuffmanNode* root, char* arr, int top) {
if (root->left) {
arr[top] = '0'; // 左分支为0
printCodes(root->left, arr, top + 1);
}
if (root->right) {
arr[top] = '1'; // 右分支为1
printCodes(root->right, arr, top + 1);
}
// 叶子节点:输出字符及其编码
if (!root->left && !root->right) {
printf("%c: ", root->character);
for (int i = 0; i < top; ++i)
printf("%c", arr[i]);
printf("\n");
}
}
// 构建霍夫曼树并生成编码
void HuffmanCodes(char* data, int* freq, int size) {
MinHeap* heap = createMinHeap(size);
// 初始化:所有字符作为独立节点入堆
for (int i = 0; i < size; ++i)
heap->array[i] = createNode(data[i], freq[i]);
heap->size = size;
buildMinHeap(heap);
// 循环合并最小频率节点,直到只剩一个根节点
while (heap->size > 1) {
HuffmanNode* left = extractMin(heap);
HuffmanNode* right = extractMin(heap);
// 创建内部节点,'$'标记非叶子节点
HuffmanNode* parent = createNode('$', left->frequency + right->frequency);
parent->left = left;
parent->right = right;
insertMinHeap(heap, parent);
}
char arr[100];
printCodes(heap->array[0], arr, 0);
}
int main() {
char* data = "hello world";
int freq[256] = {0};
// 统计频率
for (int i = 0; data[i] != '\0'; ++i)
freq[(unsigned char)data[i]]++;
// 获取唯一字符
char uniqueChars[256];
int uniqueFreq[256];
int uniqueCount = 0;
for (int i = 0; i < 256; ++i) {
if (freq[i] > 0) {
uniqueChars[uniqueCount] = (char)i;
uniqueFreq[uniqueCount] = freq[i];
uniqueCount++;
}
}
printf("Huffman编码:\n");
HuffmanCodes(uniqueChars, uniqueFreq, uniqueCount);
return 0;
}