⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xixibmdlg.cpp

📁 香农编码
💻 CPP
📖 第 1 页 / 共 2 页
字号:

void CXixibmDlg::Onhelp() 
{
	// TODO: Add your control notification handler code here
	MessageBox("      在第一列输入消息概率!\n        :)\n点击自动分配可以自动填写信源概率!\n\n若手动填写请先点击清空或者编码按钮\n\n使信源符号按序排列!!");
}

void CXixibmDlg::OnOK() 
{
	// TODO: Add extra validation here
	
	CDialog::OnCancel();
	MessageBox("谢谢您的使用!愿你每天都有好的心情!:)");
}

/////////////////////////////////////////////////////////////////
void CXixibmDlg::paixu()////////////////******排序*********
{  
   for(int j=0;j<7;j++)
   {
	for(int i=0;i<7;i++)
   {
	   if (ay[i]<ay[i+1])
	   { 
		   ay[7]=ay[i];ay[i]=ay[i+1];ay[i+1]=ay[7];
           no[7]=no[i];no[i]=no[i+1];no[i+1]=no[7];//信源符号排序
	   }	  
   }
   }
   m1=no[0];m2=no[1];m3=no[2];m4=no[3];m5=no[4];m6=no[5];m7=no[6];
   a1=ay[0];a2=ay[1];a3=ay[2];a4=ay[3];a5=ay[4];a6=ay[5];a7=ay[6];
     UpdateData(false);
}

void CXixibmDlg::duishu()//求对数
{
  for(int i=0;i<=6;i++)
  {
   by[i]=-log(ay[i])/log(2);
  }

  b1=by[0];b2=by[1];b3=by[2];b4=by[3];b5=by[4];b6=by[5];b7=by[6];
    UpdateData(false);
}

void CXixibmDlg::Onaboutme() 
{
	// TODO: Add your control notification handler code here
	MessageBox("        作者:赵俭        \n\n      中国地质大学\n\n 信息工程学院通信四班\n\n 欢迎访问我的个人博客:\n\nHttp://hi.baidu.com/zjjs\n\n思想有多远,我们就能走多远!");
}

void CXixibmDlg::machang()   ///求各码长
{
  for(int i=0;i<=6;i++)
  {
	  double cc=by[i];
	  if (cc-int(by[i])==0) 
	  {
		  cy[i]=int(by[i]);
	  }
	  else
	  cy[i]=int(by[i])+1;
  }
  c1=cy[0];c2=cy[1];c3=cy[2];c4=cy[3];c5=cy[4];c6=cy[5];c7=cy[6];
    UpdateData(false);
}

void CXixibmDlg::ljgl()   //求香农编码的累加概率
{   dy[0]=0;
 	dy[1]=a1;
  dy[2]=dy[1]+a2;
  dy[3]=dy[2]+a3;
  dy[4]=dy[3]+a4;
  dy[5]=dy[4]+a5;
  dy[6]=dy[5]+a6;
  d1=dy[0];d2=dy[1];d3=dy[2];d4=dy[3];d5=dy[4];d6=dy[5];d7=dy[6];
    UpdateData(false);
}
///////////////////////////////////////////////////////////////////////
//////////////**************香农编码**************
void CXixibmDlg::bianma()
{   ////编码之前清空码字
	ey[0]=_T("");ey[1]=_T("");ey[2]=_T("");ey[3]=_T("");ey[4]=_T("");ey[5]=_T("");ey[6]=_T("");    
   double temp(0);
   for(int a=0;a<=6;a++)
   {
	   tbm[a]=dy[a];
   }
    for(int j=0;j<=6;j++)
	{
	for(int i=0;i<cy[j];i++)//cy[j]为码长
	{
		temp=tbm[j]*2.0;
		if (temp>=1.0)
		{//如果乘2的结果大于1,则编码为1
			ey[j]=ey[j]+"1";
			tbm[j]=temp-1.0;//去整取余
		}
		else
		{
			ey[j]=ey[j]+"0";
			tbm[j]=temp;
		}
	}
	}
	e1=ey[0];e2=ey[1];e3=ey[2];e4=ey[3];e5=ey[4];e6=ey[5];e7=ey[6];
	  UpdateData(false);
}

