Обновить 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