哈夫曼树与哈夫曼编码

【定义】
带权路径长度(WPL):设二叉树有n个叶子节点,每个叶子节点带有权值Wk,从根节点到每个叶子节点的长度为Lk,则每个叶子节点的带权路径长度之和就是:
WPL=【求和k=1->n】WkLk
最优二叉树或者哈夫曼树:WPL最小的二叉树

/* 哈夫曼树和哈夫曼编码 */

#include
#include

#define LENGTH 6

typedef int ElementType;

//哈夫曼树节点定义
typedef struct HuffmanTreeNode *Huffman;
struct HuffmanTreeNode{
    ElementType data; //权值
    Huffman Left;
    Huffman Right;
};

Huffman CreateHuffmanTree(ElementType arr[]); //创建哈夫曼树
int CalculateWPL(Huffman PtrTree,int len); //计算带权路径长度
void HuffmanCoding(Huffman PtrTree,int len); //哈夫曼编码
void PreOrderPriHuffmanTreeNode(Huffman PtrTree);//先序打印哈夫曼树
void MidOrderPriHuffmanTreeNode(Huffman PtrTree);//中序打印哈夫曼树

int main()
{
    ElementType arr[]={9,12,6,3,5,15};
    Huffman Proot=CreateHuffmanTree(arr);

    puts("PreOrderPriHuffmanTreeNode: ");
    PreOrderPriHuffmanTreeNode(Proot);
    putchar('\n');
    puts("MidOrderPriHuffmanTreeNode: ");
    MidOrderPriHuffmanTreeNode(Proot);
    putchar('\n');

    HuffmanCoding(Proot,0);

    printf("WPL=%d\n", CalculateWPL(Proot,0));

    system("pause");

    return 0;
}

Huffman CreateHuffmanTree(ElementType arr[])
{
    Huffman PtrArr[LENGTH];
    Huffman PtrT;
    Huffman Proot=NULL;

    /*
        [1]将各个权值看成n棵树的森林(每棵树仅有一个节点)
        构建一个结构体指针数组,每个数组元素均是一棵树
    */
    for(int i=0;idata=arr[i];
        PtrT->Left=NULL;
        PtrT->Right=NULL;
        PtrArr[i]=PtrT;
    }

    /* 循环建立哈夫曼树 */
    for(int i=1;idatadata){
                    k2=k1;
                    k1=j;
                }else if(PtrArr[j]->datadata){
                    k2=j;
                }
            }
        }
        /*
            [2]在森林中选出两个根结点的权值最小的树合并,
            作为一棵新树的左、右子树,
            新树的根结点权值为其左、右子树根结点权值之和
            Proot 指向其根节点
        */
        Proot=(Huffman)malloc(sizeof(struct HuffmanTreeNode));
        Proot->data=PtrArr[k1]->data + PtrArr[k2]->data;
        Proot->Left=PtrArr[k1];
        Proot->Right=PtrArr[k2];
        
        //新树插入森林
        PtrArr[k1]=Proot;
        PtrArr[k2]=NULL;
    }

    return Proot;
}

int CalculateWPL(Huffman PtrTree,int len)
{
    if(!PtrTree){
        return 0;
    }else{
        if(PtrTree->Left==NULL&&PtrTree->Right==NULL){
            return PtrTree->data * len;
        }else{
            return CalculateWPL(PtrTree->Left,len+1)+CalculateWPL(PtrTree->Right,len+1);
        }
    }
}

void HuffmanCoding(Huffman PtrTree,int len)
{
    static int arr[20];
    if(PtrTree){
        if(PtrTree->Left==NULL&&PtrTree->Right==NULL){
            printf("Weight: %d\n", PtrTree->data);
            for(int i=0;iLeft,len+1);
            arr[len]=1;
            HuffmanCoding(PtrTree->Right,len+1);
        }
    }
}

void PreOrderPriHuffmanTreeNode(Huffman PtrTree)
{
    if(!PtrTree){
        return;
    }else
    {
        printf("%d ", PtrTree->data); 
        PreOrderPriHuffmanTreeNode(PtrTree->Left);
        PreOrderPriHuffmanTreeNode(PtrTree->Right);
    }
}

void MidOrderPriHuffmanTreeNode(Huffman PtrTree)
{
    if(!PtrTree){
        return;
    }else
    {
        printf("%d ", PtrTree->data); 
        MidOrderPriHuffmanTreeNode(PtrTree->Left);
        MidOrderPriHuffmanTreeNode(PtrTree->Right);
    }
}

输出示例

PreOrderPriHuffmanTreeNode:
50 21 9 12 29 14 6 8 3 5 15
MidOrderPriHuffmanTreeNode:
50 21 9 12 29 14 6 8 3 5 15
Weight: 9
00
Weight: 12
01
Weight: 6
100
Weight: 3
1010
Weight: 5
1011
Weight: 15
11
WPL=122

你可能感兴趣的:(哈夫曼树与哈夫曼编码)