void CXixibmDlg::bmxl()    //求编码效率及平均码长
{
  double tem1(0.0),tem2(0.0);
  for(int i=0;i<=6;i++)
  {
	  tem1=tem1+ay[i]*by[i]; 
	  tem2=tem2+ay[i]*cy[i];
  }
  
  xl=tem1/tem2; 
  mc=tem2;
  xys=tem1;
  
    UpdateData(false);
}

void CXixibmDlg::feixiaolv()    //求费诺编码效率及平均码长
{double fnmc(0.0);double tem1(0.0);
 for(int i=0;i<=6;i++)
  {
	  tem1=tem1+ay[i]*by[i]; 
	  fnmc=fnmc+ay[i]*js[i];
  }
 mcfn=fnmc;
  xlfn=tem1/fnmc;
UpdateData(false);
}
//////////////////////////////////////////////////////////////////////////
//**************费诺编码********************
int CXixibmDlg::feinuobianma(int low,int high)
{
   int m=low,n=high;
   if(m==n)	return 1;
    else 
		if(m+1==n)
	{ //gy[m]为码字//// js[m]为码长
	   gy[m]=gy[m]+"0";js[m]=js[m]+1;
	   gy[n]=gy[n]+"1";js[n]=js[n]+1;
	   return 1;
    }
    else
	{/////////寻找分割点///////////
       double sum0=0,sum1=0,sum2=0;
       for(int i=m;i<=n;i++)  sum0+=ay[i];  
   do{
         sum1+=ay[m];
         sum2=sum1+ay[m+1];
         m++;
	 }while(pd(sum1/sum0-0.5)>pd(sum2/sum0-0.5));
     for(i=low;i<m;i++) 
	 {gy[i]=gy[i]+"0";js[i]=js[i]+1;}//m以上的赋0
     for(i=m;i<=n;i++)  
	 {gy[i]=gy[i]+"1";js[i]=js[i]+1;}//m以下的赋1
	}
	feinuobianma(low,m-1);/////
	feinuobianma(m,high);//////递归调用
	return 1;
}

double CXixibmDlg::pd(double f)
{return(f>=0?f:-f);}

void CXixibmDlg::diaoyong()////////调用费诺编码函数
{
	for (int m=0;m<=7;m++) gy[m]=_T("");
	for(int i=0;i<=6;i++) js[i]=0;
 feinuobianma(0,6);
g1=gy[0];g2=gy[1];g3=gy[2];g4=gy[3];g5=gy[4];g6=gy[5];g7=gy[6];
f1=js[0];f2=js[1];f3=js[2];f4=js[3];f5=js[4];f6=js[5];f7=js[6];
  UpdateData(false);
}

void CXixibmDlg::Onfeipei() //////////
/////**************产生随机数据**********
{
	// TODO: Add your control notification handler code here
    double ayy[7];int byy[7];double tem2(0.0),qi(0.0),qi1(0.0);
	srand((unsigned int)time((time_t *)NULL));//种子
	for(int i=0;i<=5;i++)
	{
	  byy[i]=10+rand()%90;//产生随机数
	}
	double sum8(0.0);///用来存储产生的6个随机数的总和
	for(int j=0;j<=5;j++)
	{	
		sum8=sum8+byy[j];
    	ayy[j]=byy[j];
	}
	for(int k=0;k<=5;k++)
	{	
		ayy[k]=int((ayy[k]/(sum8+150))*100);//总和加50,每位随机数除它们的总和
	    ayy[k]=ayy[k]/100;///////////////////保留两位有效数字
		tem2=tem2+ayy[k];
	}
	qi=1-tem2;qi1=int(qi*100);qi1=qi1/100;//处理第七位数
	if (qi-qi1>=0.005)///去尾巴
	{
		qi1=qi1+0.01;
	}
	else
	{	qi1=qi1;}
   a1=ayy[0];a2=ayy[1];a3=ayy[2];a4=ayy[3];a5=ayy[4];a6=ayy[5];//先产生六个随机数
   a7=qi1;/////////////////////////////////////////第七个通过计算而得,保证七个随机数总和为1
   m1=1;m2=2;m3=3;m4=4;m5=5;m6=6;m7=7;
	UpdateData(false);
}

