1. 程式人生 > >資料結構——哈夫曼樹的應用

資料結構——哈夫曼樹的應用

Huffman樹的應用1

在這裡插入圖片描述

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define N 6
#define M 2*N-1
#define MAXINT 32767
#define ch 30
#define NUM 100

typedef char numcode[NUM];
typedef char charcode[ch];
typedef char* HuffmanCode[N] ;

typedef struct{
    int weight;   //權值 
    int parent;   //雙親 
    int lchild;   //左孩子 
    int rchild;   //右孩子 
}HTNode,HuffmanTree[M]; 



void select(HuffmanTree ht,int pos,int *s1,int *s2){     //選擇最小值與次小值 
    int i,j,m1,m2;/*m1存放最小權值,s1是m1在陣列的下標*/
    m1=m2=MAXINT;/*m2存放次小權值,s2是m2在陣列的下標*/ 
    for(j=0;j<=pos;j++) {
        if(ht[j].weight<m1&&ht[j].parent==-1){   /*是否出現新的最小值*/ 
            m2=m1;
			*s2=*s1;
            *s1=j;
			m1=ht[j].weight;
        }
        else if(ht[j].weight<m2&&ht[j].parent==-1){  /*是否出現新的次小值*/ 
            m2=ht[j].weight;
            *s2=j;
        }
    }
}

void CrtHuffmanTree(HuffmanTree ht,int w[]){            //建立哈夫曼樹 
    int i,s1,s2;
    for(i=0;i<N;i++){      //葉子初始化 
        ht[i].weight=w[i];
		ht[i].parent=-1;
        ht[i].lchild=-1;
		ht[i].rchild=-1;
    }
    for(i=N;i<M;i++){    //其他結點初始化 
        ht[i].weight=0;
		ht[i].parent=-1;
        ht[i].lchild=-1;
		ht[i].rchild=-1;
    }
    
    /*選擇合併*/
    for(i=N;i<M;i++) {
        select(ht,i-1,&s1,&s2);  /*選擇最小的兩項*/
        ht[i].weight=ht[s1].weight+ht[s2].weight;
        ht[s1].parent=i;
        ht[s2].parent=i;
        ht[i].lchild=s1;
        ht[i].rchild=s2;
    }
}

void CrtHuffmanCode(HuffmanTree ht,HuffmanCode hc){     //建立字元編碼集 
    char *cd=(char*)malloc(N*sizeof(char));;
	int start,c,p,i;
	
    cd[N-1]='\0';   
    for(i=0;i<N;i++){
        start=N-1;
		c=i;
        p=ht[i].parent;
        while(p!=-1){
            --start;
            if(ht[p].lchild==c) cd[start]='0';
            else    cd[start]='1';
            
			c=p;
			p=ht[p].parent;
        }
        hc[i]=(char*)malloc((N-start)*sizeof(char));        
        strcpy(hc[i],&cd[start]);

    }
    free(cd);
}

void printcode(char s[],HuffmanCode hc){    //輸出個字元及對應編碼 
    for(int i=0;i<N;i++){
        printf("%c:",s[i]);
        printf("%s\n",hc[i]);

    }
}

void chartocode(charcode c,char s[],HuffmanCode hc){  //輸出編碼串 
    char *p=c;  
    while(*p!='\0'){    
        for(int j=0;j<N;j++){
            if(*p==s[j])
                printf("%s",hc[j]);
        }
        p++;
    }
    printf("\n");   
}

void  numtochar(numcode ns,HuffmanTree ht,char s[]){   //輸出譯碼串 
    char *p=ns;
	int key;
	HTNode g;
    while(*p!='\0'){
        g=ht[M-1];             
        while(g.lchild!=-1&&g.rchild!=-1&&(*p!='\0')){
            switch(*p){              
            case '0':
					key=g.lchild;
					g=ht[g.lchild];
					break;
            case '1':
					key=g.rchild;
					g=ht[g.rchild];
					break;
            }
            p++;
        }
        printf("%c",s[key]);
    }
}

int main(){ 
    HuffmanTree ht;    //哈夫曼樹 二叉樹 
	HuffmanCode hc;    //字元編碼  字元指標陣列 
	charcode c;       //編碼串 字元陣列 
	numcode ns;       //譯碼串 字元陣列 
    char s[N]={'A','B','C','D','E','F'};
    int  w[N];

    for(int i=0;i<N;i++) scanf("%d",&w[i]);   //頻度陣列   
    scanf("%s",&c);   //編譯碼 
    scanf("%s",&ns);  //譯碼串 


    CrtHuffmanTree(ht,w);    //建立哈夫曼樹 

    CrtHuffmanCode(ht,hc);
    
    printcode(s,hc);       //列印各字元及編碼 
    chartocode(c,s,hc);    //列印編碼串 
    numtochar(ns,ht,s);    //列印譯碼串 
}