Обновить sk1/compressor.c
This commit is contained in:
		
							parent
							
								
									5ba38bda7b
								
							
						
					
					
						commit
						4f7f2b98c9
					
				| @ -4,76 +4,46 @@ | |||||||
| 
 | 
 | ||||||
| #define MAX_TREE_HT 256 | #define MAX_TREE_HT 256 | ||||||
| 
 | 
 | ||||||
| // Узел дерева Хаффмана
 | // A Huffman tree node
 | ||||||
| struct MinHeapNode { | struct MinHeapNode { | ||||||
|     unsigned char data; |     unsigned char data; | ||||||
|     unsigned freq; |     unsigned freq; | ||||||
|     struct MinHeapNode *left, *right; |     struct MinHeapNode *left, *right; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| // Минкуча
 | // A MinHeap
 | ||||||
| struct MinHeap { | struct MinHeap { | ||||||
|     unsigned size; |     unsigned size; | ||||||
|     unsigned capacity; |     unsigned capacity; | ||||||
|     struct MinHeapNode** array; |     struct MinHeapNode** array; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| // Функция для создания нового узла
 | // Function to create a new node
 | ||||||
| struct MinHeapNode* createNode(unsigned char data, unsigned freq) { | struct MinHeapNode* createNode(unsigned char data, unsigned freq) { | ||||||
|     struct MinHeapNode* temp = (struct MinHeapNode*)malloc(sizeof(struct MinHeapNode)); |     struct MinHeapNode* temp = (struct MinHeapNode*)malloc(sizeof(struct MinHeapNode)); | ||||||
|     if (!temp) { |  | ||||||
|         perror("Ошибка выделения памяти для узла дерева"); |  | ||||||
|         exit(EXIT_FAILURE); |  | ||||||
|     } |  | ||||||
|     temp->data = data; |     temp->data = data; | ||||||
|     temp->freq = freq; |     temp->freq = freq; | ||||||
|     temp->left = temp->right = NULL; |     temp->left = temp->right = NULL; | ||||||
|     return temp; |     return temp; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Функция для создания Минкучи
 | // Function to create a MinHeap
 | ||||||
| struct MinHeap* createMinHeap(unsigned capacity) { | struct MinHeap* createMinHeap(unsigned capacity) { | ||||||
|     struct MinHeap* minHeap = (struct MinHeap*)malloc(sizeof(struct MinHeap)); |     struct MinHeap* minHeap = (struct MinHeap*)malloc(sizeof(struct MinHeap)); | ||||||
|     if (!minHeap) { |  | ||||||
|         perror("Ошибка выделения памяти для Минкучи"); |  | ||||||
|         exit(EXIT_FAILURE); |  | ||||||
|     } |  | ||||||
|     minHeap->size = 0; |     minHeap->size = 0; | ||||||
|     minHeap->capacity = capacity; |     minHeap->capacity = capacity; | ||||||
|     minHeap->array = (struct MinHeapNode**)malloc(minHeap->capacity * sizeof(struct MinHeapNode*)); |     minHeap->array = (struct MinHeapNode**)malloc(minHeap->capacity * sizeof(struct MinHeapNode*)); | ||||||
|     if (!minHeap->array) { |  | ||||||
|         perror("Ошибка выделения памяти для массива Минкучи"); |  | ||||||
|         free(minHeap); |  | ||||||
|         exit(EXIT_FAILURE); |  | ||||||
|     } |  | ||||||
|     return minHeap; |     return minHeap; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Функция для освобождения памяти дерева
 | // Swap function
 | ||||||
| void freeHuffmanTree(struct MinHeapNode* root) { |  | ||||||
|     if (!root) return; |  | ||||||
|     freeHuffmanTree(root->left); |  | ||||||
|     freeHuffmanTree(root->right); |  | ||||||
|     free(root); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Освобождение памяти массива кодов
 |  | ||||||
| void freeCodes(char** codes) { |  | ||||||
|     for (int i = 0; i < 256; i++) { |  | ||||||
|         if (codes[i]) { |  | ||||||
|             free(codes[i]); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Swap
 |  | ||||||
| void swapMinHeapNode(struct MinHeapNode** a, struct MinHeapNode** b) { | void swapMinHeapNode(struct MinHeapNode** a, struct MinHeapNode** b) { | ||||||
|     struct MinHeapNode* t = *a; |     struct MinHeapNode* t = *a; | ||||||
|     *a = *b; |     *a = *b; | ||||||
|     *b = t; |     *b = t; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // MinHeapify
 | // MinHeapify function
 | ||||||
| void minHeapify(struct MinHeap* minHeap, int idx) { | void minHeapify(struct MinHeap* minHeap, int idx) { | ||||||
|     int smallest = idx; |     int smallest = idx; | ||||||
|     int left = 2 * idx + 1; |     int left = 2 * idx + 1; | ||||||
| @ -91,7 +61,7 @@ void minHeapify(struct MinHeap* minHeap, int idx) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Извлечение минимального узла
 | // Extract minimum value node from heap
 | ||||||
| struct MinHeapNode* extractMin(struct MinHeap* minHeap) { | struct MinHeapNode* extractMin(struct MinHeap* minHeap) { | ||||||
|     struct MinHeapNode* temp = minHeap->array[0]; |     struct MinHeapNode* temp = minHeap->array[0]; | ||||||
|     minHeap->array[0] = minHeap->array[minHeap->size - 1]; |     minHeap->array[0] = minHeap->array[minHeap->size - 1]; | ||||||
| @ -100,11 +70,10 @@ struct MinHeapNode* extractMin(struct MinHeap* minHeap) { | |||||||
|     return temp; |     return temp; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Вставка нового узла в Минкучу
 | // Insert a new node to MinHeap
 | ||||||
| void insertMinHeap(struct MinHeap* minHeap, struct MinHeapNode* minHeapNode) { | void insertMinHeap(struct MinHeap* minHeap, struct MinHeapNode* minHeapNode) { | ||||||
|     ++minHeap->size; |     ++minHeap->size; | ||||||
|     int i = minHeap->size - 1; |     int i = minHeap->size - 1; | ||||||
| 
 |  | ||||||
|     while (i && minHeapNode->freq < minHeap->array[(i - 1) / 2]->freq) { |     while (i && minHeapNode->freq < minHeap->array[(i - 1) / 2]->freq) { | ||||||
|         minHeap->array[i] = minHeap->array[(i - 1) / 2]; |         minHeap->array[i] = minHeap->array[(i - 1) / 2]; | ||||||
|         i = (i - 1) / 2; |         i = (i - 1) / 2; | ||||||
| @ -112,39 +81,47 @@ void insertMinHeap(struct MinHeap* minHeap, struct MinHeapNode* minHeapNode) { | |||||||
|     minHeap->array[i] = minHeapNode; |     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* createAndBuildMinHeap(unsigned char data[], int freq[], int size) { | ||||||
|     struct MinHeap* minHeap = createMinHeap(size); |     struct MinHeap* minHeap = createMinHeap(size); | ||||||
|     for (int i = 0; i < size; ++i) |     for (int i = 0; i < size; ++i) | ||||||
|         minHeap->array[i] = createNode(data[i], freq[i]); |         minHeap->array[i] = createNode(data[i], freq[i]); | ||||||
|     minHeap->size = size; |     minHeap->size = size; | ||||||
|     for (int i = (minHeap->size - 2) / 2; i >= 0; --i) |     buildMinHeap(minHeap); | ||||||
|         minHeapify(minHeap, i); |  | ||||||
|     return minHeap; |     return minHeap; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Построение дерева Хаффмана
 | // Build Huffman Tree
 | ||||||
| struct MinHeapNode* buildHuffmanTree(unsigned char data[], int freq[], int size) { | struct MinHeapNode* buildHuffmanTree(unsigned char data[], int freq[], int size) { | ||||||
|     struct MinHeapNode *left, *right, *top; |     struct MinHeapNode *left, *right, *top; | ||||||
|     struct MinHeap* minHeap = createAndBuildMinHeap(data, freq, size); |     struct MinHeap* minHeap = createAndBuildMinHeap(data, freq, size); | ||||||
| 
 | 
 | ||||||
|     while (minHeap->size > 1) { |     while (!isSizeOne(minHeap)) { | ||||||
|         left = extractMin(minHeap); |         left = extractMin(minHeap); | ||||||
|         right = extractMin(minHeap); |         right = extractMin(minHeap); | ||||||
| 
 | 
 | ||||||
|         top = createNode('$', left->freq + right->freq); |         top = createNode('$', left->freq + right->freq); | ||||||
|         top->left = left; |         top->left = left; | ||||||
|         top->right = right; |         top->right = right; | ||||||
|  | 
 | ||||||
|         insertMinHeap(minHeap, top); |         insertMinHeap(minHeap, top); | ||||||
|     } |     } | ||||||
| 
 |     return extractMin(minHeap); | ||||||
|     struct MinHeapNode* root = extractMin(minHeap); |  | ||||||
|     free(minHeap->array); |  | ||||||
|     free(minHeap); |  | ||||||
|     return root; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Сохранение кодов
 | // Print Huffman Codes to a map
 | ||||||
| void storeCodes(struct MinHeapNode* root, char** codes, char* currentCode, int top) { | void storeCodes(struct MinHeapNode* root, char** codes, char* currentCode, int top) { | ||||||
|     if (root->left) { |     if (root->left) { | ||||||
|         currentCode[top] = '0'; |         currentCode[top] = '0'; | ||||||
| @ -157,13 +134,8 @@ void storeCodes(struct MinHeapNode* root, char** codes, char* currentCode, int t | |||||||
|     if (!(root->left) && !(root->right)) { |     if (!(root->left) && !(root->right)) { | ||||||
|         currentCode[top] = '\0'; |         currentCode[top] = '\0'; | ||||||
|         codes[root->data] = strdup(currentCode); |         codes[root->data] = strdup(currentCode); | ||||||
|         if (!codes[root->data]) { |  | ||||||
|             perror("Ошибка выделения памяти для кодов"); |  | ||||||
|             exit(EXIT_FAILURE); |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 | 
 | ||||||
| // Compress the input file using Huffman Coding
 | // Compress the input file using Huffman Coding
 | ||||||
| int compressFile(const char* input_file_name, const char* output_file_name) { | int compressFile(const char* input_file_name, const char* output_file_name) { | ||||||
| @ -225,7 +197,7 @@ int compressFile(const char* input_file_name, const char* output_file_name) { | |||||||
|         byte <<= (8 - bitCount); |         byte <<= (8 - bitCount); | ||||||
|         fwrite(&byte, sizeof(unsigned char), 1, outputFile); |         fwrite(&byte, sizeof(unsigned char), 1, outputFile); | ||||||
|     } |     } | ||||||
|     freeHuffmanTree(root); | 
 | ||||||
|     fclose(inputFile); |     fclose(inputFile); | ||||||
|     fclose(outputFile); |     fclose(outputFile); | ||||||
|     return 0; |     return 0; | ||||||
| @ -278,7 +250,7 @@ int decompressFile(const char* input_file_name, const char* output_file_name) { | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     freeHuffmanTree(root); | 
 | ||||||
|     fclose(inputFile); |     fclose(inputFile); | ||||||
|     fclose(outputFile); |     fclose(outputFile); | ||||||
|     return 0; |     return 0; | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user