Обновить sk1/compressor.c
This commit is contained in:
parent
9d92249280
commit
e463e2d1b0
275
sk1/compressor.c
275
sk1/compressor.c
@ -1,4 +1,275 @@
|
|||||||
int compress_1(const char* input_file_name, const char* output_file_name);
|
#include <stdio.h>
|
||||||
int decompress_1(const char* input_file_name, const char* output_file_name);
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define MAX_TREE_HT 256
|
||||||
|
|
||||||
|
// A Huffman tree node
|
||||||
|
struct MinHeapNode {
|
||||||
|
unsigned char data;
|
||||||
|
unsigned freq;
|
||||||
|
struct MinHeapNode *left, *right;
|
||||||
|
};
|
||||||
|
|
||||||
|
// A MinHeap
|
||||||
|
struct MinHeap {
|
||||||
|
unsigned size;
|
||||||
|
unsigned capacity;
|
||||||
|
struct MinHeapNode** array;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Function to create a new node
|
||||||
|
struct MinHeapNode* createNode(unsigned char data, unsigned freq) {
|
||||||
|
struct MinHeapNode* temp = (struct MinHeapNode*)malloc(sizeof(struct MinHeapNode));
|
||||||
|
temp->data = data;
|
||||||
|
temp->freq = freq;
|
||||||
|
temp->left = temp->right = NULL;
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to create a MinHeap
|
||||||
|
struct MinHeap* createMinHeap(unsigned capacity) {
|
||||||
|
struct MinHeap* minHeap = (struct MinHeap*)malloc(sizeof(struct MinHeap));
|
||||||
|
minHeap->size = 0;
|
||||||
|
minHeap->capacity = capacity;
|
||||||
|
minHeap->array = (struct MinHeapNode**)malloc(minHeap->capacity * sizeof(struct MinHeapNode*));
|
||||||
|
return minHeap;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Swap function
|
||||||
|
void swapMinHeapNode(struct MinHeapNode** a, struct MinHeapNode** b) {
|
||||||
|
struct MinHeapNode* t = *a;
|
||||||
|
*a = *b;
|
||||||
|
*b = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MinHeapify function
|
||||||
|
void minHeapify(struct MinHeap* minHeap, int idx) {
|
||||||
|
int smallest = idx;
|
||||||
|
int left = 2 * idx + 1;
|
||||||
|
int right = 2 * idx + 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 != idx) {
|
||||||
|
swapMinHeapNode(&minHeap->array[smallest], &minHeap->array[idx]);
|
||||||
|
minHeapify(minHeap, smallest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract minimum value node from heap
|
||||||
|
struct MinHeapNode* extractMin(struct MinHeap* minHeap) {
|
||||||
|
struct MinHeapNode* temp = minHeap->array[0];
|
||||||
|
minHeap->array[0] = minHeap->array[minHeap->size - 1];
|
||||||
|
--minHeap->size;
|
||||||
|
minHeapify(minHeap, 0);
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert a new node to MinHeap
|
||||||
|
void insertMinHeap(struct MinHeap* minHeap, struct 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build the MinHeap
|
||||||
|
void buildMinHeap(struct MinHeap* minHeap) {
|
||||||
|
int n = minHeap->size - 1;
|
||||||
|
for (int i = (n - 1) / 2; i >= 0; --i)
|
||||||
|
minHeapify(minHeap, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if size is 1
|
||||||
|
int isSizeOne(struct MinHeap* minHeap) {
|
||||||
|
return (minHeap->size == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create and build a MinHeap
|
||||||
|
struct MinHeap* createAndBuildMinHeap(unsigned char data[], int freq[], int size) {
|
||||||
|
struct MinHeap* minHeap = createMinHeap(size);
|
||||||
|
for (int i = 0; i < size; ++i)
|
||||||
|
minHeap->array[i] = createNode(data[i], freq[i]);
|
||||||
|
minHeap->size = size;
|
||||||
|
buildMinHeap(minHeap);
|
||||||
|
return minHeap;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build Huffman Tree
|
||||||
|
struct MinHeapNode* buildHuffmanTree(unsigned char data[], int freq[], int size) {
|
||||||
|
struct MinHeapNode *left, *right, *top;
|
||||||
|
struct MinHeap* minHeap = createAndBuildMinHeap(data, freq, size);
|
||||||
|
|
||||||
|
while (!isSizeOne(minHeap)) {
|
||||||
|
left = extractMin(minHeap);
|
||||||
|
right = extractMin(minHeap);
|
||||||
|
|
||||||
|
top = createNode('$', left->freq + right->freq);
|
||||||
|
top->left = left;
|
||||||
|
top->right = right;
|
||||||
|
|
||||||
|
insertMinHeap(minHeap, top);
|
||||||
|
}
|
||||||
|
return extractMin(minHeap);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print Huffman Codes to a map
|
||||||
|
void storeCodes(struct MinHeapNode* root, char** codes, char* currentCode, int top) {
|
||||||
|
if (root->left) {
|
||||||
|
currentCode[top] = '0';
|
||||||
|
storeCodes(root->left, codes, currentCode, top + 1);
|
||||||
|
}
|
||||||
|
if (root->right) {
|
||||||
|
currentCode[top] = '1';
|
||||||
|
storeCodes(root->right, codes, currentCode, top + 1);
|
||||||
|
}
|
||||||
|
if (!(root->left) && !(root->right)) {
|
||||||
|
currentCode[top] = '\0';
|
||||||
|
codes[root->data] = strdup(currentCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Compress the input file using Huffman Coding
|
||||||
|
int compressFile(const char* input_file_name, const char* output_file_name) {
|
||||||
|
FILE* inputFile = fopen(input_file_name, "rb");
|
||||||
|
if (!inputFile) {
|
||||||
|
perror("Error opening input file");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int freq[256] = {0};
|
||||||
|
unsigned char buffer;
|
||||||
|
|
||||||
|
// Count frequency of each byte
|
||||||
|
while (fread(&buffer, sizeof(unsigned char), 1, inputFile)) {
|
||||||
|
freq[buffer]++;
|
||||||
|
}
|
||||||
|
rewind(inputFile);
|
||||||
|
|
||||||
|
unsigned char data[256];
|
||||||
|
int frequencies[256], size = 0;
|
||||||
|
for (int i = 0; i < 256; i++) {
|
||||||
|
if (freq[i] > 0) {
|
||||||
|
data[size] = (unsigned char)i;
|
||||||
|
frequencies[size] = freq[i];
|
||||||
|
size++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MinHeapNode* root = buildHuffmanTree(data, frequencies, size);
|
||||||
|
char* codes[256] = {0};
|
||||||
|
char currentCode[MAX_TREE_HT];
|
||||||
|
storeCodes(root, codes, currentCode, 0);
|
||||||
|
|
||||||
|
FILE* outputFile = fopen(output_file_name, "wb");
|
||||||
|
if (!outputFile) {
|
||||||
|
perror("Error opening output file");
|
||||||
|
fclose(inputFile);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write codes to output file
|
||||||
|
fwrite(freq, sizeof(int), 256, outputFile);
|
||||||
|
|
||||||
|
unsigned char byte = 0;
|
||||||
|
int bitCount = 0;
|
||||||
|
while (fread(&buffer, sizeof(unsigned char), 1, inputFile)) {
|
||||||
|
char* code = codes[buffer];
|
||||||
|
for (int i = 0; code[i] != '\0'; i++) {
|
||||||
|
byte = (byte << 1) | (code[i] - '0');
|
||||||
|
bitCount++;
|
||||||
|
if (bitCount == 8) {
|
||||||
|
fwrite(&byte, sizeof(unsigned char), 1, outputFile);
|
||||||
|
byte = 0;
|
||||||
|
bitCount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bitCount > 0) {
|
||||||
|
byte <<= (8 - bitCount);
|
||||||
|
fwrite(&byte, sizeof(unsigned char), 1, outputFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(inputFile);
|
||||||
|
fclose(outputFile);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decompress the file
|
||||||
|
int decompressFile(const char* input_file_name, const char* output_file_name) {
|
||||||
|
FILE* inputFile = fopen(input_file_name, "rb");
|
||||||
|
if (!inputFile) {
|
||||||
|
perror("Error opening input file");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int freq[256];
|
||||||
|
fread(freq, sizeof(int), 256, inputFile);
|
||||||
|
|
||||||
|
unsigned char data[256];
|
||||||
|
int frequencies[256], size = 0;
|
||||||
|
for (int i = 0; i < 256; i++) {
|
||||||
|
if (freq[i] > 0) {
|
||||||
|
data[size] = (unsigned char)i;
|
||||||
|
frequencies[size] = freq[i];
|
||||||
|
size++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MinHeapNode* root = buildHuffmanTree(data, frequencies, size);
|
||||||
|
|
||||||
|
FILE* outputFile = fopen(output_file_name, "wb");
|
||||||
|
if (!outputFile) {
|
||||||
|
perror("Error opening output file");
|
||||||
|
fclose(inputFile);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MinHeapNode* current = root;
|
||||||
|
unsigned char buffer;
|
||||||
|
int bitCount = 0;
|
||||||
|
while (fread(&buffer, sizeof(unsigned char), 1, inputFile)) {
|
||||||
|
for (int i = 7; i >= 0; i--) {
|
||||||
|
int bit = (buffer >> i) & 1;
|
||||||
|
if (bit == 0)
|
||||||
|
current = current->left;
|
||||||
|
else
|
||||||
|
current = current->right;
|
||||||
|
|
||||||
|
if (!(current->left) && !(current->right)) {
|
||||||
|
fwrite(¤t->data, sizeof(unsigned char), 1, outputFile);
|
||||||
|
current = root;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(inputFile);
|
||||||
|
fclose(outputFile);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int compress_1(const char* input_file_name, const char* output_file_name){
|
||||||
|
if(compressFile(input_file_name, output_file_name) == 0){
|
||||||
|
printf("Succsses!");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int decompress_1(const char* input_file_name, const char* output_file_name){
|
||||||
|
if(decompressFile(input_file_name, output_file_name) == 0){
|
||||||
|
printf("Succsses!");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
int compress_2(const char* input_file_name, const char* output_file_name);
|
int compress_2(const char* input_file_name, const char* output_file_name);
|
||||||
int decompress_2(const char* input_file_name, const char* output_file_name);
|
int decompress_2(const char* input_file_name, const char* output_file_name);
|
Loading…
Reference in New Issue
Block a user