2012 Dm 07

578 views
513 views

Published on

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
578
On SlideShare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
2
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

2012 Dm 07

  1. 1. project #7 Group Codes 이산치 수학 B1 조장 20113318 정예린 조원 20093483 백종근 20093496 윤은영 20093468 김현호 20113311 장동규
  2. 2. 순서 •조원별 업무분담 •일정 계획 •문제 파악-문자의 빈도수에 따른 코드를 찾는 허프만 알고리즘으로 설계 •알고리즘 계획 •소스구현
  3. 3. 1) 조원별 업무 분담이름 역할백종근 보고서 작성, 자료 조사김현호 자료 조사, 보고서 작성장동규 알고리즘, 자료조사, 보고서 작성윤은영 보고서 작성, 자료 조사정예린 코딩, 자료 조사2)일정계획날짜 계획06.11~06.13 프로젝트에 대한 자료 조사06.14~06.18 알고리즘을 이용해 소스를 작성 소스의 잘못된 부분 수정, 최종 보고서 작06.18~06.20 성
  4. 4. 3)문제파악1. hamming distance같은 비트 수를 갖는 2진 부호 사이에 대응되는 비트값이 일치하지 않는 개수. 일반적으로해밍 거리 d가 d≥2a+1이면 a개의 오류를 정정할 수 있다. A:101011, B:110010, A와 B의해밍 거리는 3이다.해밍 코드에서 연속하는 두 숫자 코드 사이의 2진수. 즉, 두 개의 n 비트 2진 부호.(x1, x2,…, xn), (y1, y2,…, yn)에 있어서ㅣx1-y1ㅣ+ㅣx2-y2ㅣ+…+ㅣxn-yn을 해밍 거리라고 한다. 각 x, y는 2진 부호이면서 1, 0 중 하나의 값을 가지므로ㅣxi+yiㅣ= xi⊕yi=(xi-yi)2인 성질을 가진다. 따라서ㅣx1-y1ㅣ+ㅣx2-y2ㅣ+…+ㅣxn-ynㅣ=(x1-y1)2+(x2-y2)2+…+(xn-yn)2이 되므로 유클리드 거리의 제곱이 된다.
  5. 5. 2. coordinate어느 한 행과 열의 교차점과 같은 특정 위치를 지정하기 위해 사용되는 1쌍의 값. 컴퓨터그래픽스(CG)와 화면 표시에서 좌표는 직선상의 점, 네모꼴의 각, 화면상의 픽셀의 위치 등을 지정하는 데 사용된다. 다른 컴퓨터 응용에서 좌표는 스프레드시트상의 셀, 도표상의 데이터 포인트, 기억 장치 내의 위치 등을 지정하는 데 사용된다. 좌표의 의미와 배열 등을 규정하는 체계 또는 표준을 좌표계(coordinate system)라고 한다. 가장 보편적인 데카르트 좌표계에서는 각 축이 교차하는 점을 좌표를 측정하는 원점으로 하여 2차원 및 3차원의 공간위에 직사각형의 그리드를 겹쳐 놓는다. 2차원에서는 X축과 Y축의 교차점이 원점이 되고, 3차원에서는 X축, Y축, Z축의 교차점이 원점이 된다. 목적에 따라 여러 가지 좌표계가 사용된다.3. n-tuple한 릴레이션의 애트리뷰트 개수를 차수(degree)라 하는데, N의 차수를 가진 한 행(行)을 말한다.4. huffman code압축기법의 하나.가변 길이 코드로 문자의 발생빈도를 검사해 발생 빈도가 높은 문자에 적은 수의 비트를,빈도수가 적은 문자에 많은 수의 비트를 할당한다.4)-1 heapheap은 프로그램이 실행될 때까지는 알 수 없는 가변적인 량만큼의 데이터를 저장하기 위해, 프로그램의 프로세스가 사용할 수 있도록 미리 예약되어 있는 메인 메모리의 영역이다.예를 들면, 하나의 프로그램은 처리를 위해 한 명 이상의 사용자로부터 서로 다른 량의 입력을 받을 수 있으며, 즉시 모든 입력데이터에 대해 처리를 개시한다. 운영체계로부터 이미확보된 일정량의 heap 저장 공간을 가지고 있으면, 저장과 관련된 처리를 좀 더 쉽게 할 수있으며, 일반적으로 필요할 때마다 운영체계에게 매번 저장 공간을 요청하는 것보다 빠르다.프로세스는 필요할 때 heap 블록을 요구하고, 더 이상 필요 없을 때 반환하며, 이따금씩 "자투리 모으기"를 수행함으로써 자신에게 할당된 heap을 관리한다. 여기서 자투리 모으기란더 이상 사용되지 않는 블록들을 사용 가능한 상태로 만들고, 또한 heap 내의 사용 가능한공간을 인지함으로써 사용되지 않은 작은 조각들이 낭비되지 않도록 하는 것을 말한다.
  6. 6. 4)-2 허프만 트리 예4)알고리즘 계획1. 문자열을 검사해 각 문자의 빈도수를 조사해 우선순위 큐에 집어넣는다. (빈도수가 낮을수록 우선순위는 높다)2. 큐에서 2개의 노드를 추출 이진트리로 만들고 루트는 두 노드의 빈도수 합으로 한다.3. 생성된 이진트리의 루트노드 x를 다시 우선순위 큐에 삽입 이때 x의 빈도수는 x의 자식노드의 빈도수 합이다.4. 모든 원소가 이진트리의 원소가 될 때 까지 2,3 과정 반복5. 트리가 완성되면 루트를 기준으로 왼쪽은0, 오른쪽은 1의 가중치를 부여해 트리의 노드 에 코드를 부여
  7. 7. 5)소스 구현-참고소스 및 분석5)-1//Deap Class and Huffman Tree Library//created by Kim Yongmook ( http://moogi.new21.org )//Originically created on June 10, 2003#include <stdio.h>#include <time.h>#include <stdlib.h>#include <string.h>#include <assert.h>typedef int BOOL;#define ASSERT(p) assert(p)template<typename TYPE>inline void Swap(TYPE &a, TYPE& b){ TYPE c; c=a; a=b; b=c;}//Deap data structure * * * * * * * * * * * *template<typename TYPE, typename ARG_TYPE>class CDeap { TYPE *m_pData; int m_nSize, m_nCount; static int GetAdjacentNode(int x, int *dir=NULL) { int i; //x must be equal to or greater than 2! //2->6, 15->11, 7->5 converter //dir: 0 if 2,4,5,10 (left side, that is min heap), else 3 7 13 (right side,max heap) for(i=31;(x&(1<<i))==0;i--); if(dir) *dir=!!(x&(1<<(i-1))); return x^(1<<(i-1)); } void AddHelper(ARG_TYPE p, int pos);public: CDeap(int siz): m_nSize(siz), m_nCount(2) {
  8. 8. m_pData=new TYPE[siz]; m_pData-=2; //0, 1 인덱스는 쓰이지 않고 있다. } ~CDeap() { delete [](m_pData+2); } int GetSize() const { return m_nSize; } int GetCount() const { return m_nCount-2; } //WARN: 최소한 자료가 하나는 있어야 이들 함수를 쓸 수 있다 TYPE GetMax() const { ASSERT(m_nCount>2); return m_pData[m_nCount>3 ? 3:2];} TYPE& GetMax() { ASSERT(m_nCount>2); return m_pData[m_nCount>3 ? 3:2]; } TYPE GetMin() const { ASSERT(m_nCount>2); return m_pData[2]; } TYPE& GetMin() { ASSERT(m_nCount>2); return m_pData[2]; } BOOL Add(ARG_TYPE p, int policy=-1); BOOL RemoveMax(); BOOL RemoveMin(); void Display() const; //디버깅용};//DEAP의 정의와, 양쪽 힙의 특성을 유지하게끔, p 위치에 삽입된 원소를//요리조리 옮겨주는 함수//단, pos가 MIN 쪽일 때는 트리의 맨 밑바닥 번호여야 하고, (즉 (pos<<1)>=m_nCount )//MAX 쪽일 때는 자식이 최대 하나만 있어야 한다.template<typename TYPE, typename ARG_TYPE>void CDeap<TYPE, ARG_TYPE>::AddHelper(ARG_TYPE p, int pos){ int adj, dir, root; //ASSERT((pos<<1)>=m_nCount); m_pData[pos]=p; if(m_nCount>3) { //원소가 둘 이상이 되면 adj=GetAdjacentNode(pos, &dir); //이제 우리가 어느 쪽이냐에 따라 adj 값을 보정한다. if(dir) { //우리가 max쪽이면 상대는 min. 우리가 상대의 자식들보다도 큰지 검사해야 한다. if((adj<<1)<m_nCount && m_pData[adj]<m_pData[adj<<1]) { adj<<=1; //two children if(adj+1<m_nCount && m_pData[adj]<m_pData[adj+1])adj++; } } else //우리가 min쪽이므로 짝이 존재하지 않을 수도 있다.
  9. 9. if(adj>=m_nCount) adj>>=1; //짝이 존재하는 곳까지 부모 노드로... //우리가 왼쪽에 있는데(min side. dir=0, pos) 우리 값이 오른쪽(adj)보다더 크면 //두 값을 맞바꾸고, adj가 우리 원소가 들어가는 번호가 된다. if(dir^(m_pData[pos]>m_pData[adj])) { Swap(m_pData[adj], m_pData[pos]); dir^=1; } else adj=pos; ASSERT(adj>=2 && adj<=m_nCount); //이제 우리 원소가 소속된 쪽(min or max)에 맞게 힙을 재정렬한다. while(adj>3) { root=adj>>1; //루트가 현재보다 더 크고 최소 트리 모드이거나 //루트가 현재보다 작고 최대 트리 모드이면 서로 위치를 바꾼다:) if( (m_pData[root]>m_pData[adj])^dir ) { Swap(m_pData[adj], m_pData[root]); adj=root; } else break; } }}//policy: 원소 개수가 m_nSize를 넘어갈 때의 정책://0: 최소값을 경신. 1: 최대값을 경신.//-1: 그냥 에러를 반환한다.template<typename TYPE, typename ARG_TYPE>BOOL CDeap<TYPE, ARG_TYPE>::Add(ARG_TYPE p, int policy){ if(GetCount()==m_nSize) switch(policy) { case 0: if(GetMax()<p) return false; else RemoveMax(); break; case 1: if(GetMin()>p) return false; else RemoveMin(); break; default: return false; } m_nCount++; AddHelper(p, m_nCount-1); return true;}template<typename TYPE, typename ARG_TYPE>
  10. 10. BOOL CDeap<TYPE, ARG_TYPE>::RemoveMin(){ int i,j; if(m_nCount==2) return false; //no data to delete for(i=2;(i<<1)<m_nCount;m_pData[i]=m_pData[j], i=j) { j=(i<<1); if(j+1<m_nCount && m_pData[j+1]<m_pData[j]) j++; } //이제 남은 자리에다 마지막 원소를 삽입한다. m_nCount--; AddHelper(m_pData[m_nCount], i); return true;}template<typename TYPE, typename ARG_TYPE>BOOL CDeap<TYPE, ARG_TYPE>::RemoveMax(){ int i,j; switch(m_nCount) { case 2: return false; //no data to delete case 4: case 3: m_nCount--; return true; //simply decrease the count } for(i=3;(i<<1)<m_nCount;m_pData[i]=m_pData[j], i=j) { j=(i<<1); if(j+1<m_nCount && m_pData[j+1]>m_pData[j]) j++; } m_nCount--; //이제 남은 자리에다 마지막 원소를 삽입한다. if(m_nCount==i) i>>=1; //min쪽의 밑바닥 검사를 위한 조치이다!! AddHelper(m_pData[m_nCount], i); return true;}template<typename TYPE, typename ARG_TYPE>void CDeap<TYPE, ARG_TYPE>::Display() const{ int x,a=1,b=0,c=0; for(x=2;x<m_nCount;x++) { printf("%d ", m_pData[x]); c++; if(c==a) { printf("| "), c=0; if(b==1) a<<=1; b^=1; } } puts("");}//Huffman tree library * * * * * * * * * * * *#define NOPARENT 999999class CHuffman {
  11. 11. struct ENTRY { //index 멤버는 배열에서는 이 원소의 부모 노드 번호로, //min 힙 안에서는 이 원소의 원래 배열 번호를 가리킨다. 다용도임. int index, value; ENTRY() {} ENTRY(int a, int b): index(a), value(b) {} operator int() const { return value; } }; int m_nCount; ENTRY *m_pEnt; CDeap<ENTRY, const ENTRY&> m_Heap;public: CHuffman(const int *data, int count): m_Heap(count), m_nCount(count) { int i; m_pEnt=new ENTRY[count*2]; for(i=0;i<count;i++) { m_pEnt[i]=ENTRY(NOPARENT, data[i]); m_Heap.Add(ENTRY(i,data[i])); } } ~CHuffman() { delete []m_pEnt; } void Solve(); //result retrieve int GetCode(int n, char *cod=NULL) const;};//허프만 나무를 n log n 시간만에 구성한다. 힙 덕분에 가능한 복잡도임void CHuffman::Solve(){ int lp=m_nCount; ENTRY a,b; //가장 작은 놈 둘을 빼낸다. while(m_Heap.GetCount()>=2) { a=m_Heap.GetMin(); m_Heap.RemoveMin(); b=m_Heap.GetMin(); m_Heap.RemoveMin(); m_pEnt[a.index].index=-lp; //left (0) side m_pEnt[b.index].index=lp; //right (1) side m_pEnt[lp]=ENTRY(NOPARENT, a.value+b.value); m_Heap.Add(ENTRY(lp, a.value+b.value)); lp++; }}
  12. 12. //actual binary code, plus its length as the return valueint CHuffman::GetCode(int n, char *cod) const{ int j; char *cod2=cod; for(j=0;m_pEnt[n].index!=NOPARENT;j++) { if(cod) { *cod=0+(m_pEnt[n].index>0); cod++; } n=abs(m_pEnt[n].index); } if(cod) { *cod=0; _strrev(cod2); } //reverse the order. _strrev는 표준 함수가 아니기 때문에 지원하지 않는 컴파일러도 있음. return j;}//Demonstrations * * * * * * * * * * * *void DeapTest(){ CDeap<int, int> pk(150); unsigned seee; int i,j, bef,arr[500]; seee=time(0); srand(seee); for(i=0;i<500;i++) arr[i]=i+1; for(j=0;j<3;j++) for(i=0;i<200;i++) Swap(arr[i], arr[rand()%100]); printf("Original order: "); for(i=0;i<150;i++) printf("%d ", arr[i]); puts("n"); for(i=0;i<150;i++) pk.Add(arr[i], 0); printf("Heap form: "); pk.Display(); puts(""); printf("Min form: "); bef=-1; while(pk.GetCount()>0) { printf("%d ", pk.GetMin()); ASSERT(bef<=pk.GetMin()); bef=pk.GetMin(); pk.RemoveMin(); } puts("n"); for(i=0;i<150;i++) pk.Add(arr[i], 1); printf("Max form: "); bef=99999; while(pk.GetCount()>0) { printf("%d ", pk.GetMax()); ASSERT(bef>=pk.GetMax()); bef=pk.GetMax(); pk.RemoveMax(); }}void HuffmanTree(){
  13. 13. int seq[26]={ 1532, 418, 729, 902, 2503, 359, 614, 460, 1765, 67, 530, 1317, 580,1148, 1266, 549, 51, 1100, 2325, 1277, 840, 280, 249, 137, 850, 214}; int i, sum; char buf[24]; CHuffman huf(seq, 26); huf.Solve(); for(i=sum=0;i<26;i++) { printf("%cs code size is %d - ", i+A, huf.GetCode(i, buf)); puts(buf); sum+=huf.GetCode(i)*seq[i]; } printf("Compression size %dn", sum); for(i=sum=0;i<26;i++) sum+=seq[i]*5; printf("UnCompression size %dn", sum);}int main(){ puts("Sorting with Deap:"); DeapTest(); puts("nnHuffman tree:"); HuffmanTree(); return 0;}5)-2#include<stdio.h>#include<stdlib.h> struct sort{ char c; double d;}; //문자와 확률을 넘겨 받는 구초제형 선언#define MAX_ELEMENT 100
  14. 14. typedef struct TreeNode{ int weight; struct TreeNode *left_child; struct TreeNode *right_child;}TreeNode;typedef struct element{ TreeNode *ptree; int key;}element;typedef struct HeapType{ element heap[MAX_ELEMENT]; int heap_size;}HeapType;void print(TreeNode *root);void init(HeapType *h){ h->heap_size=0;}//삽입함수
  15. 15. void insert_min_heap(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 delete_min_heap(HeapType *h){ int parent, child; element item, temp;
  16. 16. item = h->heap[1]; temp = h->heap[(h->heap_size)--]; parent = 1; child = 2; 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 item;}
  17. 17. //이진트리생성함수TreeNode *make_tree(TreeNode *left, TreeNode *right){ TreeNode *node = (TreeNode *)malloc(sizeof(TreeNode)); if(node == NULL){ fprintf(stderr,"메모리할당에러n"); exit(1); } node->left_child = left; node->right_child = right; return node;}//이진트리제거함수void destroy_tree(TreeNode *root){ if(root == NULL) return; destroy_tree(root->left_child); destroy_tree(root->right_child);
  18. 18. free(root);}//허프만코드생성함수void huffman_tree(struct sort arr[], int n){ int i; HeapType heap; element e, e1, e2; TreeNode *node, *x; //int k; init(&heap); for(i=0;i<n;i++){ node = make_tree(NULL,NULL); e.key = node->weight = arr[i]; e.ptree = node; insert_min_heap(&heap, e); } //for(i=0;i<=n;i++) // printf("%d->",heap.heap[i].key);
  19. 19. for(i=1;i<n;i++){ //최소값을가지는두개의노드를삭제 e1 = delete_min_heap(&heap); /*printf("방금힙에서꺼낸것: %dn", e1.key); for(k=1;k<n;k++) printf("꺼내고난후에힙배열: %dn",heap.heap[k].key);*/ e2 = delete_min_heap(&heap); /*printf("그다음힙에서꺼낸것: %dn", e2.key); for(k=1;k<n;k++) printf("꺼내고난후에힙배열: %dn",heap.heap[k].key);*/ //두개의노드를합친다. x = make_tree(e1.ptree, e2.ptree); e.key = x->weight = e1.key + e2.key; //printf("e.key=%d, x->weight=%dn",e.key, x->weight); e.ptree = x; insert_min_heap(&heap, e); //printf("%dn", heap.heap[4].key);}
  20. 20. e = delete_min_heap(&heap); //최종트리 //print(e.ptree);//원래나오는최종트리heap배열엔: 4 6 12 15 8 destroy_tree(e.ptree);}void print(TreeNode *root){ if(root){ print(root->left_child); print(root->right_child); printf("(%d)",root->weight); }}void main(){ struct sort arr[100],; //구조체형 배열을 선언하여 입력받음 int i=0,j=0,m;
  21. 21. for(i=0;i<100;i++) { for(j=0;j<100;j++) { arr[i].c=0; arr[i].d=0; } } j=0; while(j!=6) { scanf("%c %lfn",&arr[j].c,&arr[j].d); j++; } for(i=0;i<j;i++) { printf("%c %fn",arr[i].c,arr[i].d); //printf("i=%d",i); } huffman_tree(arr, 5);}

×