Top 11 허프만 코드 C 언어 16489 Good Rating This Answer

You are looking for information, articles, knowledge about the topic nail salons open on sunday near me 허프만 코드 c 언어 on Google, you do not find the information you need! Here are the best content compiled and compiled by the toplist.prairiehousefreeman.com team, along with other related topics such as: 허프만 코드 c 언어 C 허프만 코드 구현, 허프만 코드 예제, 허프만 코드 디코딩, 허프만 코드 c, 허프만 트리, 백준 허프만, 허프만 코드 힙, 허프만 코드 자바


허프만 압축 알고리즘 강좌 (Huffman Coding Algorithm Tutorial)
허프만 압축 알고리즘 강좌 (Huffman Coding Algorithm Tutorial)


It’s my life : 자료구조 :: 힙(2) “최소힙을 이용한 허프만트리”

  • Article author: printf.egloos.com
  • Reviews from users: 1417 ⭐ Ratings
  • Top rated: 4.4 ⭐
  • Lowest rated: 1 ⭐
  • Summary of article content: Articles about It’s my life : 자료구조 :: 힙(2) “최소힙을 이용한 허프만트리” 허프만 트리 HuffmanTree.cpp □ 허프만(Huffman) 코드 허프만 부호와의 기본 개념은 각 단위 정보를 표현하는 비트 수를 단위 정보들의 출현 빈도를 … …
  • Most searched keywords: Whether you are looking for It’s my life : 자료구조 :: 힙(2) “최소힙을 이용한 허프만트리” 허프만 트리 HuffmanTree.cpp □ 허프만(Huffman) 코드 허프만 부호와의 기본 개념은 각 단위 정보를 표현하는 비트 수를 단위 정보들의 출현 빈도를 … It’s my life
  • Table of Contents:
It's my life : 자료구조 :: 힙(2)
It’s my life : 자료구조 :: 힙(2) “최소힙을 이용한 허프만트리”

Read More

[C++] 압축 프로그램 개발 (코드 O, 허프만 코딩, Huffman coding, 허프만 코드)

  • Article author: kibbomi.tistory.com
  • Reviews from users: 32975 ⭐ Ratings
  • Top rated: 3.5 ⭐
  • Lowest rated: 1 ⭐
  • Summary of article content: Articles about [C++] 압축 프로그램 개발 (코드 O, 허프만 코딩, Huffman coding, 허프만 코드) [C++] 압축 프로그램 개발 (코드 O, 허프만 코딩, Huffman coding, 허프만 코드). KIBBOMI 2020. 11. 4. 03:34. 학부 저학년 때 개발했던 프로그램입니다. …
  • Most searched keywords: Whether you are looking for [C++] 압축 프로그램 개발 (코드 O, 허프만 코딩, Huffman coding, 허프만 코드) [C++] 압축 프로그램 개발 (코드 O, 허프만 코딩, Huffman coding, 허프만 코드). KIBBOMI 2020. 11. 4. 03:34. 학부 저학년 때 개발했던 프로그램입니다. 학부 저학년 때 개발했던 프로그램입니다. 그때는 성능보다는 개발을 우선으로 해서, 과제용으로는 충분할지 모르겠으나 어디 보여주기엔 좀 그래서… 외장하드에 묻어두다가 그래도 그때 개발했던 내용을 공유하..
  • Table of Contents:
[C++] 압축 프로그램 개발 (코드 O, 허프만 코딩, Huffman coding, 허프만 코드)
[C++] 압축 프로그램 개발 (코드 O, 허프만 코딩, Huffman coding, 허프만 코드)

Read More

자료구조 | 우선순위큐 히프, 허프만코드

  • Article author: skying23.tistory.com
  • Reviews from users: 10576 ⭐ Ratings
  • Top rated: 4.1 ⭐
  • Lowest rated: 1 ⭐
  • Summary of article content: Articles about 자료구조 | 우선순위큐 히프, 허프만코드 최소히프를 사용한 허프만 코드 #include … top+1); } //단말노드이면 코드를 출력한다. if(is_leaf(root)){ printf(“%c: “, root->ch); … …
  • Most searched keywords: Whether you are looking for 자료구조 | 우선순위큐 히프, 허프만코드 최소히프를 사용한 허프만 코드 #include … top+1); } //단말노드이면 코드를 출력한다. if(is_leaf(root)){ printf(“%c: “, root->ch); … 개념 보통의 큐는 FIFO(first-in-first-out) 원칙에 따라 먼저 들어온 데이터가 먼저 나간다. 그러나 우선순위 큐는 데이터들이 우선순위를 가진다. 따라서 우선순위가 높은 데이터가 먼저 나간다. 구현방법 배열..
  • Table of Contents:

댓글0

공지사항

최근글

인기글

최근댓글

태그

전체 방문자

자료구조 | 우선순위큐 히프, 허프만코드
자료구조 | 우선순위큐 히프, 허프만코드

Read More

[허프만 코드] Huffman Code의 이해 및 구현

  • Article author: wisdomtic.cf
  • Reviews from users: 18055 ⭐ Ratings
  • Top rated: 3.6 ⭐
  • Lowest rated: 1 ⭐
  • Summary of article content: Articles about [허프만 코드] Huffman Code의 이해 및 구현 예를 들어 AABBAC라는 문자열을 살펴보면, 각 문자의 빈도수는 아래와 같습니다. A : 3번 B : 2번 C : 1번. 이에 따라, 가장 자주 나오는 문자 … …
  • Most searched keywords: Whether you are looking for [허프만 코드] Huffman Code의 이해 및 구현 예를 들어 AABBAC라는 문자열을 살펴보면, 각 문자의 빈도수는 아래와 같습니다. A : 3번 B : 2번 C : 1번. 이에 따라, 가장 자주 나오는 문자 … “허프만 코드” 문자 빈도 수를 이용해 통계적으로 압축하는 알고리즘 이론 허프만 코드는 압축 알고리즘 중 하나로, 입력 데이터를 더 적은 용량으로 만드는 것입니다. 허프만 코드의 요점은 자주 나오는 문자에..
  • Table of Contents:

허프만  코드

태그

관련글

댓글0

공지사항

최근글

인기글

최근댓글

태그

전체 방문자

[허프만 코드] Huffman Code의 이해 및 구현
[허프만 코드] Huffman Code의 이해 및 구현

Read More

