C 언어 로 호 프 만 트 리 데이터 구 조 를 자세히 설명 합 니 다.

1.기본 개념
a.경로 와 경로 길이
한 나무 에 하나의 결점 서열 k1,k2,...,kj 가 존재 한다 면 ki 는 ki+1 의 부모(1<=ik1 에서 kj 까지 지나 가 는 분기 수 는 이 두 점 사이 의 경로 길이 라 고 하 는데 이것 은 경로 상의 결산 점수 가 1 감소 하 는 것 과 같다.
b.노드 의 권리 와 밴드 경로 의 길이
많은 응용 에서 나무의 결점 을 특정한 의 미 를 가 진 실 수 를 부여 한다.우 리 는 이 실 수 를 이 결점 의 권 이 라 고 부른다.(예 를 들 어 다음 나무의 파란색 숫자 는 결점 의 권 리 를 나타 낸다)
결점 의 대 권 경로 길 이 는 나무 뿌리 결점 에서 이 결점 사이 의 경로 길이 와 이 결점 상권 의 곱셈 으로 규정 된다.
c.나무의 대역 권 경로 길이
나무의 대역 권 경로 길 이 는 나무의 모든 잎 결점 의 대역 권 경로 길이 의 합 으로 정의 되 고 공식 은 다음 과 같다.
2015816155922684.jpg (314×123)
 그 중에서 n 은 잎 결점 의 수 를 나타 내 고 wi 와 li 는 잎 결점 ki 의 가중치 와 나무 뿌리 결점 에서 ki 사이 의 경로 길 이 를 나타 낸다.
아래 그림 에서 트 리 의 대역 권 경로 길이 WPL=9 x 2+12 x 2+15 x 2+6 x 3+3 x 4+5 x 4  =  122
d.하프 만 나무
하프 만 나 무 는 가장 좋 은 이 진 트 리 라 고도 부른다.이것 은 n 개의 잎 사 귀 결점 으로 구 성 된 모든 이 진 트 리 중 권한 경로 길이 가 WPL 에서 가장 작은 이 진 트 리 입 니 다.
아래 그림 과 같이 하프 만 나무 설명도 입 니 다.
2015816155310262.png (672×652)
2.구조 하프 만 나무
n 개의 가중치 가 있다 고 가정 하면 구 조 된 하 프 만 나 무 는 n 개의 잎 결점 이 있다.n 개의 가중치 가 각각 w1,w2,...,wn 으로 설정 되면 하 프 만 나무의 구조 규칙 은 다음 과 같다.
(1)w1,w2,...,wn 을 n 그루 의 나무 가 있 는 숲 으로 본다.
(2)숲 에서 두 개의 노드 의 가중치 가 가장 작은 나 무 를 선택 하여 합 쳐 새 나무의 왼쪽,오른쪽 나무 로 하고 새 나무의 뿌리 결산 점 의 가중치 는 왼쪽,오른쪽 나무 뿌리 결산 점 의 가중치 의 합 이다.
(3)숲 에서 선택 한 나무 두 그루 를 삭제 하고 새 나 무 를 숲 에 넣는다.
(4)반복(2),(3)보 는 숲 속 에 나무 한 그루 만 남 을 때 까지 이 나 무 는 바로 구 하 는 하프 만 나무 이다.
 예 를 들 어 다음 그림 의 여섯 개의 대 권 엽 결점 에 대해 하프 만 나 무 를 구성 하 는데 절 차 는 다음 과 같다.
2015816155522204.png (1140×1318)
  주의:얻 은 하프 만 나무의 구 조 를 가능 한 한 유일 하 게 하기 위해 일반적으로 규정된 하프 만 나무의 각 결점 의 왼쪽 뿌리 결점 의 권 리 는 오른쪽 뿌리 결점 과 같은 권 리 를 가진다.
구체 적 인 알고리즘 은 다음 과 같다.
   

 //2、     a   n            ,       
  struct BTreeNode* CreateHuffman(ElemType a[], int n) 
  { 
    int i, j; 
    struct BTreeNode **b, *q; 
    b = malloc(n*sizeof(struct BTreeNode)); 
    for (i = 0; i < n; i++) //   b    ,         a           
    { 
      b[i] = malloc(sizeof(struct BTreeNode)); 
      b[i]->data = a[i]; 
      b[i]->left = b[i]->right = NULL; 
    } 
    for (i = 1; i < n; i++)//   n-1           
    { 
      //k1                   ,k2        
      int k1 = -1, k2; 
      for (j = 0; j < n; j++)// k1           ,k2      
      { 
        if (b[j] != NULL && k1 == -1) 
        { 
          k1 = j; 
          continue; 
        } 
        if (b[j] != NULL) 
        { 
          k2 = j; 
          break; 
        } 
      } 
      for (j = k2; j < n; j++)//                  
      { 
        if (b[j] != NULL) 
        { 
          if (b[j]->data < b[k1]->data) 
          { 
            k2 = k1; 
            k1 = j; 
          } 
          else if (b[j]->data < b[k2]->data) 
            k2 = j; 
        } 
      } 
      //                   ,q       
      q = malloc(sizeof(struct BTreeNode)); 
      q->data = b[k1]->data + b[k2]->data; 
      q->left = b[k1]; 
      q->right = b[k2]; 
   
      b[k1] = q;//          b     k1   
      b[k2] = NULL;//k2     
    } 
    free(b); //         b 
    return q; //              
  } 
3.하프 만 인 코딩
전신 통신 에서 전문 은 2 진법 의 0,1 서열 로 전송 되 고 모든 문 자 는 2 진법 인 코딩 에 대응 하 며 전문 의 총 길 이 를 단축 시 키 기 위해 부 등장 인 코딩 방식 으로 하프 만 트 리 를 구성한다.
각 문자 의 출현 빈 도 를 문자 결점 의 값 으로 잎 결점 을 부여 하고,각 지점 의 좌우 지점 은 각각 0 과 1 로 인 코딩 하여,나무 뿌리 결점 에서 각 잎 결점 의 경로 로 한다.
분기 의 0,1 인 코딩 서열 은 이 잎 결점 의 바 이 너 리 인 코딩 과 같다.위의 글 에서 보 듯 이 하 프 만 인 코딩 은 다음 과 같다.
2015816155607502.png (672×652)
 a 의 인 코딩:00
b 의 인 코딩:01
c 인 코딩:100
d 인 코딩:1010
e 의 인 코딩:1011
f 의 인 코딩:11
4.하 프 만 나무의 조작 연산
위의 하 프 만 트 리 를 구체 적 인 사례 로 하여 하 프 만 트 리 의 조작 연산 을 상세 한 프로그램 으로 보 여 줍 니 다.

 #include<stdio.h> 
 #include<stdlib.h> 
 typedef int ElemType; 
 struct BTreeNode 
 { 
  ElemType data; 
  struct BTreeNode* left; 
  struct BTreeNode* right; 
 }; 
  
 //1、     ,            。       ,     int 
 void PrintBTree_int(struct BTreeNode* BT) 
 { 
  if (BT != NULL) 
  { 
   printf("%d", BT->data); //        
   if (BT->left != NULL || BT->right != NULL) 
   { 
    printf("("); 
    PrintBTree_int(BT->left); //      
    if (BT->right != NULL) 
     printf(","); 
    PrintBTree_int(BT->right); //      
    printf(")"); 
   } 
  } 
 } 
  
 //2、     a   n            ,       
 struct BTreeNode* CreateHuffman(ElemType a[], int n) 
 { 
  int i, j; 
  struct BTreeNode **b, *q; 
  b = malloc(n*sizeof(struct BTreeNode)); 
  for (i = 0; i < n; i++) //   b    ,         a           
  { 
   b[i] = malloc(sizeof(struct BTreeNode)); 
   b[i]->data = a[i]; 
   b[i]->left = b[i]->right = NULL; 
  } 
  for (i = 1; i < n; i++)//   n-1           
  { 
   //k1                   ,k2        
   int k1 = -1, k2; 
   for (j = 0; j < n; j++)// k1           ,k2      
   { 
    if (b[j] != NULL && k1 == -1) 
    { 
     k1 = j; 
     continue; 
    } 
    if (b[j] != NULL) 
    { 
     k2 = j; 
     break; 
    } 
   } 
   for (j = k2; j < n; j++)//                  
   { 
    if (b[j] != NULL) 
    { 
     if (b[j]->data < b[k1]->data) 
     { 
      k2 = k1; 
      k1 = j; 
     } 
     else if (b[j]->data < b[k2]->data) 
      k2 = j; 
    } 
   } 
   //                   ,q       
   q = malloc(sizeof(struct BTreeNode)); 
   q->data = b[k1]->data + b[k2]->data; 
   q->left = b[k1]; 
   q->right = b[k2]; 
  
   b[k1] = q;//          b     k1   
   b[k2] = NULL;//k2     
  } 
  free(b); //         b 
  return q; //              
 } 
  
 //3、             
 ElemType WeightPathLength(struct BTreeNode* FBT, int len)//len   0 
 { 
  if (FBT == NULL) //    0 
   return 0; 
  else 
  { 
   if (FBT->left == NULL && FBT->right == NULL)//        
    return FBT->data * len; 
   else //        ,      ,               ,len   
    return WeightPathLength(FBT->left,len+1)+WeightPathLength(FBT->right,len+1); 
  } 
 } 
  
 //4、     (                        ) 
 void HuffManCoding(struct BTreeNode* FBT, int len)//len    0 
 { 
  static int a[10];//      a,         ,             
  if (FBT != NULL)//                a  0 1     
  { 
   if (FBT->left == NULL && FBT->right == NULL) 
   { 
    int i; 
    printf("     %d   :", FBT->data); 
    for (i = 0; i < len; i++) 
     printf("%d", a[i]); 
    printf("
"); } else// , 0、1 a { // , len 1 a[len] = 0; HuffManCoding(FBT->left, len + 1); a[len] = 1; HuffManCoding(FBT->right, len + 1); } } } // void main() { int n, i; ElemType* a; struct BTreeNode* fbt; printf(" n:"); while(1) { scanf("%d", &n); if (n > 1) break; else printf(" n :"); } a = malloc(n*sizeof(ElemType)); printf(" %d :", n); for (i = 0; i < n; i++) scanf(" %d", &a[i]); fbt = CreateHuffman(a, n); printf(" :"); PrintBTree_int(fbt); printf("
"); printf(" :"); printf("%d
", WeightPathLength(fbt, 0)); printf(" :
"); HuffManCoding(fbt, 0); }
실행 결과:
2015816155632294.png (555×288)
다음은 ACM 문 제 를 보도 록 하 겠 습 니 다.
    제목 설명: 
    하프 만 트 리,첫 줄 에 n 을 입력 하여 잎 결점 의 개 수 를 표시 합 니 다.이 잎 결점 으로 하프 만 나 무 를 생 성 해 야 한다.하프 만 나무의 개념 에 따 르 면 이 결점 들 은 권한 이 있다.즉,weight 이다.제목 은 모든 결점 의 값 과 권한 의 곱셈 의 합 을 출력 해 야 한다. 
    입력: 
    여러 그룹의 데 이 터 를 입력 하 십시오. 
    각 조 의 첫 번 째 줄 에 n 개의 수 를 입력 한 다음 에 n 개의 잎 노드(잎 노드 의 가중치 가 100 을 초과 하지 않 고 2<=n<=1000)를 입력 합 니 다. 
    출력: 
    출력 값. 
    샘플 입력: 
    5   
    1 2 2 5 9 
    샘플 출력: 
    37 
ac 코드
링크 구축 하프 만 트 리(정렬 삽입)

 #include <stdio.h> 
 #include <stdlib.h> 
 #define max 1001 
  
 struct htree 
 { 
  int weight; 
  struct htree *lchild; 
  struct htree *rchild; 
  struct htree *next; 
 }; 
  
 void addNode(struct htree *, struct htree *); 
 struct htree* createHfmtree(int *, int); 
 int getWpl(struct htree *, int); 
  
 int main() 
 { 
  int w[max]; 
  int i, n, wpl; 
  struct htree *ht; 
  
  while(scanf("%d", &n) != EOF) 
  { 
   for(i = 0; i < n; i ++) 
   { 
    scanf("%d", &w[i]); 
   } 
    
   ht = createHfmtree(w, n); 
   wpl = getWpl(ht, 0); 
   printf("%d
", wpl); } return 0; } struct htree* createHfmtree(int *w, int n) { int i; struct htree *head, *pl, *pr, *proot; head = (struct htree *)malloc(sizeof(struct htree)); head->next = NULL; for(i = 0; i < n; i ++) { struct htree *pnode = malloc(sizeof(struct htree)); pnode->weight = *(w + i); pnode->lchild = pnode->rchild = pnode->next = NULL; addNode(head, pnode); } while(head->next) { if(head->next->next == NULL) break; pl = head->next; pr = pl->next; head->next = pr->next; proot = (struct htree *)malloc(sizeof(struct htree)); proot->weight = pl->weight + pr->weight; proot->lchild = pl; proot->rchild = pr; addNode(head, proot); } return head->next; } void addNode(struct htree *head, struct htree *pnode) { struct htree *t = head; while(t->next && t->next->weight < pnode->weight) t = t->next; pnode->next = t->next; t->next = pnode; } int getWpl(struct htree *ht, int level) { if(ht == NULL) return 0; if(!ht->lchild && !ht->rchild) { return ht->weight * level; } return getWpl(ht->lchild, level + 1) + getWpl(ht->rchild, level + 1); }

좋은 웹페이지 즐겨찾기