數據結構之赫夫曼編碼

#include <stdio.h>
#include <string.h>
#include <stdlib.h><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

typedef struct
{
    unsigned int weight;/*
放權值*/
    unsigned int parent;/*
父親結點
*/
    unsigned int lchild;/*
左孩子
*/
    unsigned int rchild;/*
右孩子
*/
}HTNode, *HuffmanTree;   /*
動態申請赫夫曼樹
*/
typedef char **HuffmanCode;/*
動態分配赫夫曼表*/

void CreateHuffmanTree(HuffmanTree *HT, unsigned int *w , int n);
void Select(HuffmanTree HT, int t, int *s1, int *s2);
void HuffmanCoding(HuffmanTree HT, HuffmanCode *HC, int n);
void PrintHuffmanCode(HuffmanCode HC, unsigned int *w, int n);
int main(void)
{
    HuffmanTree HT;
    HuffmanCode HC;  
    int i, n;
    unsigned int *w;
   
    printf("
請輸入葉子結點數 : ");
    scanf("%d", &n);
   
    w = (unsigned int *)malloc(n * sizeof(unsigned int));
   
    printf("
請輸入各個葉子結點的權值
: /n");
    for(i = 0; i < n; i++)
    {
        scanf("%d", &w[i]);
    }
    CreateHuffmanTree(&HT, w, n);
    HuffmanCoding(HT, &HC, n);
    PrintHuffmanCode(HC, w, n);
   
    system(“pause”);
}

/*****************************
建立赫夫曼樹,w存放權值,在每次
把兩個小的權值相加後,在每次
select
中都能包括進去新的結點
每次父親結點被重新賦值,不爲0
在每次select中除去

*****************************/
void CreateHuffmanTree(HuffmanTree *HT, unsigned int *w , int n)
{
     int i, m;
     int s1, s2;
     char *cd;
    
     m = 2 * n - 1;                /*
總結點數*/
    
     *HT = (HuffmanTree)malloc((m + 1) * sizeof(HTNode));
    
     for(i = 1; i <= n; ++i, ++w)  /*
葉子結點初試化
*/
     {
         (*HT)[i].weight = *w;
         (*HT)[i].parent = 0;
         (*HT)[i].lchild = 0;
         (*HT)[i].rchild = 0;
     }
    
     for(; i <= m; ++i)
     {
         (*HT)[i].weight = 0;
         (*HT)[i].parent = 0;
         (*HT)[i].lchild = 0;
         (*HT)[i].rchild = 0;
     }
    
     for(i = n + 1; i <= m; ++i)
     {
         Select(*HT, i - 1, &s1, &s2);/*
從權值中選兩個最小的
*/
         (*HT)[s1].parent = i;       /*
父親結點都被賦值,select循環中可以除去
*/
         (*HT)[s2].parent = i;
         (*HT)[i].lchild = s1;      /*
孩子結點被賦值
*/
         (*HT)[i].rchild = s2;
         (*HT)[i].weight = (*HT)[s1].weight + (*HT)[s2].weight;/*
加後成新結點
*/
     }
}

/*尋找兩個最小的結點s1, s2*/
void Select(HuffmanTree HT, int t, int *s1, int *s2)
{
     int m, n, i;
    
     m = n = 10000;/*
感覺有點取巧可以自己修改
*/
     for(i = 1; i <= t; i++)/*
遍歷找兩個最小的結點
*/
     {
         if(HT[i].parent == 0 /*m
n只是一個穿插的過程
*/
            && (HT[i].weight < m || HT[i].weight < n))
         {
             if(m < n)         /*
把大的除去,小的繼續比較放那裏
*/
             {
                 n = HT[i].weight;
                 *s2 = i;
             }
             else
             {
                 m = HT[i].weight;
                 *s1 = i;
             }
         }
     }
     if(*s1 > *s2)            /*
把小的放前面
*/
     {
         i = *s1;
         *s1 = *s2;
         *s2 = i;
     }
}

/*赫夫曼編碼,放入HC*/
void HuffmanCoding(HuffmanTree HT, HuffmanCode *HC, int n)
{
     int i, start, c, f;
     char *cd;
    
     (*HC) = (HuffmanCode )malloc((n + 1) * sizeof(char *));
     cd = (char *)malloc(n * sizeof(char));/*
編碼的空間
*/
     cd[n - 1] = '/0';                     /*
編碼結束符號
*/
    
     for(i = 1; i <= n; ++i)               /*
逐個葉子結點求編碼
*/
     { 
         start = n - 1;                    /*
結束位置
*/
         for(c = i, f = HT[i].parent; f != 0; c = f, f = HT[f].parent)
         {
             /*
從根到葉子求編碼
*/             
             if(HT[f].lchild == c)
             {
                 cd[--start] = '0';
             }//if
             else
             {
                 cd[--start] = '1';
             }//else
         }//for
        
         /*
爲第i個葉子結點求空間
*/
         (*HC)[i] = (char *)malloc((n - start) * sizeof(char));
         strcpy((*HC)[i], &cd[start]);     /*
cd複製到
HC*/
     }//for
}

/*打印編碼*/   
void PrintHuffmanCode(HuffmanCode HC, unsigned int *w, int n)
{
     int i;
    
     printf("HuffmanCode
: /n");
     for(i = 1; i <= n; i++)
     {
         printf("%3d---", w[i - 1]);        /*
先打印權值
*/
         puts(HC[i]);                       /*
打印表
*/
         printf("/n");
     }
}
        

發佈了30 篇原創文章 · 獲贊 5 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章