
































































HuffmanTree *HTCreate(RateTabNode *head)//双链表形式创建Huffman树
{
HuffmanTree *p1,*p2,*root;
RateTabNode *temp,*p;
root=(HuffmanTree *)malloc(sizeof(HuffmanTree));
//printf("%d/n",SizeAssure(head));
if(SizeAssure(head)==2)//当只生剩下两个元素,直接将这两棵树作为子树,返回总根结点地址
{
root->ch='/0';
root->LChild=head;
head->parent=root;
root->RChild=head->next;
root->weight=head->weight+head->next->weight;
head->next->parent=root;
head=root;
head->parent=NULL;
return head;
}
else
{
for(p=temp=head;p!=NULL;p=p->next)//找权最小的结点
{
if(temp->weight>p->weight)
temp=p;
}
p1=temp;
/****记下最小结点的地址,将它从链表中移除(分三种情况,头、尾和中间)***/
if(p1->pre==NULL)//表头
{
head=head->next;
head->pre=NULL;
}
else if(p1->next==NULL)//表尾
{
p1->pre->next=NULL;
}
else
{
p1->pre->next=p1->next;
p1->next->pre=p1->pre;
}//中间
p1->next=p1->pre=NULL;
/*********寻找次小权结点,过程同上面完全相同,找去掉最小后的最小,即次小**********/
for(temp=p=head;p!=NULL;p=p->next)
{
if(temp->weight>p->weight)
temp=p;
}
p2=temp;
if(p2->pre==NULL)
{
head=head->next;
head->pre=NULL;
}
else if(p2->next==NULL)
{
p2->pre->next=NULL;
}
else
{
p2->pre->next=p2->next;
p2->next->pre=p2->pre;
}
//取次小值
p2->next=p2->pre=NULL;
//printf("%d/n",SizeAssure(head));getch();
/*********将两个最小值建立一棵子树,并将它们的根结点插入双链表**********/
root->LChild=p1;
root->RChild=p2;
p1->parent=root;
p2->parent=root;
root->ch='/0';
root->weight=p1->weight+p2->weight;
root->next=head;
head->pre=root;
head=root;
head->pre=NULL;
head=HTCreate(head);//递归,直到剩两个结点在双链表中
}
}
{
static int num=0;
if(head->LChild==NULL&&head->RChild==NULL&&num<size)
{
leafhead[num].ch=head->ch;
leafhead[num].leaf=head;
++num;
return;
}
if(head==NULL)return;
FindLeaf(head->LChild,leafhead,size);
FindLeaf(head->RChild,leafhead,size);
}
void HFCoding(LeafNode *leafhead,CodeNode *codehead,int size)//自下向上编码,左0右1
{
int i=0,j=CodeMaxLen;
LeafNode *leaftmp=leafhead;
while(i<size)
{
j=CodeMaxLen;
codehead[i].ch=leaftmp[i].ch;
codehead[i].code[--j]='/0';
while(leaftmp[i].leaf->parent!=NULL&&j>=0)
{
if(leaftmp[i].leaf->parent->LChild==leaftmp[i].leaf)
codehead[i].code[--j]='0';
if(leaftmp[i].leaf->parent->RChild==leaftmp[i].leaf)
codehead[i].code[--j]='1';
leaftmp[i].leaf=leaftmp[i].leaf->parent;//向上
}
++i;
}
}
/********************************************/
/* Huffman编码的无损压缩V2.0 */
/* 2008.3.28 */
/* 作者:付闯 */
/********************************************/
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<malloc.h>
#include<string.h>
#define MaxSize 65536
//定义缓冲区最大高度
#define CodeMaxLen 32
//定义Huffman编码最大长度
typedef struct HT
{
char ch;
unsigned long weight;
struct HT *pre;
struct HT *next;
struct HT *parent;
struct HT *LChild;
struct HT *RChild;
}HuffmanTree,RateTabNode;//树结点,同时也是双链表结点
typedef struct
{
char ch;//字符
char code[CodeMaxLen];//字符的编码
}CodeNode;//存储字符的Huffman编码
typedef struct
{
char ch;
HuffmanTree *leaf;
}LeafNode;//临时存储叶子结点的地址
typedef struct
{
char ch;
unsigned long weight;
}OFinal;//最后写入文件的单元
void compress(FILE *,FILE*);//压缩
void decompress(FILE *,FILE*);//解压缩
/*********************统计字符权并编码************************/
RateTabNode *Probability(FILE *);//建立双链表
int IsExisted(RateTabNode *,char);//统计文本中字符个数
int SizeAssure(RateTabNode *);//返回双链表大小,即字符的总个数
HuffmanTree* HTCreate(RateTabNode *);//创建Huffman树
void FindLeaf(RateTabNode *,LeafNode *,int);//找出所有叶子并记录地址
void HFCoding(LeafNode *,CodeNode *,int);//从叶子到根,从下向上的进行编码左0 右1
void buf_init(char (*)[8],int);//缓冲初始化
void wbuffer(FILE *,CodeNode *,char (*)[8],int,int);//