허프만 코드(Huffman code)

  • Article author: withhamit.tistory.com
  • Reviews from users: 31016 ⭐ Ratings
  • Top rated: 3.7 ⭐
  • Lowest rated: 1 ⭐
  • Summary of article content: Articles about 허프만 코드(Huffman code) 허프만 코드는 데이터를 효율적으로 압축하는데 사용하는 방법으로 탐욕 알고리즘 중 하나입니다. 압축하고자 하는 문자열에서 자주 등장하는 문자는 … …
  • Most searched keywords: Whether you are looking for 허프만 코드(Huffman code) 허프만 코드는 데이터를 효율적으로 압축하는데 사용하는 방법으로 탐욕 알고리즘 중 하나입니다. 압축하고자 하는 문자열에서 자주 등장하는 문자는 … 허프만 코드는 데이터를 효율적으로 압축하는데 사용하는 방법으로 탐욕 알고리즘 중 하나입니다. 압축하고자 하는 문자열에서 자주 등장하는 문자는 짧은 비트로 표현하고 거의 등장하지 않는 문자는 긴 비트로..
  • Table of Contents:

관련글

댓글4

공지사항

태그

전체 방문자

티스토리툴바

허프만 코드(Huffman code)
허프만 코드(Huffman code)

Read More

허프만 알고리즘 :: zoonvivor

  • Article author: zoonvivor.tistory.com
  • Reviews from users: 49383 ⭐ Ratings
  • Top rated: 3.5 ⭐
  • Lowest rated: 1 ⭐
  • Summary of article content: Articles about 허프만 알고리즘 :: zoonvivor 허프만 알고리즘. zoonvivor 2018. 5. 4. 18:52 … 아래는 C언어 소스코드이다. … //leaf일때 그에 해당하는 알파벳과 허프만코드를 저장한다. if (IS_LEAF(root)). …
  • Most searched keywords: Whether you are looking for 허프만 알고리즘 :: zoonvivor 허프만 알고리즘. zoonvivor 2018. 5. 4. 18:52 … 아래는 C언어 소스코드이다. … //leaf일때 그에 해당하는 알파벳과 허프만코드를 저장한다. if (IS_LEAF(root)). 1. 사용하는 이유 압축기법의 하나로써 문자의 빈도에 따라 자주 사용되는 문자에는 적은 비트값을, 자주 사용되지 않는 문자에는 많은 비트값을 주어 전체에 필요한 비트값을 줄이기 위해 사용. 영상 압축에 많이..zoon’s story !
  • Table of Contents:
허프만 알고리즘 :: zoonvivor
허프만 알고리즘 :: zoonvivor

Read More

[DS] Huffman Coding Tree (허프만 코딩 트리) — Fascination

  • Article author: fascination-euna.tistory.com
  • Reviews from users: 25959 ⭐ Ratings
  • Top rated: 4.8 ⭐
  • Lowest rated: 1 ⭐
  • Summary of article content: Articles about [DS] Huffman Coding Tree (허프만 코딩 트리) — Fascination # Huffman Coding Tree · # Huffman Coding Tree in C · ‘Study > Data Structure’ 카테고리의 다른 글 … …
  • Most searched keywords: Whether you are looking for [DS] Huffman Coding Tree (허프만 코딩 트리) — Fascination # Huffman Coding Tree · # Huffman Coding Tree in C · ‘Study > Data Structure’ 카테고리의 다른 글 … # Huffman Coding Tree – 데이터 문자의 출현 빈도에 따라 가변 길이의 부호를 사용하는 압축 알고리즘 > 출현 빈도가 높은 문자가 짧은 부호로 변환됨으로써 전체 문장의 데이터 비트 수는 줄어들게 됨 – 장점:..
  • Table of Contents:

블로그 메뉴

공지사항

인기 글

태그

최근 댓글

최근 글

티스토리

티스토리툴바

[DS] Huffman Coding Tree (허프만 코딩 트리) — Fascination
[DS] Huffman Coding Tree (허프만 코딩 트리) — Fascination

Read More


See more articles in the same category here: 995+ tips for you.

Data Structure – Huffman Coding (데이터 압축)

힙을 이용한 허프만 부호화 (텍스트 데이터 압축)

유니코드 문자는 1바이트씩 차지한다. 만약 문자가 10개면 10바이트나 차지하게 된다.

그러나 ‘데이비드 허프먼‘이 제시한 압축 기법에 의하면 10개의 문자를 3바이트 이하로 나타낼 수 있다.

이 압축 기법의 핵심은 빈도 수가 높은 문자에 적은 비트를 할당하고, 빈도 수가 낮은 문자에 많은 비트를 할당하는 것이다.

예를 들어 ‘abccc’라고 하면 a와 b에 각각 11,10 비트를 할당하고 c에 0비트를 할당한다. 이 비트를 문자열에 대입해서 나타내면 (1110000)이므로 7bit로 압축된다.

각 문자에 할당된 비트는 ‘허프만 코드’라고 불리며 ‘허프만 트리’를 통해 얻어 낼 수 있다.

그러기 위해 먼저 ‘허프만 트리’를 구축할 필요가 있다.

‘허프만 트리’에서 리프 노드의 weight는 문자의 빈도 수이다. 내부 노드의 weight는 자식 노드들의 weight합이 된다.

즉 이 트리는 weight를 원소로 가지는 노드가 합쳐 지면서 구축이 된다.

예를 들어 ‘weight=1인 노드’ 와 ‘weight=2인 노드’가 합쳐져서 [(weight가 3인 루트 노드)-(weight가 1,2인 리프 노드들)]형태의 트리가 만들어 진다.

참고로 문자의 빈도 수(weight)가 클수록 나중에 합쳐지게 된다. 따라서 빈도 수가 가장 높으면 트리의 리프 노드들 중 가장 레벨이 낮고 이 낮은 레벨이 적은 ‘허프만 코드’와 연관이 있다.

반대로 문자의 빈도 수(weight)가 낮을수록 먼저 합쳐지게 된다. 초기에는 가장 작은 weight를 지닌 두 개의 노드들로 트리가 구성된다. 이 노드들은 트리의 리프 노드들 중 가장 레벨이 높고 많은 ‘허프만 코드’와 연관이 있다.

그런데 마침 키 값이 가장 작은 노드를 얻어 내는 좋은 자료구조가 있다.

바로 ‘힙(Heap)’이다.

힙을 어떻게 사용하는지는 아래 그림을 통해 설명하였다. 또한 디코딩 방법까지 나타내었으니 참고하길 바란다.

아래에 힙을 이용한 허프만 부호화 (텍스트 데이터 압축)를 C언어로 구현해보았다.

