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)树算法

http://blog.163.com/zhoumhan_0351/blog/static/3995422720098275836215/ 构造最优二叉树-赫夫曼(Huffman)树算法   ...

赫夫曼(Huffman)树

赫夫曼树即最优树,是一类带权路径长度最短的树。 首先得,澄清几个概念: (1)结点的路径长度:  从根结点到该结点的路径上分支的数目。 (2)树的路径长度: 从树根到每个结点的路径长...

赫夫曼(Huffman树

转载自:http://blog.163.com/zhoumhan_0351/blog/static/3995422720098275836215/ 一、基本概念 1、赫夫曼(Huffman)树又称...

Huffman(赫夫曼树)

1.Huffman设计了一个贪心算法来构造最优前缀码,可以有效地压缩数据,按频率(大小)来编码。2.构造huffman树最普通的算法是每次选出两个最小的元素作为它的左右子树。依次从叶节点向上回溯,即可...

[C/C++] 构造最优二叉树-赫夫曼(哈夫曼、Huffman)树算法实现

一、基本概念 1、赫夫曼(Huffman)树又称最优二叉树或最优搜索树,是一种带权路径长度最短的二叉树。在许多应用中,常常赋给树中结点一个有某种意义的实数,称此实数为该结点的权。从树根结点到该结点之...

贪心算法 赫夫曼编码问题(Huffman)

赫夫曼编码是一种广泛用于数据压缩的问题,该算法的主要优势在于节约了存储和传输成本。 举一个例子: 假设要传输的数据为那么传输成本就是: 45*3 + 30 * 3 + 29 * 3 + 10 *...
  • jeffleo
  • jeffleo
  • 2016年12月10日 11:06
  • 331

huffman(赫夫曼编码)之C/C++实现

有点儿兴奋,有点儿紧张,这是我人生发的第一篇正式的blog,在进入正文之前,请容许我说一点儿序言,之所以发这一blog文章,一来是想记录下自己一天做了些什么,学了些什么,所谓:好记性不如烂笔头,以前没...

重温经典之赫夫曼(Huffman)编码

先看看赫夫曼树 假设有n个权值{w1,w2,…,wn},构造一个有n个叶子结点的二叉树,每个叶子结点权值为wi,则其中带权路径长度WPL最小的二叉树称作赫夫曼树或最优二叉树。   赫夫曼树的构造...

Huffman tree(赫夫曼树、霍夫曼树、哈夫曼树、最优二叉树)

Huffman tree(赫夫曼树、霍夫曼树、哈夫曼树、最优二叉树)flyfish 2015-8-1Huffman tree因为翻译不同所以有其他的名字 赫夫曼树、霍夫曼树、哈夫曼树 定义引用自严蔚...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Huffman赫夫曼树
举报原因:
原因补充:

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