USTC机试——根据浮点数序列输出数列的huffuman编码

思想:1:huffuman并不唯一(完整代码在最低端)
          2:利用<queue>头文件中的priority_queue队列实现结点的存储,优先队列是实现自动调整结点顺序的一种数据结构,由于我在结构体中重载的小于符号是根据其数值排序,故可以实现从小到大的自动排序。

          3:每个树的结点的结构体如下:

struct Node{
   struct Node *lchild;
   struct Node *rchild;
   double d;//存储这个结点对应的数值
   bool operator <(const Node &A)const{//重载小于符号方便优先队列调用
      return d<A.d;
   }
   char tab[N];//每个结点附加一个huffuman编码
}Tree[N];
         4:利用小顶堆形式的优先队列存储上述结点:
priority_queue <Node*, vector<Node*>,  greater<Node*> > q;

   5:求解思想:先根据文件中的数字序列建立一棵完整的树,建立完整的树后利用遍厉到叶节点输出huffuman编码(huffuman编码的构建在遍历的过程确定)
    根据两个节点建立一棵树的方法:
Node *setTree(Node *a,Node *b){//根据两个结点构建一颗树
     Node *temp1=create();//静态获取一个结点的方法,完整代码中此方法的定义
     temp1->d=a->d+b->d;
	 temp1->lchild=a;
	 temp1->rchild=b;
	 return temp1;
}

    根据优先队列建立一棵完整的树:思想:反复的从队列中取出两个最小节点,利用上面setTree方法建立一棵树并且再把树的根节点压入优先队列中,如此往复,当优先队列中只有一个元素时就是建立好树的根节点
 Node *t1,*t2,*T;
   while(q.size()>1){//在优先队列中创建一课完整的树
       t1=q.top();
	   q.pop();
	   t2=q.top();
	   q.pop();
	   T=setTree(t1,t2);
	   q.push(T);
   }
   T=q.top();//最后队列中剩下的是根节点

      在建立完一棵huffuman树后,遍历该树时建立每个结点的huffuman编码,思想:T结点的左孩子huffuman编码等于T结点的编码链接上'0',T结点的右孩子huffuman编码等于T结点的编码链接上'1';
void Huffuman(Node *T){//注解,huffuman树并不唯一所以此处多思考一下
	if(T->lchild!=NULL){strcpy(T->lchild->tab,T->tab);strcat(T->lchild->tab,"0");Huffuman(T->lchild);}
	if(T->rchild!=NULL){strcpy(T->rchild->tab,T->tab);strcat(T->rchild->tab,"1");Huffuman(T->rchild);}
	if(T->lchild==NULL&&T->rchild==NULL){
		fprintf(fp2,"%lf %s\n",T->d,T->tab);//输出Huffuman编码
	}
}


完整代码如下:

#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
#define N 100 

struct Node{
   struct Node *lchild;
   struct Node *rchild;
   double d;
   bool operator <(const Node &A)const{//重载小于符号方便优先队列调用
      return d<A.d;
   }
   char tab[N];//每个结点附加一个huffuman编码
}Tree[N];

priority_queue <Node*, vector<Node*>,  greater<Node*> > q;//优先队列,此处有一注意事项即把最后一个>前的空格不可省略
int loc=0;
Node *create(){//静态分配一个结点
     Tree[loc].lchild=Tree[loc].rchild=NULL;
	 memset(Tree[loc].tab,0,sizeof(Tree[loc].tab));
	 return &Tree[loc++];
}

Node *setTree(Node *a,Node *b){//根据两个结点构建一颗树
     Node *temp1=create();
     temp1->d=a->d+b->d;
	 temp1->lchild=a;
	 temp1->rchild=b;
	 return temp1;
}


FILE *fp1,*fp2;
void Huffuman(Node *T){//注解,huffuman树并不唯一所以此处多思考一下
	if(T->lchild!=NULL){strcpy(T->lchild->tab,T->tab);strcat(T->lchild->tab,"0");Huffuman(T->lchild);}
	if(T->rchild!=NULL){strcpy(T->rchild->tab,T->tab);strcat(T->rchild->tab,"1");Huffuman(T->rchild);}
	if(T->lchild==NULL&&T->rchild==NULL){
		fprintf(fp2,"%lf %s\n",T->d,T->tab);//输出Huffuman编码
	}
}
int main(){//利用优先队列取两个节点创建树节点再放回去,往复循环创建一颗完整的树
   fp1=fopen("7.in","r");
   fp2=fopen("7.out","w");
   while(!feof(fp1)){//将结点压入栈中
      Node *T=create();
	  fscanf(fp1,"%lf",&T->d);//双精度数字格式
      q.push(T);
   }

   Node *t1,*t2,*T;
   while(q.size()>1){//在优先队列中创建一课完整的树
       t1=q.top();
	   q.pop();
	   t2=q.top();
	   q.pop();
	   T=setTree(t1,t2);
	   q.push(T);
   }
   T=q.top();//最后队列中剩下的是根节点
   Huffuman(T);
   return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值