#include #include #define MAX 99999 typedef struct TreeNode { char ch; // 문자 int weight; // 문자의 빈도수(누적치) struct TreeNode* left; struct TreeNode* right; }TreeNode; typedef TreeNode* TreeNode_ptr; typedef struct { TreeNode_ptr htree; // 히든 트리 char ch; // 문자 int key; // 문자의 빈도수(누적치) }element; typedef struct { element heap[MAX]; int heap_size; }HeapType; typedef HeapType* HeapType_ptr; HeapType_ptr Heap_init() { HeapType_ptr h = (HeapType_ptr)malloc(sizeof(HeapType)); h->heap_size = 0; return h; } // 현재 요소의 개수가 heap_size인 히프 h에 item을 삽입한다. // 삽입 함수 void insert_min_heap(HeapType_ptr h, element item) { int i; i = ++(h->heap_size); // 트리를 거슬러 올라가면서 부모 노드와 비교하는 과정 // 배열로 트리를 구현하니까 부모 노드의 idx는 1 while ((i != 1) && (item.key < h->heap[i / 2].key)) { h->heap[i] = h->heap[i / 2]; // 부모를 한 칸 내림 i /= 2; } h->heap[i] = item; // 삽입될 위치가 확실해진 다음에 새로운 노드를 삽입 } // 삭제 함수 element delete_min_heap(HeapType_ptr h) { int parent, child; element item, temp; item = h->heap[1]; // 루트 노드 값을 반환하기 위해 item변수로 옮긴다. temp = h->heap[(h->heap_size)–]; // 말단 노드 값을 temp변수로 옮기고 힙 사이즈를 1 줄인다. (처음에는 루트에 위치해있다고 생각) parent = 1; child = 2; // 루트의 왼쪽 자식부터 비교한다. // 자식이 힙을 벗어나지 않았으면 반복문 진행 while (child <= h->heap_size) { // 두 자식노드가 있으면 더 작은 자식노드를 찾는다. if ((h->heap[parent * 2].key >= 0) && (h->heap[(parent * 2) + 1].key >= 0)) { if ((h->heap[parent * 2].key) < (h->heap[(parent * 2) + 1].key)) child = parent * 2; else child = (parent * 2) + 1; } // 말단 노드를 현재 자식의 부모 노드의 위치에 있다고 생각했을 때, 값이 작거나 같으면 힙 조정할 필요가 X if (temp.key <= h->heap[child].key) break; // 부모 노드 자리에 자식 노드의 키 값을 저장 h->heap[parent] = h->heap[child]; // 한 단계 아래로 이동 parent = child; child *= 2; } // 말단 노드를 현재 자식의 부모 노드의 위치에 있다고 생각했을 때, 자식 값이랑 작거나 같음 -> 실제로 부모 노드에 저장 // (Or) child>h->heap_size로, 위치해야 될 노드에 저장 h->heap[parent] = temp; return item; } // 히든 트리 생성 함수 TreeNode_ptr make_Htree(TreeNode_ptr left, TreeNode_ptr right) { TreeNode_ptr node = (TreeNode_ptr)malloc(sizeof(TreeNode)); node->left = left; node->right = right; return node; } // 잎 노드 판단 함수 int is_leaf(TreeNode_ptr T) { // 1 1 -> 0 // 1 0 -> 0 // 0 1 -> 0 // 0 0 -> 1 return !(T->left) && !(T->right); } typedef struct { char ch; int freq; int* codes; int codes_stop; }PrintArray; PrintArray* parray; // 허프만 코드가 담긴 배열을 parray 구조체에 저장 void print_codes_array(int codes[], int stop, int freq, char ch) { static int i = 0; printf(“[%d] %c(freq:%d,stop:%d):”, i, ch, freq, stop); for (int j = 0; j < stop; j++) printf("%d", codes[j]); printf(" "); parray[i].ch = ch; parray[i].freq = freq; parray[i].codes_stop = stop; for (int k = 0; k < parray[i].codes_stop; k++) (parray[i].codes)[k] = codes[k]; i++; } // 허프만 코드가 담긴 배열 생성 void make_codes_array(TreeNode_ptr T, int codes[], int idx) { // 왼쪽 자식이 있으면 1 저장, 순환 호출 if (T->left) { codes[idx] = 1; make_codes_array(T->left, codes, idx + 1); } // 오른쪽 자식이 있으면 0 저장, 순환 호출 if (T->right) { codes[idx] = 0; make_codes_array(T->right, codes, idx + 1); } // 리프 노드면 허프만 코드 배열을 구조체에 저장 if (is_leaf(T)) { print_codes_array(codes, idx, T->weight, T->ch); } } // 허프만 힙을 이용한 허프만 트리 생성 // 허프만 힙: 허프만 트리 구축을 위한 힙 // 히든 트리: 허프만 힙의 원소(element)가 갖는 숨겨진 트리 // 허프만 트리: 허프만 코드 생성울 위한 트리 (최종 히든 트리) TreeNode_ptr huffman_tree; // 허프만 트리 void make_huffman_heap(int freq[], char ch_list[], int n) { int i; TreeNode_ptr hnode; // 히든 트리 노드 HeapType_ptr h; // 힙 element e, e1, e2; // e: 새로 삽입할 힙 원소, e1,e2: 임의 힙 노드 int codes[100]; h = Heap_init(); // 허프만 힙 초기 세팅 for (i = 0; i < n; i++) { hnode = make_Htree(NULL, NULL); // 히든 트리 노드 생성 e.ch = hnode->ch = ch_list[i]; // 필드에 문자 부여 e.key = hnode->weight = freq[i]; // 필드에 문자의 빈도수 부여 e.htree = hnode; // 필드에 히든 트리의 주소 부여 insert_min_heap(h, e); } // 허프만 트리 구축 for (i = 1; i < n; i++) { // 최소값을 가지는 두 개의 노드를 삭제 e1 = delete_min_heap(h); e2 = delete_min_heap(h); // 두 개의 노드 합쳐서 새 히든 트리 생성 hnode = make_Htree(e1.htree, e2.htree); // 허프만 힙에 새 원소 삽입 (두 개의 노드 키를 누적) e.key = hnode->weight = e1.key + e2.key; e.htree = hnode; insert_min_heap(h, e); } e = delete_min_heap(h); huffman_tree = e.htree; // 허프만 트리 (최종 히든 트리) // 허프만 트리로 코드 생성 (및 출력) make_codes_array(huffman_tree, codes, 0); } int geti; char get_symbol(char string[]) { return string[geti++]; } char* string = NULL; int input_processing(char* ch_list, int* freq) { // 소문자 알파벳 처리 리스트 생성 int alphabet = 26; char* alphabet_list = (char*)malloc(sizeof(char) * alphabet); int* alphabet_freq = (int*)calloc(alphabet, sizeof(int)); for (int i = 0; i < alphabet; i++) alphabet_list[i] = 'a' + i; // 문자열 처리 리스트 생성 string = (char*)malloc(sizeof(char) * MAX); gets(string); // 입력된 알파벳 빈도수 저장 char tmp = 0; int idx = 0; geti = 0; while ((tmp = get_symbol(string)) != 0) { if ('a' <= tmp && tmp <= 'z') { idx = tmp - 'a'; alphabet_freq[idx]++; } } // 빈도수가 0인 알파벳은 제외 int num = 0; for (int i = 0; i < alphabet; i++) { if (alphabet_freq[i] > 0) { ch_list[num] = alphabet_list[i]; freq[num++] = alphabet_freq[i]; } } // 배열 출력 for (int i = 0; i < num; i++) { printf("%c:%d ", ch_list[i], freq[i]); } return num; } int main(void) { // 영어(소문자) 처리 허프만 암호화 // 입력한 문자 배열 char* ch_list = (char*)malloc(sizeof(char)*MAX); // 입력한 문자의 빈도 수 배열 int* freq = (int*)malloc(sizeof(int)*MAX); // 입력받아서 배열에 저장, 문자의 개수 반환 int num = input_processing(ch_list, freq); // 출력을 위한 구조체 배열 생성 parray = (PrintArray*)malloc(sizeof(PrintArray)* MAX); for (int i = 0; i < num; i++) { parray[i].codes = (int*)malloc(sizeof(PrintArray) * MAX); } // 알파벳에 따른 호프만 코드들을 구조체에 저장 make_huffman_heap(freq, ch_list, num); // 호프만 코드들을 입력한 문자에 맞게 저장하기 int tmp; geti = 0; char* huffman_encode=(char*)malloc(sizeof(char)); int huffman_encode_size = 0; while ((tmp = get_symbol(string)) != 0) { for (int i = 0; i < num; i++) { if (parray[i].ch == tmp) { for (int k = 0; k < parray[i].codes_stop; k++) { huffman_encode[huffman_encode_size++] = (parray[i].codes)[k]; realloc(huffman_encode, sizeof(char)+huffman_encode_size); } break; } } } // 호프만 인코드 결과 보기 printf(" "); for (int i = 0; i < huffman_encode_size; i++) printf("%d", huffman_encode[i]); printf(" "); // 허프만 트리 이용해서 디코딩하기 TreeNode* temp=huffman_tree; for (int i = 0; i < huffman_encode_size; i++) { if (huffman_encode[i] == 1) { temp = temp->left; if ((temp->left == NULL) && (temp->right == NULL)) { printf(“%c”,temp->ch); temp = huffman_tree; } } else { temp = temp->right; if ((temp->left == NULL) && (temp->right == NULL)) { printf(“%c”, temp->ch); temp = huffman_tree; } } } printf(”