void CXixibmDlg::clear()
{
    a1=a2=a3=a4=a5=a6=a7=0;
	b1=b2=b3=b4=b5=b6=b7=0;
	c1=c2=c3=c4=c5=c6=c7=0;
	d1=d2=d3=d4=d5=d6=d7=0;
	f1=f2=f3=f4=f5=f6=f7=0;
	h1=h2=h3=h4=h5=h6=h7=0;
	xys=0.0;mc=0.0;xl=0.0;
	xlfn=0.0;mcfn=0.0;
	xlhfm=0.0;mchfm=0.0;
	m1=1;m2=2;m3=3;m4=4;m5=5;m6=6;m7=7;
	e1=_T("");e2=_T("");e3=_T("");e4=_T("");e5=_T("");e6=_T("");e7=_T("");
    g1=_T("");g2=_T("");g3=_T("");g4=_T("");g5=_T("");g6=_T("");g7=_T("");
	i1=_T("");i2=_T("");i3=_T("");i4=_T("");i5=_T("");i6=_T("");i7=_T("");
	for(int i=0;i<=6;i++) js[i]=0;
	  UpdateData(false);
}

void CXixibmDlg::dyhuffman()//调用哈夫曼
{
  for (int m=0;m<7;m++) iy[m]=_T("");
  for(int i=0;i<=6;i++) hy[i]=0;
  huffman();//哈夫曼编码
  i1=iy[0];i2=iy[1];i3=iy[2];i4=iy[3];i5=iy[4];i6=iy[5];i7=iy[6];
  h1=hy[0];h2=hy[1];h3=hy[2];h4=hy[3];h5=hy[4];h6=hy[5];h7=hy[6];
  UpdateData(false);
}

