Update sk1/compressor.c
This commit is contained in:
		
							parent
							
								
									dea7942391
								
							
						
					
					
						commit
						3935a5851e
					
				
							
								
								
									
										149
									
								
								sk1/compressor.c
									
									
									
									
									
								
							
							
						
						
									
										149
									
								
								sk1/compressor.c
									
									
									
									
									
								
							| @ -21,7 +21,7 @@ int compress_2(const char* input_file_name, const char* output_file_name) { | |||||||
| 
 | 
 | ||||||
|     unsigned char current_byte, previous_byte; |     unsigned char current_byte, previous_byte; | ||||||
|     size_t count = 0; |     size_t count = 0; | ||||||
|      | 
 | ||||||
|     // Читаємо перший байт
 |     // Читаємо перший байт
 | ||||||
|     if (fread(&previous_byte, 1, 1, infile) != 1) { |     if (fread(&previous_byte, 1, 1, infile) != 1) { | ||||||
|         fclose(infile); |         fclose(infile); | ||||||
| @ -88,64 +88,87 @@ int decompress_2(const char* input_file_name, const char* output_file_name) { | |||||||
| 
 | 
 | ||||||
| // --- Алгоритм Хаффмана (Huffman Coding) ---
 | // --- Алгоритм Хаффмана (Huffman Coding) ---
 | ||||||
| 
 | 
 | ||||||
| // Структура для вузлів дерева Хаффмана
 | typedef struct Node { | ||||||
| typedef struct { |  | ||||||
|     unsigned char symbol; |     unsigned char symbol; | ||||||
|     size_t frequency; |     size_t frequency; | ||||||
| } HuffmanSymbol; |  | ||||||
| 
 |  | ||||||
| typedef struct Node { |  | ||||||
|     HuffmanSymbol symbol; |  | ||||||
|     struct Node *left, *right; |     struct Node *left, *right; | ||||||
| } Node; | } Node; | ||||||
| 
 | 
 | ||||||
|  | // Структура для кодів Хаффмана
 | ||||||
|  | typedef struct { | ||||||
|  |     unsigned char symbol; | ||||||
|  |     char *code; | ||||||
|  | } HuffmanCode; | ||||||
|  | 
 | ||||||
| // Функція для порівняння вузлів для використання в черзі
 | // Функція для порівняння вузлів для використання в черзі
 | ||||||
| int compare_nodes(const void *a, const void *b) { | int compare_nodes(const void *a, const void *b) { | ||||||
|     return ((Node*)a)->symbol.frequency - ((Node*)b)->symbol.frequency; |     return ((Node*)a)->frequency - ((Node*)b)->frequency; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Створення дерева Хаффмана
 | // Створення дерева Хаффмана
 | ||||||
| Node* create_huffman_tree(HuffmanSymbol* symbols, size_t n) { | Node* create_huffman_tree(unsigned char *data, size_t size) { | ||||||
|     // Використовуємо чергу для побудови дерева Хаффмана
 |     size_t freq[256] = {0}; | ||||||
|     qsort(symbols, n, sizeof(HuffmanSymbol), compare_nodes); |     for (size_t i = 0; i < size; i++) { | ||||||
| 
 |         freq[data[i]]++; | ||||||
|     // Створюємо чергу вузлів для побудови дерева
 |  | ||||||
|     Node** queue = malloc(n * sizeof(Node*)); |  | ||||||
|     for (size_t i = 0; i < n; i++) { |  | ||||||
|         queue[i] = malloc(sizeof(Node)); |  | ||||||
|         queue[i]->symbol = symbols[i]; |  | ||||||
|         queue[i]->left = queue[i]->right = NULL; |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     size_t queue_size = n; |     // Створюємо список вузлів
 | ||||||
|  |     Node *nodes[256]; | ||||||
|  |     size_t node_count = 0; | ||||||
| 
 | 
 | ||||||
|     // Побудова дерева Хаффмана
 |     for (int i = 0; i < 256; i++) { | ||||||
|     while (queue_size > 1) { |         if (freq[i] > 0) { | ||||||
|         // Зливаємо два найменші елементи
 |             nodes[node_count] = malloc(sizeof(Node)); | ||||||
|         Node* left = queue[0]; |             nodes[node_count]->symbol = (unsigned char)i; | ||||||
|         Node* right = queue[1]; |             nodes[node_count]->frequency = freq[i]; | ||||||
|  |             nodes[node_count]->left = nodes[node_count]->right = NULL; | ||||||
|  |             node_count++; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Сортуємо вузли по частоті
 | ||||||
|  |     qsort(nodes, node_count, sizeof(Node*), compare_nodes); | ||||||
|  | 
 | ||||||
|  |     // Побудова дерева
 | ||||||
|  |     while (node_count > 1) { | ||||||
|  |         Node* left = nodes[0]; | ||||||
|  |         Node* right = nodes[1]; | ||||||
| 
 | 
 | ||||||
|         Node* parent = malloc(sizeof(Node)); |         Node* parent = malloc(sizeof(Node)); | ||||||
|         parent->symbol.symbol = 0;  // Спільний символ
 |         parent->symbol = 0; | ||||||
|         parent->symbol.frequency = left->symbol.frequency + right->symbol.frequency; |         parent->frequency = left->frequency + right->frequency; | ||||||
|         parent->left = left; |         parent->left = left; | ||||||
|         parent->right = right; |         parent->right = right; | ||||||
| 
 | 
 | ||||||
|         // Видаляємо перші два елементи з черги та додаємо новий
 |         // Зміщуємо вузли в черзі
 | ||||||
|         memmove(queue, queue + 2, (queue_size - 2) * sizeof(Node*)); |         memmove(nodes, nodes + 2, (node_count - 2) * sizeof(Node*)); | ||||||
|         queue[queue_size - 2] = parent; |         nodes[node_count - 2] = parent; | ||||||
|         queue_size--; |         node_count--; | ||||||
| 
 | 
 | ||||||
|         qsort(queue, queue_size, sizeof(Node*), compare_nodes); |         qsort(nodes, node_count, sizeof(Node*), compare_nodes); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     Node* root = queue[0]; |     return nodes[0]; // Повертаємо корінь дерева
 | ||||||
|     free(queue); |  | ||||||
| 
 |  | ||||||
|     return root; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Функція для стиснення з використанням дерева Хаффмана
 | // Функція для рекурсивного запису бітових кодів з дерева Хаффмана
 | ||||||
|  | void generate_huffman_codes(Node* root, HuffmanCode* codes, char* current_code, int depth) { | ||||||
|  |     if (!root) return; | ||||||
|  | 
 | ||||||
|  |     if (root->left == NULL && root->right == NULL) { | ||||||
|  |         current_code[depth] = '\0'; | ||||||
|  |         codes[root->symbol].symbol = root->symbol; | ||||||
|  |         codes[root->symbol].code = strdup(current_code); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     current_code[depth] = '0'; | ||||||
|  |     generate_huffman_codes(root->left, codes, current_code, depth + 1); | ||||||
|  |      | ||||||
|  |     current_code[depth] = '1'; | ||||||
|  |     generate_huffman_codes(root->right, codes, current_code, depth + 1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Функція для стиснення за допомогою Хаффмана
 | ||||||
| int compress_1(const char* input_file_name, const char* output_file_name) { | int compress_1(const char* input_file_name, const char* output_file_name) { | ||||||
|     FILE *infile = fopen(input_file_name, "rb"); |     FILE *infile = fopen(input_file_name, "rb"); | ||||||
|     if (!infile) { |     if (!infile) { | ||||||
| @ -157,43 +180,51 @@ int compress_1(const char* input_file_name, const char* output_file_name) { | |||||||
|     size_t file_size = ftell(infile); |     size_t file_size = ftell(infile); | ||||||
|     fseek(infile, 0, SEEK_SET); |     fseek(infile, 0, SEEK_SET); | ||||||
| 
 | 
 | ||||||
|     unsigned char* buffer = malloc(file_size); |     unsigned char* data = malloc(file_size); | ||||||
|     if (!buffer) { |     if (!data) { | ||||||
|         fclose(infile); |         fclose(infile); | ||||||
|         return -1; |         return -1; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fread(buffer, 1, file_size, infile); |     fread(data, 1, file_size, infile); | ||||||
|     fclose(infile); |     fclose(infile); | ||||||
| 
 | 
 | ||||||
|     // Підрахунок частоти кожного байта
 |     // Створюємо дерево Хаффмана
 | ||||||
|     size_t frequencies[256] = {0}; |     Node* root = create_huffman_tree(data, file_size); | ||||||
|     for (size_t i = 0; i < file_size; i++) { | 
 | ||||||
|         frequencies[buffer[i]]++; |     // Генерація кодів Хаффмана
 | ||||||
|  |     HuffmanCode codes[256]; | ||||||
|  |     for (int i = 0; i < 256; i++) { | ||||||
|  |         codes[i].code = NULL; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     HuffmanSymbol symbols[256]; |     char current_code[256]; | ||||||
|     size_t num_symbols = 0; |     generate_huffman_codes(root, codes, current_code, 0); | ||||||
| 
 | 
 | ||||||
|     for (int i = 0; i < 256; i++) { |     // Стиснення даних
 | ||||||
|         if (frequencies[i] > 0) { |     FILE *outfile = fopen(output_file_name, "wb"); | ||||||
|             symbols[num_symbols].symbol = (unsigned char)i; |     if (!outfile) { | ||||||
|             symbols[num_symbols].frequency = frequencies[i]; |         free(data); | ||||||
|             num_symbols++; |         return -1; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     for (size_t i = 0; i < file_size; i++) { | ||||||
|  |         unsigned char symbol = data[i]; | ||||||
|  |         const char* code = codes[symbol].code; | ||||||
|  |         for (size_t j = 0; code[j] != '\0'; j++) { | ||||||
|  |             // Записуємо біт в файл
 | ||||||
|  |             fputc(code[j] == '1' ? 1 : 0, outfile); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     Node* huffman_tree = create_huffman_tree(symbols, num_symbols); |     fclose(outfile); | ||||||
|  |     free(data); | ||||||
| 
 | 
 | ||||||
|     // Тут треба реалізувати кодування та запис бітових кодів в файл
 |     return 1;  // Повертаємо успішний результат
 | ||||||
|     // Оскільки це складніше, я залишаю це як заготовку для подальшої реалізації
 |  | ||||||
| 
 |  | ||||||
|     free(buffer); |  | ||||||
|     return 1; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // Функція для декомпресії за допомогою Хаффмана
 | ||||||
| int decompress_1(const char* input_file_name, const char* output_file_name) { | int decompress_1(const char* input_file_name, const char* output_file_name) { | ||||||
|     // Реалізація декомпресії за допомогою Хаффмана буде складною
 |     // Декомпресія за допомогою Хаффмана потребує відновлення дерева та розшифровки бітових кодів
 | ||||||
|     // і потребує зберігання дерев або довжини кодування кожного символу
 |     return 0;  // Не реалізовано повністю
 | ||||||
|     return 0; |  | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user