Update sk1/compressor.c
This commit is contained in:
		
							parent
							
								
									dea7942391
								
							
						
					
					
						commit
						3935a5851e
					
				
							
								
								
									
										149
									
								
								sk1/compressor.c
									
									
									
									
									
								
							
							
						
						
									
										149
									
								
								sk1/compressor.c
									
									
									
									
									
								
							| @ -88,64 +88,87 @@ int decompress_2(const char* input_file_name, const char* output_file_name) { | ||||
| 
 | ||||
| // --- Алгоритм Хаффмана (Huffman Coding) ---
 | ||||
| 
 | ||||
| // Структура для вузлів дерева Хаффмана
 | ||||
| typedef struct { | ||||
| typedef struct Node { | ||||
|     unsigned char symbol; | ||||
|     size_t frequency; | ||||
| } HuffmanSymbol; | ||||
| 
 | ||||
| typedef struct Node { | ||||
|     HuffmanSymbol symbol; | ||||
|     struct Node *left, *right; | ||||
| } Node; | ||||
| 
 | ||||
| // Структура для кодів Хаффмана
 | ||||
| typedef struct { | ||||
|     unsigned char symbol; | ||||
|     char *code; | ||||
| } HuffmanCode; | ||||
| 
 | ||||
| // Функція для порівняння вузлів для використання в черзі
 | ||||
| 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) { | ||||
|     // Використовуємо чергу для побудови дерева Хаффмана
 | ||||
|     qsort(symbols, n, sizeof(HuffmanSymbol), compare_nodes); | ||||
| 
 | ||||
|     // Створюємо чергу вузлів для побудови дерева
 | ||||
|     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; | ||||
| Node* create_huffman_tree(unsigned char *data, size_t size) { | ||||
|     size_t freq[256] = {0}; | ||||
|     for (size_t i = 0; i < size; i++) { | ||||
|         freq[data[i]]++; | ||||
|     } | ||||
| 
 | ||||
|     size_t queue_size = n; | ||||
|     // Створюємо список вузлів
 | ||||
|     Node *nodes[256]; | ||||
|     size_t node_count = 0; | ||||
| 
 | ||||
|     // Побудова дерева Хаффмана
 | ||||
|     while (queue_size > 1) { | ||||
|         // Зливаємо два найменші елементи
 | ||||
|         Node* left = queue[0]; | ||||
|         Node* right = queue[1]; | ||||
|     for (int i = 0; i < 256; i++) { | ||||
|         if (freq[i] > 0) { | ||||
|             nodes[node_count] = malloc(sizeof(Node)); | ||||
|             nodes[node_count]->symbol = (unsigned char)i; | ||||
|             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)); | ||||
|         parent->symbol.symbol = 0;  // Спільний символ
 | ||||
|         parent->symbol.frequency = left->symbol.frequency + right->symbol.frequency; | ||||
|         parent->symbol = 0; | ||||
|         parent->frequency = left->frequency + right->frequency; | ||||
|         parent->left = left; | ||||
|         parent->right = right; | ||||
| 
 | ||||
|         // Видаляємо перші два елементи з черги та додаємо новий
 | ||||
|         memmove(queue, queue + 2, (queue_size - 2) * sizeof(Node*)); | ||||
|         queue[queue_size - 2] = parent; | ||||
|         queue_size--; | ||||
|         // Зміщуємо вузли в черзі
 | ||||
|         memmove(nodes, nodes + 2, (node_count - 2) * sizeof(Node*)); | ||||
|         nodes[node_count - 2] = parent; | ||||
|         node_count--; | ||||
| 
 | ||||
|         qsort(queue, queue_size, sizeof(Node*), compare_nodes); | ||||
|         qsort(nodes, node_count, sizeof(Node*), compare_nodes); | ||||
|     } | ||||
| 
 | ||||
|     Node* root = queue[0]; | ||||
|     free(queue); | ||||
| 
 | ||||
|     return root; | ||||
|     return nodes[0]; // Повертаємо корінь дерева
 | ||||
| } | ||||
| 
 | ||||
| // Функція для стиснення з використанням дерева Хаффмана
 | ||||
| // Функція для рекурсивного запису бітових кодів з дерева Хаффмана
 | ||||
| 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) { | ||||
|     FILE *infile = fopen(input_file_name, "rb"); | ||||
|     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); | ||||
|     fseek(infile, 0, SEEK_SET); | ||||
| 
 | ||||
|     unsigned char* buffer = malloc(file_size); | ||||
|     if (!buffer) { | ||||
|     unsigned char* data = malloc(file_size); | ||||
|     if (!data) { | ||||
|         fclose(infile); | ||||
|         return -1; | ||||
|     } | ||||
| 
 | ||||
|     fread(buffer, 1, file_size, infile); | ||||
|     fread(data, 1, file_size, infile); | ||||
|     fclose(infile); | ||||
| 
 | ||||
|     // Підрахунок частоти кожного байта
 | ||||
|     size_t frequencies[256] = {0}; | ||||
|     for (size_t i = 0; i < file_size; i++) { | ||||
|         frequencies[buffer[i]]++; | ||||
|     } | ||||
| 
 | ||||
|     HuffmanSymbol symbols[256]; | ||||
|     size_t num_symbols = 0; | ||||
|     // Створюємо дерево Хаффмана
 | ||||
|     Node* root = create_huffman_tree(data, file_size); | ||||
| 
 | ||||
|     // Генерація кодів Хаффмана
 | ||||
|     HuffmanCode codes[256]; | ||||
|     for (int i = 0; i < 256; i++) { | ||||
|         if (frequencies[i] > 0) { | ||||
|             symbols[num_symbols].symbol = (unsigned char)i; | ||||
|             symbols[num_symbols].frequency = frequencies[i]; | ||||
|             num_symbols++; | ||||
|         codes[i].code = NULL; | ||||
|     } | ||||
| 
 | ||||
|     char current_code[256]; | ||||
|     generate_huffman_codes(root, codes, current_code, 0); | ||||
| 
 | ||||
|     // Стиснення даних
 | ||||
|     FILE *outfile = fopen(output_file_name, "wb"); | ||||
|     if (!outfile) { | ||||
|         free(data); | ||||
|         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); | ||||
| 
 | ||||
|     // Тут треба реалізувати кодування та запис бітових кодів в файл
 | ||||
|     // Оскільки це складніше, я залишаю це як заготовку для подальшої реалізації
 | ||||
| 
 | ||||
|     free(buffer); | ||||
|     return 1; | ||||
|     return 1;  // Повертаємо успішний результат
 | ||||
| } | ||||
| 
 | ||||
| // Функція для декомпресії за допомогою Хаффмана
 | ||||
| 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