Huffman赫夫曼树

原创 2012年03月28日 21:02:48
描述:

对输入的英文大写字母进行统计概率 然后构建哈夫曼树,输出是按照概率降序排序输出Huffman编码。

输入:
大写字母个数 n
第一个字母 第二个字母 第三个字母 ... 第n个字母
输出:
字母1 出现次数 Huffman编码
字母2 出现次数 Huffman编码
字母3 出现次数 Huffman编码
字母n 出现次数 Huffman编码
输入样例:
10
I I U U U I U N U U
输出样例:
U 6 1
I 3 01
N 1 00


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

typedef struct
{
    char c;
    int weight;
    int parent,lchild,rchild;
}HTNode;
typedef char **HuffmanCode;//动态分配数组存储郝夫曼编码表

//记录,用于存放字母和其出现次数
typedef struct
{
    char letter;
    int nums;
}Record;

//链表结点,用于存放记录
typedef struct _Node
{
    Record *record;
    struct _Node *next;
}ListNode;

void ListInsert(ListNode *L,Record *_record)
{
    ListNode *p=L;
    ListNode *s=(ListNode*)malloc(sizeof(ListNode));
    s->record=_record;
    s->next=p->next;
    p->next=s;
}

int ListSearch(ListNode *L,char _letter)
{
    ListNode *p=L->next;
    int cursor=1;
    while(p&&p->next!=NULL)
    {
        if(p->record->letter==_letter)
        return cursor;
        p=p->next;
        cursor++;
    }
    return 0;
}

//遍历链表,调试用,非必须
int TraverseList(ListNode *L)
{
	if(L->next==NULL)
	return 0;
	ListNode *p=L->next;
	//p=L->next;
	//printf("线性表La=");
	while(p->next!=NULL)
	{
		printf("%c %d\n",p->record->letter,p->record->nums);
		p=p->next;
	}
	return 1;
}

int ListLength(ListNode *L)
{
    if(L->next==NULL)
    return 0;
    int length=0;
    ListNode *p=L->next;
    while(p->next!=NULL)
    {
        p=p->next;length++;
    }
    return length;
}

//对链表中的记录进行排序,使权值大的排在前面,以便输出时按权值大小的先后顺序输出
ListNode* ListReOrder(ListNode *p)
{
    ListNode *head=p;
    ListNode *p1=p->next;
    for(;p1!=NULL;p1=p1->next)
    {
        ListNode *p2=p1->next;
        for(;p2!=NULL;p2=p2->next)
        {
            if(p1->record->nums<p2->record->nums)
            {
                Record *temp;
                temp=p1->record;
                p1->record=p2->record;
                p2->record=temp;
            }
        }
    }
    return head;
}

//选择parent为0且weight最小的两个下标
void Select(HTNode* &HT,int k,int &s1,int &s2)
{
    int i;
	for (i=1;i<=k && HT[i].parent!=0 ;i++);
	s1=i;
	for (i=1;i<=k;i++)
		if (HT[i].parent==0 && HT[i].weight<HT[s1].weight)
			s1=i;
	for (i=1; i<=k ; i++)
		if (HT[i].parent==0 && i!=s1)
			break;
	s2=i;
	for (i=1;i<=k;i++)
		if ( HT[i].parent==0 && i!=s1 && HT[i].weight<HT[s2].weight)
			s2=i;
}

void HuffmanCoding(HTNode* &HT,HuffmanCode &HC,int *w,char *letter,int n)
{
    if(n<=1) return;
    int m=2*n-1;
    HT=(HTNode*)malloc((m+1)*sizeof(HTNode));//0号单元未用
    int i;
    //初始化各个HTNode*
        for(i=1;i<=n;++i)
    {
        HT[i].weight=w[i-1];
        HT[i].c=letter[i-1];
        HT[i].parent=HT[i].lchild=HT[i].rchild=0;
    }
    for(;i<=m;++i)
    {
        HT[i].weight=0;
        HT[i].c='\0';
        HT[i].parent=HT[i].lchild=HT[i].rchild=0;
    }

    //建立赫夫曼树
    int s1,s2;
    for(i=n+1;i<=m;++i)
    {
        Select(HT,i-1,s1,s2);
        HT[s1].parent=i;HT[s2].parent=i;
        HT[i].lchild=s1;HT[i].rchild=s2;
        HT[i].weight=HT[s1].weight+HT[s2].weight;
    }

    HC=(HuffmanCode)malloc((n+1)*sizeof(char*));
    char *cd=(char*)malloc(n*sizeof(char));
    cd[n-1]='\0';
    for(i=1;i<=n;++i)
    {
        int start=n-1;
        int c,f;
        for(c=i,f=HT[i].parent;f!=0;c=f,f=HT[f].parent)
        {
            if(HT[f].lchild==c) cd[--start]='0';
            else cd[--start]='1';
        }
        HC[i]=(char*)malloc((n-start)*sizeof(char));
        strcpy(HC[i],&cd[start]);
    }
    free(cd);
}
int main()
{
    ListNode *h=(ListNode*)malloc(sizeof(ListNode));
    h->next=NULL;
    int numofleeters;
    scanf("%d",&numofleeters);
    int i;
    char theLetter;
    for(i=0;i<numofleeters;i++)
    {
        scanf("%c",&theLetter);
        if(theLetter=='\n'||theLetter==' ') i--;//去除回车符、空格
        if(theLetter!=' ')
        {
            int pos=ListSearch(h,theLetter);
            if(!pos)
            {
                //如果是新的字符,则新建一个链表结点插入链表
                Record *newrecord=(Record*)malloc(sizeof(Record));
                if(!newrecord) exit(-1);
                newrecord->letter=theLetter;newrecord->nums=1;
                ListInsert(h,newrecord);
            }
            else
            {
                //如果是已经存在的字符,修改其在链表中记录的字符个数
                ListNode *p=h->next;int cursor=1;
                while(cursor<pos)
                {
                    p=p->next;cursor++;
                }
                p->record->nums++;
            }
        }
    }//for i
    h=ListReOrder(h);
    //TraverseList(h);
    int *w=(int*)malloc(ListLength(h)*sizeof(int));
    char *cstr=(char*)malloc(ListLength(h)*sizeof(char));
    ListNode *p=h->next;
    for(i=0;i<ListLength(h);++i)
    {
        w[i]=p->record->nums;
        cstr[i]=p->record->letter;
        p=p->next;
    }
    HTNode *HT;HuffmanCode HC;int n=ListLength(h);
    HuffmanCoding(HT,HC,w,cstr,n);

    for(i=1;i<=n;++i)
    {
        printf("%c %d %s\n",HT[i].c,HT[i].weight,HC[i]);
    }

    return 0;
}


