Обновить 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); | ||||
| int decompress_1(const char* input_file_name, const char* output_file_name); | ||||
| #include <stdio.h> | ||||
| #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 decompress_2(const char* input_file_name, const char* output_file_name); | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user