“); return 0; }

It’s my life : 자료구조 :: 힙(2) “최소힙을 이용한 허프만트리”

# 허프만 트리

■ 허프만(Huffman) 코드

■ 허프만 압축기법

# include

# include

# include < string .h>

#define ALPHABET 26

#define MAX_LEN 255

#define MAX_ELEMENT 1000

typedef struct {

int alpha; // 알파벳 저장을 위한 배열

int freq; // 빈도수 저장을 위한 배열

}AlphaType;

typedef struct TreeNode{

AlphaType weight;

TreeNode *left_child;

TreeNode *right_child;

}TreeNode;

typedef struct {

TreeNode *pTree;

int key;

}Element;

typedef struct {

Element heap[MAX_ELEMENT];

int heap_size;

}HeapType;

void InsertHeap(HeapType *h,Element item)

{

int i;

i=++(h->heap_size);

while (i != 1 && item.key < h->heap[i/ 2 ].key) // 부모노드와 비교

{

h->heap[i]=h->heap[i/ 2 ];

i/= 2 ;

}

h->heap[i]=item;

}

Element DeleteHeap(HeapType *h)

{

int parent= 1 ,child= 2 ;

Element data,temp;

data = h->heap[parent];

temp = h->heap[(h->heap_size)–]; // 삭제에 의한 size 감소

while (child <= h->heap_size)

{

//자식 노드간 작은 수 비교

if ((child < h->heap_size) && (h->heap[child].key) > h->heap[child+ 1 ].key)

child++;

if (temp.key <= h->heap[child].key) break ;

h->heap[parent] = h->heap[child];

parent = child;

child *= 2 ; // 다음 자식 노드와 비교

}

h->heap[parent]=temp;

return data;

}

TreeNode* MakeNode(TreeNode *left,TreeNode *right) // 노드 생성

{

TreeNode *node=(TreeNode*)malloc( sizeof (TreeNode));

if (node == NULL )

{

printf( “메모리 할당 에러

” );

exit(- 1 );

}

node->left_child=left;

node->right_child=right;

return node;

}

void PrintTree(TreeNode *p, int i, char *pCode)

{

if (p)

{

i++;

pCode[i]= ‘1’ ;

PrintTree(p->left_child,i,pCode);

pCode[i]= ‘0’ ;

PrintTree(p->right_child,i,pCode);

pCode[i]= ‘\0’ ;

if (p->left_child == NULL && p->right_child == NULL )

{

printf( “%3c\t%3d\t%s

” ,p->weight.alpha,p->weight.freq,pCode);

}

}

}

int DestroyTree(TreeNode *p)

{

if (p == NULL ) return – 1 ;

DestroyTree(p->left_child);

DestroyTree(p->right_child);

free(p);

return 1 ;

}

void HuffmanTree(AlphaType *pArr, int n)

{

TreeNode *node,*temp;

Element e,e1,e2;

HeapType heap;

char binaryCode[ 100 ];

int i;

heap.heap_size= 0 ;

for (i= 0 ;iweight.alpha=pArr[i].alpha;

e.key=node->weight.freq=pArr[i].freq;

e.pTree=node;

InsertHeap(&heap,e); // 생성한 노드를 힙에 삽입

}

for (i= 0 ;iweight.freq=e1.key+e2.key; // 2개의 노드 값을 더한다

e.pTree=temp; // 위에서 만든 노드를 대입

InsertHeap(&heap,e); // 트리로 구성된 노드를 힙에 삽입

}

e = DeleteHeap(&heap); // 여기서 꺼낸 데이터는 완성된 트리

PrintTree(e.pTree,- 1 ,binaryCode); // 허프만 코드 출력

DestroyTree(e.pTree); // 메모리 반환

}