数据结构和算法——Huffman树和Huffman编码

Huffman树是一种特殊结构的二叉树,由Huffman树设计的二进制前缀编码,也称为Huffman编码在通信领域有着广泛的应用。在word2vec模型中,在构建层次Softmax的过程中,也使用到了...
  • google19890102
  • google19890102
  • 2017年02月04日 15:43
  • 1519

蓝桥杯vip练习 Huffman树

问题描述   Huffman树在编码中有着广泛的应用。在这里,我们只关心Huffman树的构造过程。   给出一列数{pi}={p0, p1, …, pn-1},用这列数构造Huffman树的过程...
  • u010057965
  • u010057965
  • 2014年04月16日 19:23
  • 1266

【C++】Huffman树的实现

介绍huffman树之前我们先来看下如下几个基本概念 1、路径和路径长度 路径:我们定义从A节点到B节点所经过的分支序列称为从A节点到B节点的路径。 路径长度:路径中分支的数目称为路径长度。若规...
  • ArchyLi
  • ArchyLi
  • 2017年05月21日 23:48
  • 528

Huffman树及编码C++实现

Huffman树及编码C++实现                                         By qianghaohao(Johar)                    H...
  • qianghaohao
  • qianghaohao
  • 2016年05月19日 22:54
  • 2041

基础练习 Huffman树

问题描述   Huffman树在编码中有着广泛的应用。在这里,我们只关心Huffman树的构造过程。   给出一列数{pi}={p0, p1, …, pn-1},用这列数构造Huffman树的过程...
  • Liukx940818
  • Liukx940818
  • 2015年03月11日 14:52
  • 531

蓝桥杯-Huffman树(VIP试题)

问题描述   Huffman树在编码中有着广泛的应用。在这里,我们只关心Huffman树的构造过程。   给出一列数{pi}={p0, p1, …, pn-1},用这列数构造Huffman树的过程如下...
  • slightfeverGK
  • slightfeverGK
  • 2016年02月22日 19:33
  • 1290

huffman(哈夫曼)树的实现

哈夫曼树的实现 概念: 哈夫曼(Huffman)树又称最优二叉树或最优搜索树,是一种带权路径长度最短的二叉树。在许多应用中,常常赋给树中结点一个有某种意义的实数,称此实数为该结点的权。从树根结点到该...
  • curson_
  • curson_
  • 2016年12月21日 00:12
  • 416

Huffman树及其应用

最优二叉树(赫夫曼树)                 路    径:由一结点到另一结点间的分支所构成。         路径长度:路径上的分支数目。a→e的路径长度=2         树...
  • qq_28602957
  • qq_28602957
  • 2016年06月01日 10:56
  • 2103

二叉树应用-Huffman编码树(数据结构基础 第6周)

问题描述 分析 做了,在POJ上能AC,但是在coursera上一直提示Compile Error. 没找着问题,呃,,, 源码#include using namespace std;...
  • NNNNNNNNNNNNY
  • NNNNNNNNNNNNY
  • 2016年07月10日 20:52
  • 962

哈夫曼树最优性的证明(思考良久)

哈夫曼树为什么就是最优树??怎么去证明!!?? 证明围绕着两个东西(一定要先看,而且要能够认同): 1. 现在还不知道树长什么模样,但不管怎样,可以确定:最小的两个权值是在整棵树的最下段的两片叶子...
  • qq_25847123
  • qq_25847123
  • 2015年10月09日 09:22
  • 3318
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Huffman赫夫曼树
举报原因:
原因补充:

(最多只允许输入30个字)