void CXixibmDlg::hfmmc()///////计算哈夫曼平均码长和编码效率//////
{ 
	double temp(0.0),temp2(0.0);
  for(int i=0;i<=6;i++)
  {
	  temp=temp+ay[i]*by[i];
	  temp2=temp2+ay[i]*hy[i];
  }
   mchfm=temp2;//码长
   xlhfm=temp/temp2;//效率
   UpdateData(false);
}
////////////*********哈夫曼编码**********
void CXixibmDlg::huffman()
{
  class   Sarray   Array[7];         //这个数组保存了7个原始数据的输入     
  double   temp=0;                               
  double   total=0;                           //该变量用来记录每两个信号合成后,新节点(信号)的发生概率     
  int   i,j,k;                  //中间计数器     
  char ff=NULL;      //二叉树遍历函数     
  for(i=0;i<7;i++)                                                           
  {   
    temp=ay[i];    
    Array[i].symbol[0]='a';     //该信号命名为ai     
    Array[i].symbol[1]=(char)i;   
    Array[i].prb=temp;                                      //发生概率为刚才输入的数值     
    total+=temp;                                             //在这里total用来统计所有信号发生概率之和是否等于1     
    temp=0;                                           //为确保不影响后面的数据输入,这里temp置0                    
    }     
     char   t_symbol[2];   
    for(i=0;i<6;i++)                               //以下是冒泡排序过程     
    for(j=i+1;j<7;j++)   
  {   
      if(Array[i].prb<Array[j].prb)   
  {   
      temp=Array[i].prb;   
      t_symbol[0]=Array[i].symbol[0];   
      t_symbol[1]=Array[i].symbol[1];       
      Array[i].prb=Array[j].prb;   
      Array[i].symbol[0]=Array[j].symbol[0];   
      Array[i].symbol[1]=Array[j].symbol[1];   
      Array[j].symbol[0]=t_symbol[0];   
      Array[j].symbol[1]=t_symbol[1];   
      Array[j].prb=temp;   
      }   
    }   
    Node   *p;   
    for(i=0;i<7;i++)       //输出各个信号的概率,并为它们分配(在二叉树中的)存储空间     
  {         
     p=(Node   *)malloc(sizeof(Node));   
     Array[i].addr=p;   
     p->left=NULL;   
     p->right=NULL;   
     p->symbol[0]='a';   
     p->symbol[1]=(char)i;   	
  }
     temp=0.0;   
     int   time=0;       //该变量用来记录Huffman过程进行的次数     
     total=0.0;         //重置                     
     Node   *pleft,*pright;         
     while(total<1.0)             //当概率和小雨1时,Huffman就还可以继续     
     {   
        total=Array[6-time].prb+Array[6-time-1].prb;     //概率相加,新节点的概率等于它们的和                       
        pleft=Array[6-time-1].addr;           //新节点的左孩子为概率较大的节点     
        pright=Array[6-time].addr;             //新节点的右孩子为概率较小的节点     
        j=0;   
        Array[6-time].prb=0;                         //产生新节点前,先在Array[]中将相应信号的概率置0     
        Array[6-time-1].prb=0;   
        while(total<Array[j].prb)     { j++;}              //找出新节点在Array[]中的合适位置(排序)        
        if(j<(6-time-1))                       //如果合适的位置不在最后,则     
		{   
          for(k=6-time-2;k>=j;k--)       //从这里起,后面所有的信号都要依次后挪     
		  {                 
			  Array[k+1].symbol[0]=Array[k].symbol[0];   
			  Array[k+1].symbol[1]=Array[k].symbol[1];   
			  Array[k+1].prb=Array[k].prb;   
              Array[k+1].addr=Array[k].addr;   
		  }   
		}                               
             Array[j].symbol[1]=(char)time;           //新节点的标识为Q0,Q1,Q2...,下标也就是Huffman过程的次数     
             Array[j].symbol[0]='Q';   
             p=(Node   *)malloc(sizeof(Node));     //为新节点分配存储空间     
             Array[j].addr=p;         //把这个地址填充到Array[]当中     
             Array[j].prb=total;           //新节点的概率为两个信号概率之和     
             p->left=pleft;             //左指针,即左孩子的地址     
             p->right=pright;         //右指针     
             p->symbol[0]=Array[j].symbol[0];       //把新节点的标识填到二叉树当中     
             p->symbol[1]=Array[j].symbol[1];               
             time++;                 //Huffman过程的次数加一                                                            
    }       
       p=Array[0].addr;       //头指针(根节点的地址)置为数组第一个元素的指针     
       Traverse(p,-1);         //遍历二叉树   ,传入二叉树头节点的指针                             
       CString strtemp;
       for(i=0;i<7;i++)    //输出原始信号的Huffman编码码值    
      {   
         for(j=0;j<=result[i].length;j++)     
		{	
	    	strtemp=("%s",result[i].path[j]);
			iy[i] = iy[i] + strtemp;//结果输出
		}
			strtemp =_T("");
          hy[i]=result[i].length+1;//码长输出
      }   												
 }   

 void  CXixibmDlg:: Traverse(Node   *T,int   step)         //step记录了到达该节点时,该节点的深度(处于二叉树中的第几层)     
  {                                                                                   //这个层数也就是该节点Huffman编码码值的长度     
    static   char   dpath[7];                                 //该数组记录了从头节点一路走来碰到的所有"1"和"0",也就是Huffman编码码值   
    static   int   value;                                         //value用来提取叶子节点标识当中的数字下标,如'a1'中的'1'     
    if(T->left!=NULL)                                         //如果左指针不为空,即下面还有孩子,则     
   {   
      step++;                         //步长递增     
      dpath[step]='1';                  //进入左孩子之前,左边置1     
      Traverse(T->left,step);           //搜寻左子树     
      dpath[step]='0';                    //此时已经从左子树返回了,将进入右子树,所以右边置0     
      Traverse(T->right,step);          //搜寻右子树     
	  step--;                           //此时可以从该节点返回了,所以步长递减     
   }   
     else   
	{                                           //如果它下面没有孩子了,即它是叶子节点,则     
      value=T->symbol[1];                       //提取下标,因为所有的原始信号都在叶子节点,且只有原始信号在叶子节点上     
      result[value].symbol[0]=T->symbol[0];       //按下标把该叶子节点的标识拷贝到输出表中     
      result[value].symbol[1]=T->symbol[1];   
      result[value].length=step;                             //信号的Huffman编码码值长度等于步长    
	  for(int   j=0;j<=step;j++)                                   //拷贝码值          
      result[value].path[j]=dpath[j];   	                                
     }              
 }           






⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -