gongshuqin's Blog

Happy coding

Huffman编译码

#include<stdio.h>
#include<malloc.h>
#include<string.h>
#include<stdlib.h>

typedef struct
{
 int weight;
 char ch;
 int parent,lchild,rchild;
}HTNode,*HuffmanTree;

typedef struct
{
 char ch;
 char *chs;
}HuffmanCode;

typedef struct
{

 char ch;
 int weight;
}sw;

typedef struct
{
 HuffmanTree HT;
 HuffmanCode *HC;
}huf;

void select(HTNode * HT,int n,int *n1,int *n2)
{
 int i=1;        
 int n3;
 while(HT[i].parent!=0)         i++;
 *n1=i;
 i++;
 while(HT[i].parent!=0)         i++;
 *n2=i;
 if(HT[*n1].weight<HT[*n2].weight)
 {        
  n3=*n1;
  *n1=*n2;
  *n2=n3;
 }
 for(i++;i<=n;i++)
 {
  if(HT[i].parent==0)
  {        
   if(HT[i].weight<HT[*n1].weight)
    *n1=i;
   else if(HT[i].weight<HT[*n2].weight)
    *n2=i;

  }

 }

}


huf * HuffmanCoding(HuffmanTree HT,HuffmanCode *HC,sw *w,int n,huf *HUF)
{
 int m,i,s1,s2,start,c,f;
 HuffmanTree p;
 char *cd;
 if(n<=1) return 0;
 m=2*n-1;
 HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
 for(p=HT+1,i=1;i<=n;i++,p++,w++)
 {
  p->weight=w->weight;
  p->ch=w->ch;
  p->parent=0;
  p->lchild=0;
  p->rchild=0;
 }
 for(;i<=m;i++,p++)
 {
  p->weight=0;
  p->ch='^';
  p->parent=0;
  p->lchild=0;
  p->rchild=0;
 }
 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));
 cd=(char *)malloc(n*sizeof(char));
 cd[n-1]='\0';
 for(i=1;i<=n;i++)
 { 
  start=n-1;
  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].ch=HT[i].ch;
  HC[i].chs=(char*)malloc((n-start)*sizeof(char));
  strcpy(HC[i].chs,&cd[start]);
  printf("%c %-10s\n",HC[i].ch,HC[i].chs);
 }
 HUF->HT=HT;
 HUF->HC=HC;
 return HUF;
}

char *       convert(char *chars,char *chars1,HuffmanCode *hc,int n)

{
 char *p=chars; int i;
 strcpy(chars1,"");
 while(*p)
 {
  i=1;       
  while(hc[i].ch!=*p&&i<=n)        i++;
  strcat(chars1,hc[i].chs);       
  p++;
 }
 printf("the chars translate are:%s\n",chars1);
 return chars1;
 fflush(stdin);
}

void transcode(HuffmanTree ht,char *chars2,char*chars3)

{
 int i=1,p; char *q=chars2;char *r=chars3;
 while(ht[i].parent!=0)        i++;
 p=i;
 while(*q)
 {
  while(ht[p].lchild!=0 && *q)
  {
   if(*q=='0')
   p=ht[p].lchild;
   else p=ht[p].rchild;
   q++;
  }
  if(ht[p].lchild==0)
  {
   *r=ht[p].ch;
   r++;
  }
  p=i;
 }
 *r='\0';
 printf("the chars are:");
 puts(chars3);
 fflush(stdin);
}

void input(int *n,sw *w)
{
 int i;
 printf("input the amount of char:");   /*输入字符的数目*/
 scanf("%d",n);
 for(i=1;i<=*n;i++,w++)
 {
  printf("input the %dth char and weight:",i); /*输入每个节点的字符和其权值*/
  fflush(stdin);
  scanf("%c%d",&w->ch,&w->weight);
 }
}

void main()
{
 char x;
 HTNode HT;
 HuffmanCode HC,*hc;
 HuffmanTree ht;
 huf *HUF,huf2;
 int n;
 sw w[40];
 char ch,inchar[500],outchar[1000];
 char *abc;
 char *p=inchar;
 printf("下面开始进行Huffman编译码:\n");
 input(&n,w);
 HUF=HuffmanCoding(&HT,&HC,w,n,&huf2);
 printf("input chars to translate and end with '#':");
 fflush(stdin);/*清除流,解决输入干扰*/
 ch=getchar();
 while(ch!='#')
 {
  *p=ch;
  p++;
  ch=getchar();
 }
 *p='\0';
 hc=HUF->HC;
 ht=HUF->HT;
 abc=convert(inchar,outchar,hc,n);
 transcode(ht,abc,outchar);
 getchar();
 fflush(stdin);
 printf("Do you want to try again?(y/n)");
 x=getchar();
 while(x=='y'){
  input(&n,w);
  HUF=HuffmanCoding(&HT,&HC,w,n,&huf2);
  printf("input chars to translate and end with '#':");
  fflush(stdin);/*清除流,解决输入干扰*/
  ch=getchar();
  while(ch!='#')
  {
   *p=ch;
   p++;
   ch=getchar();
  }
  *p='\0';
  hc=HUF->HC;
  ht=HUF->HT;
  abc=convert(inchar,outchar,hc,n);
  transcode(ht,abc,outchar);
  fflush(stdin);
  getchar();
  fflush(stdin);
  printf("Do you want to try again?(y/n)");
  x=getchar();
 }
 while(x=='n') break;
 getchar();
}

用栈实现表达式求值

#define STACK_INIT_SIZE  100
#define STACKINCREMENT   10
#include"stdio.h"
#include"stdlib.h"

typedef struct SqStack                //栈的顺序存储结构
{
  double *base;
  double *top;
  int stacksize;
}SqStack;

void InitStack (SqStack &S)           //构造一个空栈
{
  S.base=(double *)malloc(STACK_INIT_SIZE*sizeof(double));              //分配储存空间
  if(!S.base) exit (-1);                                                      //空间分配失败
  S.top=S.base;
  S.stacksize=STACK_INIT_SIZE;                                                //空间初始分配
}//InitStack

bool GetTop (SqStack S,double  &e)
{                         //若栈不空,则用e返回S的栈顶元素,并返回true;否则返回false
  if(S.top==S.base)
   return false;
  e=*(S.top-1);
  return true;
}//GetTop

bool Push(SqStack &S,double e)
{                        //插入元素为e的新的栈顶元素
  if(S.top-S.base>=S.stacksize)
  {                       //栈满,追加存储空间
    S.base=(double*)realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof(double));
     if(!S.base)  
   exit(-1);            //存储空间分配失败
     S.top=S.base+S.stacksize;                       //此处内存有可能重新分配,S.base地址有可能会变,此句不能省
     S.stacksize+=STACKINCREMENT;
  }
  *S.top++=e;               //top自增
  return true;
}// Push

bool  Pop(SqStack &S,double &e)                  //若栈不空,则删除S的栈顶元素,用e返回其值
{
  if(S.top==S.base)
   return false;
  e=*--S.top;                      //删除一个元素,top减一
  return true ;
}// Pop

char Precede(char a1 ,char a2)//判定运算符的优先级。
{       
  char r;
  switch(a2)
  {
    case'+':      //此处由于加减几乎优先级一样,故放在一起
    case'-':
     if(a1=='('||a1=='#')
   r='<';
     else
   r='>';
     break;
    case'*':      //此处由于乘除优先级一样,故放在一起
    case'/':
     if(a1=='*'||a1=='/'||a1==')')
   r='>';
     else
   r='<';
     break;
    case'(':
     if(a1==')')
     {
    printf("括号匹配错误!\n");
    exit(-1);
     }
     else
   r='<';
     break;
    case')':
     if(a1=='(')
   r='=';
     else if(a1=='#')
     {
    printf("eeror!没有左括号\n");
    exit (-1);
     }
     else
   r='>';
     break;
    case'#':
     switch(a1)
     {
      case'#':
    r='=';
     break;
      case'(':
    printf("eeror!没有右括号\n");
    exit(-1);
      default:
    r='>';
     }//switch
     break;
  }//switch
  return r;
}//Precede


bool In(char d)                   //判断c是否为七种运算符之一
{
  switch(d)
  {
   case'+':
   case'-':
   case'*':
   case'/':
   case'(':
   case')':
   case'#':
    return true;
   default:
    return false;
  }//switch
}
 

double Operate( double a,  double theta, double b )       //Operate为进行二元运算的a theta b的函数
{
  char n=char(theta);             //此处把double型强制转换成int型,虽然会造成精度缺失,但本身theta是一个符号,也算是整型
  switch(n)                       //转换后相当于和符号匹配ACSII码
  {
   case'+':
    return a+b;
   case'-':
    return a-b;
   case'*':
    return a*b;
     default:
    if(b!=0)
     return a/b;
    else
    {
    printf("error!除数不能为零\n");
    exit(-1);
    } 
  }//switch
}
 


double EvaluateExpression()
{       //算符表达式的优先算法。设OPTR和OPND分别为运算符栈和运算数栈
  SqStack OPTR,OPND;
  char  c;
  char Data[11];                     //定义此数组为了存放整数或小数
  double a,b,d,e;
  InitStack(OPTR);                   //构造一个运算符栈
  InitStack(OPND);                   //构造一个运算数栈
  Push(OPTR,'#');                    //将#压入栈底
  c=getchar();
  GetTop(OPTR,e);
  while(c!='#'||e!='#')              //栈顶不是#号且输入不是#号
  {
    if(In(c))//是符号则进栈
    {
      switch(Precede(e,c))
      {
       case'<':   //栈顶元素优先级低
     Push(OPTR,c);
     c=getchar();
     break;
       case'=':    //脱括号并接受下一字符
     Pop(OPTR,e);
     c=getchar();
     break;
       case'>':    //退栈并将运算结果入栈
     Pop(OPTR,e);
     Pop(OPND,b);
     Pop(OPND,a);
     Push(OPND,Operate(a,e,b));
     break;
      }//switch
    }
       else if(c>='0'&&c<='9'||c=='.')
    {
    int i=0;
    while(c>='0'&&c<='9'||c=='.')
    {
     Data[i]=c;
     i++;
     c=getchar();
    }
    Data[i]='\0';                      //数字没有存满,输入字符串结束符
    d=atof(Data);                      //此处是把数组里的数字,实际上是按字符串;转换为double类型,然后把浮点型数字入栈
    Push(OPND,d);                      //atof函数的形参是指针类型,故用数组名
    }
    else
    {
     printf("error!输入错误!\n");
     exit(-1);
    }
       GetTop(OPTR,e);
  }//while
  GetTop(OPND,e);
  return e;
}//EvaluateExpression
 

main()
{
  char ch;
  double  result;
  printf("请输入表达式,以#号结束\n");
  result=EvaluateExpression();
  printf("结果为%f:\n",result);
  printf("您想再试一次吗?如果想,请输入'Y';否则输入'N'\n");
  fflush (stdin);
  ch=getchar();
  while(ch=='Y'||ch=='y'){
   printf("请输入表达式,以#号结束\n");
   fflush (stdin);
   result=EvaluateExpression();
   printf("结果为%f:\n",result);
   fflush (stdin);
  }
}