Huffman赫夫曼树

描述:

对输入的英文大写字母进行统计概率 然后构建哈夫曼树,输出是按照概率降序排序输出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;
}


你可能感兴趣的:(c,struct,null,存储)