void Init(AlphaType *p)

{

for ( int i= 0 ;i

[C++] 압축 프로그램 개발 (코드 O, 허프만 코딩, Huffman coding, 허프만 코드)

학부 저학년 때 개발했던 프로그램입니다. 그때는 성능보다는 개발을 우선으로 해서, 과제용으로는 충분할지 모르겠으나 어디 보여주기엔 좀 그래서… 외장하드에 묻어두다가 그래도 그때 개발했던 내용을 공유하고자 글을 씁니다. 그리고 그때 부족하다고 생각했던 부분들을 수정해서 성능도 훨씬 끌어 올렸습니다. 처음엔 C로 구현을 했으나, heap 같은 라이브러리를 사용하기 위해 C++로 구현했습니다. ( C에서 직접 구현해서 사용해도 괜찮습니다)

0. 주저리주저리

허프만코드를 사용해서 압축을 한 프로그램입니다. 결국엔 파일을 읽어서 빈도수를 구한 뒤 허프만 코드를 만들고, 1byte에 1bit씩 채워나가면서 프로그램을 압축하는 형식입니다.

프로그램은 압축, 압축해제 2개의 큰 부분으로 나뉩니다.

압축은 허프만트리를 생성해서 코드를 구합니다. 이 코드가 압축과 압축해제의 연결고리가 됩니다. 압축할 때 생성한 코드의 규칙에 맞게 데이터를 인코딩합니다. 압축 해제할 때 프로그램이 이 ‘코드’를 가지고 있어야 해독을 할 수 있기 때문에 압축파일의 헤더 부분에 서로 약속한 규격으로 코드를 적어두어야 합니다.

압축해제는 코드를 가지고 1bit씩 읽어 buffer에 쌓습니다. 1bit씩 쌓일 때마다 갖고 있는 해독 코드표를 보면서 일치하는 게 있나.. 검사하며 있으면 그 코드에 해당하는 글자로 바꿔서 압축해제 파일에 쓰는 방식입니다.

프로그램의 대부분의 연산이 어디서 발생하는지 아시겠나요?

분석은 밑에서 하겠습니다.

1. 허프만 코딩이란?

ko.wikipedia.org/wiki/%ED%97%88%ED%94%84%EB%A8%BC_%EB%B6%80%ED%98%B8%ED%99%94

이 자료에 따르면, 허프만 부호화(Huffman coding)은 무손실 압축에 쓰이는 엔트로피 부호화의 일종이라고 합니다.

주어진 문장의 빈도수를 세어 빈도수가 많은문자는 짧은 길이의 코드로 대체,

빈도수가 적은 문자는 긴 길이의 코드로 대체하는 방식입니다.

Hello C world!로 예를 들어보겠습니다.

우선 빈도수를 세어 오름차순으로 정렬합니다.

그림 0. 초기상태 (문자, 빈도수)

위처럼, 문자와 빈도수로 나타내자. 빈도수 기준으로 오름차순으로 정렬.

이제 가장 왼쪽(빈도수 적은) 노드 2개를 합칠 것이다. 그리고 다시 빈도수 기준으로 오름차순으로 정렬.

그림 1. 합치고 다시 정렬한 상태

그럼 (1)과 같은 상태가 된다. 이런 것을 계속 반복하다 보면,

그림 2. 완성된 트리

이런 트리가 하나 만들어집니다.

★정렬할 때 삽입 순서를 어떻게 하냐 결과가 달라질 수는 있지만, 코드 길이 * 문자의 빈도수를 모두 합한 값은 항상 똑같이 나옵니다.

여기서 규칙은 마음대로 정해도 되는데, 왼쪽 자식으로 내려갈 때 0, 오른쪽으로 내려갈때 1이라는 규칙을 적용하면 밑의 그림과 같이 나타낼 수 있습니다.

그림 3. 코드 부여

루트에서 길을 계속 따라내려 가보면,

H : 000

e : 001

o : 01

I : 10

r : 1100

d : 1101

C : 1110

w : 1111

로 나타낼 수 있습니다.

자 그러면, 이런 아이디어를 가지고 압축하는 과정을 들여다보겠습니다.

특별한 내용은 없습니다. 위의 그림 0~3까지의 과정을 코드로 옮기기만 하면 됩니다.

2. 압축 과정 (인코딩)

압축과정은 위의 1번에서 설명드렸던 코드를 만드는 것입니다.

2.1) 빈도수 측정

파일을 열어서 처음부터 끝까지 읽어야 합니다. ASCII 코드 같은 경우는 1byte로 해결이 되지만 한글 같은 경우는 2byte라서 특별한 처리를 해주어야 합니다.

ANSI기준으로,

ASCII 코드는 1byte이고 0~127의 값을 가지고 있기 때문에 [128]의 배열로 선언해줍니다.

한글은 조금 달라서 알아볼 필요가 있습니다.

한글은 2byte입니다.

상위 1byte는 0xB0 ~ 0xC8 (총 25자)

하위 1byte는 0xA1 ~ 0xFE (총 94자)

= 2350자

를 나타냅니다.

그래서 배열을 [25][94]자로 확인을 해야 합니다.

그래서 어떠한 문자를 읽었을 때, 그 값이 ASCII code값보다 크다면, (Read Byte > 127) 한글이라고 판단할 수 있습니다. 혹은 읽은 문자 값이 ASCII code 범위라면 영어 혹은 특수문자(. , : ” ‘ 등)이라고 판단할 수 있는 것입니다.

그래서 빈도수를 읽는 코드를 살펴보면

bool cal_frequency(string filename, int freq[][94], int *freqascii) { //ANSI FILE * file = fopen(filename.c_str(), “rt”); if (file == NULL) { //printf(“File open error!

“); return ERROR; } unsigned char index[2] = { 0 }; while (fscanf(file, “%c”, &index[0]) != EOF) { if (index[0] > 127) //korean { fscanf(file, “%c”, &index[1]); ++freq[index[0] – 0xB0][index[1] – 0xA1]; } else// ASCII { ++freqascii[index[0]]; } } fclose(file); return true; //no error }

파일을 읽어서 EOF를 만날 때까지 한글이면 한글 배열에, ASCII코드라면 ASCII코드 배열에 1을 증가시켜줍니다.

2.2. 노드 만들기

이제 빈도수를 측정했으니, 그림 0번과 같은 문자, 빈도수를 갖고 있는 노드들을 만들어 줄 것이다.

그래서 여기서는 tree라는 클래스(구조체도 ok, 오히려 구조체가 개념에 맞을 듯싶습니다.)를 만들었다.

트리를 만들 계획이기 때문에 tree로 네이밍을 했고,

자식들을 연결하는 것은 포인터로 원래 구현을 하나 new 랑 delete 하기 귀찮아서 그냥 STL의 List를 사용했습니다.

class tree { public : tree(){} tree(unsigned char name1_, unsigned char name2_, int freq_) { name[0] = name1_; name[1] = name2_; freq = freq_; left_child = list(); right_child = list(); } //data unsigned char name[2]; //한글 2bytes int freq; //frequency //child list left_child, right_child; };

문자를 담을 2개의 char배열,

만약 아스키코드라면 [0] 번째 배열만 사용할 것입니다.

그리고 빈도수를 담고 있는 int변수,

자식들을 연결할 list 2개입니다.

그래서 이 클래스를 활용해서 우선순위 큐에 집어넣을 겁니다. 우선순위 큐는 빈도수를 기준으로 오름차순으로 정렬하도록 정의했습니다.

(C++문법 관련해서는 밑의 링크를 참조하시거나, 이 코드 링크를 밑에 걸어두었는데 거기서 확인하시길 바랍니다^^)

kibbomi.tistory.com/149

void make_node(int freq[][94], int *freqascii, priority_queue, Mycomp_tree> &pq) { //한글처리 for (int i = 0; i < 25; i++) for (int j = 0; j < 94; j++) if (freq[i][j] != 0) //존재하는 글자만 { tree item(i + 0xB0, j + 0xA1, freq[i][j]); pq.push(item); } //아스키코드 처리 for (unsigned char i = 0; i < 128; i++) if (freqascii[i] != 0) //존재하는 글자만 추출 { tree item(i, 0, freqascii[i]); pq.push(item); } return; } 위의 코드는 빈도수 배열들을 받아서 우선순위 큐(Priority Queue, 여기서는 pq)에 담습니다. 빈도수 별로 상위 2개의 노드를 합치기 때문에 우선순위 큐에 담고 있습니다. 힙 정렬이기 때문에 삽입은 O(logn)입니다. 한글 배열, 아스키코드 배열을 모두 순회하면서 빈도수가 1이라도 있는 것들을 생성하고 pq에 삽입해주었습니다. 2.3. 트리 만들기 이제 그림 1의 과정을 거쳐 그림 2를 만드는 것을 하는 함수를 만들 것입니다. 이전 2.2단계에서 만들었던 pq를 입력으로 받아서 2개씩 끄집어낸 뒤 합치고 다시 삽입하는 그런 과정입니다. 결국 pq는 자동으로 정렬을 해주니까, 상위 2개 item을 꺼내서 합치고 다시 넣어주는 과정만 있으면 됩니다. void make_tree(priority_queue, Mycomp_tree> &pq) { while (pq.size() >= 2) { tree left = pq.top(); pq.pop(); tree right = pq.top(); pq.pop(); tree parent; parent.left_child.push_back(left); parent.right_child.push_back(right); parent.freq = left.freq + right.freq; pq.push(parent); } return; }

left, right에 1개씩 할당하고,

합칠 parent 객체를 만들고 child에 연결한 뒤, 빈도수를 더하고 다시 pq에 넣어줍니다.

2.4. 코드 부여하기

이제는 저 빈도수 tree를 사용해서 code tree를 만들어야 합니다.

bool make_code(const priority_queue, Mycomp_tree>& pq, priority_queue, Mycomp_code> &huffcode) { inorder(pq.top(), huffcode,””); return true; }

코드를 만드는 함수는 다음과 같이 정의했습니다.

pq의 내용을 활용해서 huffcode pq의 내용을 채울 것입니다.

여기서 새로운 code라는 클래스(구조체)가 등장합니다.

class code { public: //data unsigned char name[2]; string huffcode; //허프만부호화코드가 담길곳 };

이 code구조체는 압축과 압축해제 사이의 중요한 역할을 합니다. 이 code가 Key 같은 느낌입니다. (설명서 같은 느낌)

code에는 해당 문자정보와, 어떠한 code로 변경될지 그 정보를 담는 string변수가 1개 있습니다.

tree를 순회하는 방식에는 3가지가 있는데 preorder, inorder, postorder, 순서대로 전위, 중위, 후위 순회입니다. 여기서는 중위 순회를 선택했습니다.

void inorder(const tree & root, priority_queue, Mycomp_code> &huffcode, string cur_code) { if(!root.left_child.empty()) inorder(root.left_child.front(), huffcode, cur_code + “0”); //is leaf, if (root.left_child.empty() && root.right_child.empty()) { code item; if (root.name[0] > 127) //korean { item.name[0] = root.name[0]; item.name[1] = root.name[1]; item.huffcode = cur_code; huffcode.push(item); } else { item.name[0] = root.name[0]; item.name[1] = 0; item.huffcode = cur_code; huffcode.push(item); } } if (!root.right_child.empty()) inorder(root.right_child.front(), huffcode, cur_code + “1”); return; }

루트의 정보와, huffcode의 정보, 현재 code의 정보를 입력으로 받습니다.

재귀함수에 익숙하지 않으신 분들은 이게 어려울 수 있는데, 보통 재귀함수는 큰 문제를 작은 문제로 쪼갤 때 활용할 수 있습니다. 여기서는 트리의 자식을 잡아서 들어도 트리이기 때문에 재귀함수를 적용할 수 있습니다.(같은 문제)

왼쪽으로 내려갈 때는 0을 붙이고 오른쪽으로 내려갈때는 1을 붙여주면서 3번째 매개변수에 코드를 전달했습니다.

중위 순회이기 때문에 값을 대입하는 게 이동하는 것 사이에 존재하게 되고, 순회한다는 개념은 값을 복사하고 저장한다는 의미이고 따라서 code객채를 만들어주고 huffcode pq에 삽입해주었습니다. huffcode는 코드를 사전적 순서로 정렬했습니다.

2.5. 압축하기

이제 드디어 압축을 할 수 있습니다.

압축의 원리는 String변수에 담아놨던 코드들을 1byte 안에 꾸깃꾸깃 넣으면 됩니다.

지금 string변수 (code)에 “01011110”이 만약 있다면 8byte로 나타내고 있는 것입니다. 그런데 이것을 1byte의 8bit에 넣자 라는 것 입니다. 그래서 해당 1byte는 01011110에 해당하는 어떠한 값을 출력하게 됩니다. 그래서 압축파일을 열어보면 이상한 글자가 많습니다.

아이디어는 위와 같고 이제 압축을 할 차례입니다.

압축을 하려면 빈도수 계산했던 것처럼 파일을 처음부터 끝까지 읽어가면서 huffcode pq를 참조해가면서 코드로 바꾸면 됩니다. 결국 huffcode pq가 Key역할을 하는 것이고 이 정보를 압축파일의 헤더에 저장해놓아서 압축 해제할 때 사용해야만 합니다. 그래서 압축파일의 구조는 (huffcode의 정보 & 그 외 정보) + (압축 data)가 들어가게 됩니다.

헤더는 설계하기 나름입니다만, 저 같은 경우는,

마지막 byte에는 의미 있는 bit가 있고 의미가 없는 bit가 있을 것입니다.

그래서 파일의 마지막 byte에는 몇 개의 의미 있는 bit가 존재하는지 나타내는 변수 1개,

huffcode 우선순위 큐의 원소 개수, 코드의 값(문자), code의 유효 bit 수, code data로 적었습니다.

위의 내용이 이해가 잘 안 될 텐데,

결국 huffcode를 만들어 내야 합니다. 처음은 이 pq를 만들어 내기 위해 몇 번 반복해야 할지 나타내는 수이고,

huffcode가 지금 string으로 되어있기 때문에 1글자가 1byte입니다. 이것도 압축할 수 있으므로 1byte짜리 ‘0’ or ‘1’을

1byte의 0___ ____ 으로 압축을 할 수 있습니다.

예를 들어 ‘a’라는 문자가 “00101”이라는 코드로 치환할 수 있을 때, 헤더에는

‘a’는 그대로 기록되고, 유효 bit 수 5가 입력된 뒤, 0010 1 000이렇게 1byte가 입력이 될 것입니다. 그래서 00101을 추출해내기 위해 5가 기록되는 것입니다.

이런 방식으로 헤더를 만듭니다.

bit를 채워 넣기 위해 shift연산을 사용했습니다.

구현은 제가 생각하는 간단한 방법으로 했기 때문에 (옛날 학부시절 코드 보면 토나옵니다) 코드를 보고 또 보시면 이해가 될 것입니다.

결국 데이터를 모두 읽고 문자에 해당하는 코드를 찾아 1byte 안에 넣는 과정이기 때문에.. 압축(인코딩)할 때는 1byte의 buffer라는 걸 사용해서 하면 편리합니다.

void convert_binary(string filename, priority_queue, Mycomp_code> & huffcode) { FILE *readfile = fopen(filename.c_str(), “rt”); filename.erase(filename.length() – 4, 4); string savefilename = filename + “.bin”; FILE *writefile = fopen(savefilename.c_str(), “wb”); int dummy = 0; fprintf(writefile, “%c”, dummy); //fprintf(writefile,”%c”, (char)huffcode.size()); fprintf(writefile, “%d”, (int)huffcode.size()); /*fclose(readfile); fclose(writefile); return;*/ //본문 encoding용 복사. int idx = 0; vector v(huffcode.size()); while (!huffcode.empty()) { code item = huffcode.top(); huffcode.pop(); v[idx++] = item; //korean if (item.name[0] > 127) { fprintf(writefile, "%c%c", item.name[0], item.name[1]); } //alphabet else { fprintf(writefile, "%c", item.name[0]); } fprintf(writefile, "%c",(char)item.huffcode.length()); BYTE buffer = 0; int msb = -1; for (int i = 0; i < item.huffcode.length(); ++i) { if (msb == 7) { fprintf(writefile, "%c", buffer); buffer = 0; msb = -1; } buffer = buffer << 1; buffer = buffer | item.huffcode[i] - '0'; ++msb; } if (msb != -1) { while (msb != 7) { buffer = buffer << 1; msb++; } fprintf(writefile, "%c", buffer); } } //--Header encoding is finished-- BYTE word[2]; BYTE buffer = 0; int msb = -1; //most significant bit while (fscanf(readfile, "%c", &word[0]) != EOF) { if (word[0] > 127) fscanf(readfile, "%c", &word[1]); //buffer의 글자에 해당하는 code를 획득 string write_code = search_code(v, word); for (int i = 0; i < write_code.length(); ++i) { if (msb == 7) { fprintf(writefile, "%c", buffer); buffer = 0; msb = -1; } buffer = buffer << 1; buffer = buffer | write_code[i] - '0'; ++msb; } } //last byte int lastbit = msb; while (lastbit != 7) { buffer = buffer << 1; lastbit++; } fprintf(writefile, "%c", buffer); fseek(writefile, 0, SEEK_SET); fprintf(writefile, "%c", (char)msb); fclose(readfile); fclose(writefile); return; } 가장 마지막 byte의 유효 bit 수는 그때까지 가지 않으면 모르기 때문에 압축을 마친 뒤 fseek함수를 통해서 찾아가서 다시 써주었습니다. 3. 압축 해제 다음은 압축해제입니다. 여기서 중요하게 생각할 점은 이전에 압축했을 때의 huffcode priority queue를 에러 없이 잘 복구하는 점, 그리고 여기서는 1byte를 읽을 때마다 코드를 참조하는 게 아니라 1bit를 읽을 때마다 pq를 찾아보며 똑같은 코드가 있는지 찾아봐야 하기 때문에 탐색 시간을 줄여야 하는 점 입니다. 탐색시간을 줄이기 위해서 이분 탐색 O(logn)을 사용했습니다.(이전 프로그램은 선형으로 탐색하도록 구현했었음. 지금 생각난 거지만 코드는 유일하기 때문에 트리를 한 칸씩 내려가면서 상태를 유지한다면 O(1) 시간에 탐색이 가능할 것 같은 생각이?? 아마도 구현 가능할 것 같은데 귀찮으니까 pass) 압축해제는 정말 간단합니다. 헤더를 써준 대로 그대로 읽어주기만 하면 되기 때문입니다. 물론 bit단위 연산이 많이 햇갈릴 수는 있지만, 그 부분은 코딩능력이기 때문에 어쩔 수 없습니다. 직접 하면서 실력을 늘리는 수밖에 없기 때문입니다. 이 부분은 특별한 알고리즘은 없습니다. encoding 할 때의 역순으로 진행하면 됩니다. 1bit을 읽을 때마다 코드를 찾아야 한다는 점, 여기서는 code를 vector에 담아서 사용했습니다. bool huffman_decode(string name) { vector v; //만들어 내야함. FILE *file = fopen("test.bin", "rb"); if (file == NULL) { return false; } FILE *decoded = fopen("decoded.txt", "wt"); char msb; int codenum; fscanf(file, "%c", &msb); fscanf(file, "%d", &codenum); for (int i = 0; i < codenum; ++i) { code item; char validbit; fscanf(file,"%c", &item.name[0]); if (item.name[0] > 127) fscanf(file, "%c", &item.name[1]); else item.name[1] = 0; fscanf(file, "%c", &validbit); BYTE buffer = 0; while (validbit > 0) { fscanf(file, "%c", &buffer); for (int j = 7; j >= 0; --j){ if (validbit <= 0) break; char bitdata = (buffer >> j) & 1; item.huffcode.push_back(bitdata + '0'); --validbit; } } v.push_back(item); } /*for (code item : v) { printf("(%c%c, %s)

", item.name[0],item.name[1], item.huffcode.c_str()); }*/ //header end. //decode start. //for binary search. sort(v.begin(), v.end(), MySort); BYTE buffer, EOFcheck; int cnt = 0; string huffcode; while (fscanf(file, "%c", &buffer) != EOF) { if (fscanf(file, "%c", &EOFcheck) == EOF) { for (int i = 7; i >= 7 - msb; --i) //3번자리 까지..유효 즉 4개 { char bitdata = (buffer >> i) & 1; huffcode.push_back(bitdata + '0'); BYTE write_word[2] = { 0 }; bool found = false; found = search_code(v, huffcode, write_word); if (found) { fprintf(decoded, "%c", write_word[0]); //printf("%c", write_word[0]); if (write_word[0] > 127) { fprintf(decoded, "%c", write_word[1]); //printf("%c", write_word[1]); } huffcode.clear(); break; } } } else { fseek(file, -1, SEEK_CUR); for (int i = 7; i >= 0; --i) { char bitdata = (buffer >> i) & 1; huffcode.push_back(bitdata + '0'); BYTE write_word[2] = { 0 }; bool found = false; found = search_code(v, huffcode, write_word); if (found) { fprintf(decoded, "%c", write_word[0]); //printf("%c", write_word[0]); if (write_word[0] > 127) { fprintf(decoded, "%c", write_word[1]); //printf("%c", write_word[1]); } huffcode.clear(); } } } } fclose(file); fclose(decoded); return true; }

탐색을 위한 이분 탐색 코드는 밑과 같습니다.

bool search_code(vector &v, string &s, BYTE word[2]) { //binary search for data structure 'code' int left = 0; int right = v.size() - 1; while (left <= right) { int mid = (left + right) / 2; if (v[mid].huffcode < s) left = mid + 1; else if (s < v[mid].huffcode) right = mid - 1; else{ word[0] = v[mid].name[0]; word[1] = v[mid].name[1]; return true; } } return false; } 4. 성능 이 부분을 넣은 이유는 알고리즘의 중요성을 부각하기 위함입니다. 이렇게 자료구조도 생각하고 탐색 시간을 고려한 프로그램과, 대충 배열에 때려 넣어서 찾거나 코드를 만든, 그런 프로그램의 시간차를 보여주고 싶습니다. 4.1) 개선 전 프로그램 예전 성능 개선 전 프로그램 경과 시간입니다. 실행시간 이게 x축 간격이 일정하지 않아서 곡선처럼 보이나 O(n)에 근접했습니다. ASCII 시간 한글 시간 한글 ASCII 시간 4.2) 개선 후 프로그램 간단하게 1MB일 때만 보여드리겠습니다. 압축 관련하여서는 추가적으로 건든 것이 없기 때문에 압축률은 똑같을 것입니다. 개선 후 실행시간 압축 시간, 압축 해제 시간 모두 상당히 줄어든 것을 볼 수 있습니다 물론 여기서도 속도를 더 줄일 수 있는 방법이 있을 것입니다. 글을 쓰면서도 더 줄일 수 있는 방법이 떠 올랐습니다만.. 다시 개선하기도 귀찮고 하니,, 넘기는데 여튼 이렇게 효율적으로 구현하면 속도가 상당히 빨라지는 것을 좀 느끼셨으면 해서 작성했습니다 4.3) 실행 화면 실험 파일(1,002KB) 이렇게 아스키코드로 된 1,002KB(약1MB)의 Test.txt의 이름을 가진 텍스트 파일이 있다. 압축 이렇게 1번을 통해 압축을 선택하고 해당 파일의 이름을 입력하면 압축을 진행한다. 압축을하면 Test.txt -> Test.bin이란 파일이 생성되는데 이 경우 크기가 525KB로 줄었다.

이 파일을 열어보면

압축 파일.bin

당연히 알 수 없는 글자로 가득 차 있다.

이제 이걸 다시 압축 해제 하면

압축해제

다시 1,002KB의 Text.txt파일이 생성되고,

복원한 파일

위의 원본과 똑같은 파일이 생성된다.

5. 결론

허프만 코드를 사용해서 압축하는 프로그램을 만들어 보았습니다.

복잡한 연산이 있기 때문에 자료구조 선택에 큰 영향을 받았고 중요성을 깨달을 수 있었습니다.

그렇게 어렵지는 않았던 것 같습니다.

학부시절에는 몇 주간 프로젝트를 세워서 분석하고 설계하고 했는데 지금은 2일 정도 만에 개선하고 블로그에 글 써야지.. 만몇 주째 하다가 논문 발표가 끝나고 날 잡고 그냥 끝냈습니다.

코드는 밑에 첨부하겠습니다.

압축 프로그램이 큰 의미는 없지만 보시는 분께 도움이 된다면 그걸로 만족입니다!

(code)

github.com/Kibbomi/Huffman_Compression

지적 댓글 환영입니다~^^

So you have finished reading the 허프만 코드 c 언어 topic article, if you find this article useful, please share it. Thank you very much. See more: C 허프만 코드 구현, 허프만 코드 예제, 허프만 코드 디코딩, 허프만 코드 c, 허프만 트리, 백준 허프만, 허프만 코드 힙, 허프만 코드 자바

Leave a Comment