栈的应用

 1、数制转换
         十进制数N和其他d进制数的转换。
         原理:N=(N div d)*d+N mod d (其中:div为整除运算,mod为求余运算)
         具体例题:
         对于输入的任意一个非负十进制整数,打印输出与其等值的八进制数。
         思想:
         在计算过程中,是从低位到高位的顺序产生八进制数的各个位数,而打印输出则是从高位到低位进行,恰好与计算过程相反。在这个例子里,利用栈的后进先出特性,且操作的顺序直线式的,即先一味地进栈,再一味地出栈。
         算法:
 void conversion(  ) {
       initstack(s);
        scanf (“%”,n);
        while(n){
             push(s,n%8);
             n=n/8;
         }
         while(! Stackempty(s)){
            pop(s,e);
            printf(“%d”,e);
          }
        }

具体代码实现(C)
 #include<string.h>
#include<ctype.h>
#include<malloc.h> /* malloc()等 */
#include<stdio.h> /* EOF(=^Z或F6),NULL */
#include<process.h> /* exit() */

#define STACK_INIT_SIZE 10 /* 存储空间初始分配量 */
#define STACKINCREMENT 2 /* 存储空间分配增量 */
typedef struct SqStack
{
   int *base; /* 在栈构造之前和销毁之后,base的值为NULL */
   int *top; /* 栈顶指针 */
   int stacksize; /* 当前已分配的存储空间,以元素为单位 */
}SqStack; /* 顺序栈 */

int InitStack(SqStack *S)
{ /* 构造一个空栈S */
   (*S).base=(int *)malloc(STACK_INIT_SIZE*sizeof(int));
   if(!(*S).base)
     exit(-2); /* 存储分配失败 */
   (*S).top=(*S).base;
   (*S).stacksize=STACK_INIT_SIZE;
   return 1;
}

int StackEmpty(SqStack S)
{ /* 若栈S为空栈,则返回TRUE,否则返回FALSE */
   if(S.top==S.base)
     return 1;
   else
     return 0;
}

int Push(SqStack *S,int e)
{ /* 插入元素e为新的栈顶元素 */
   if((*S).top-(*S).base>=(*S).stacksize) /* 栈满,追加存储空间 */
   {
     (*S).base=(int *)realloc((*S).base,((*S).stacksize+STACKINCREMENT)*sizeof(int));
     if(!(*S).base)
       exit(-2); /* 存储分配失败 */
     (*S).top=(*S).base+(*S).stacksize;
     (*S).stacksize+=STACKINCREMENT;
   }
   *((*S).top)++=e;
   return 1;
}

int Pop(SqStack *S,int *e)
{ /* 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR */
   if((*S).top==(*S).base)
     return 0;
   *e=*--(*S).top;
   return 1;
}

void conversion()
{ /* 对于输入的任意一个非负十进制整数,打印输出与其等值的八进制数 */
   SqStack s;
   unsigned n; /* 非负整数 */
   int e;
   InitStack(&s); /* 初始化栈 */
   printf("n(>=0)=");
   scanf("%u",&n); /* 输入非负十进制整数n */
   while(n) /* 当n不等于0 */
   {
     Push(&s,n%8); /* 入栈n除以8的余数(8进制的低位) */
     n=n/8;
   }
   while(!StackEmpty(s)) /* 当栈不空 */
   {
     Pop(&s,&e); /* 弹出栈顶元素且赋值给e */
     printf("%d",e); /* 输出e */
   }
   printf("\n");
}

void main()
{
   conversion();
}

2、括号匹配的检验
    假设表达式中允许包含两种括号:圆括号和方括号,其嵌套的顺序随意,即([]())或[([][])]等为正确的格式,[(])或([())均为不正确的格式。
    原理: 设置一个栈,每读入一个括号,若是右括号,则或者使置于栈顶的最急迫的期待得以消解,或者是不合法的情况;若是左括号,则作为一个新的更急迫的期待压入栈中,自然使原有的在栈中的所有未消解的期待的急迫性都降一级。算法开始和结束时,栈都应该是空的。
  算法:
void check(){
     if(InitStack(S))
     {
        gets(ch);
        p=ch;
        while(*p)
          switch(*p)
          {
             case '(':
             case '[':Push(S,*p++);break;
             case ')':
             case ']':if(!StackEmpty(S))
                      {
                         Pop(S,e);
                         if(*p==')'&&e!='('||*p==']'&&e!='[')
                            exit(ERROR);
                         else {p++;break;}
                       }
                       else  exit(ERROR);
            default : p++;
           }
      }

   具体代码的实现(C):
 #include<string.h>
#include<ctype.h>
#include<malloc.h> /* malloc()等 */
#include<stdio.h> /* EOF(=^Z或F6),NULL */
#include<stdlib.h> /* atoi() */
#include<process.h> /* exit() */
#define STACK_INIT_SIZE 10 /* 存储空间初始分配量 */
#define STACKINCREMENT 2 /* 存储空间分配增量 */
typedef struct SqStack
{
   char *base; /* 在栈构造之前和销毁之后,base的值为NULL */
   char *top; /* 栈顶指针 */
   int stacksize; /* 当前已分配的存储空间,以元素为单位 */
}SqStack; /* 顺序栈 */

int InitStack(SqStack *S)
{ /* 构造一个空栈S */
   (*S).base=(char *)malloc(STACK_INIT_SIZE*sizeof(char));
   if(!(*S).base)
     exit(-2); /* 存储分配失败 */
   (*S).top=(*S).base;
   (*S).stacksize=STACK_INIT_SIZE;
   return 1;
}

int StackEmpty(SqStack S)
{ /* 若栈S为空栈,则返回1,否则返回0 */
   if(S.top==S.base)
     return 1;
   else
     return 0;
}

int Push(SqStack *S,char e)
{ /* 插入元素e为新的栈顶元素 */
   if((*S).top-(*S).base>=(*S).stacksize) /* 栈满,追加存储空间 */
   {
     (*S).base=(char *)realloc((*S).base,((*S).stacksize+STACKINCREMENT)*sizeof(char));
     if(!(*S).base)
       exit(-2); /* 存储分配失败 */
     (*S).top=(*S).base+(*S).stacksize;
     (*S).stacksize+=STACKINCREMENT;
   }
   *((*S).top)++=e;
   return 1;
}

int Pop(SqStack *S,char *e)
{ /* 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR */
   if((*S).top==(*S).base)
     return 0;
   *e=*--(*S).top;
   return 1;
}

void check()
{ /* 对于输入的任意一个字符串,检验括号是否配对 */
   SqStack s;
   char ch[80],*p,e;
   if(InitStack(&s)) /* 初始化栈成功 */
   {
     printf("请输入表达式\n");
     gets(ch);
     p=ch;
     while(*p) /* 没到串尾 */
       switch(*p)
       {
         case '(':
         case '[':Push(&s,*p++);
                  break; /* 左括号入栈,且p++ */
         case ')':
         case ']':if(!StackEmpty(s)) /* 栈不空 */
                  {
                    Pop(&s,&e); /* 弹出栈顶元素 */
                    if(*p==')'&&e!='('||*p==']'&&e!='[') /* 弹出的栈顶元素与*p不配对 */
                    {
                      printf("左右括号不配对\n");
                      exit(0);
                    }
                    else
                    {
                      p++;
                      break; /* 跳出switch语句 */
                    }
                  }
                  else /* 栈空 */
                  {
                    printf("缺乏左括号\n");
                    exit(0);
                  }
         default: p++; /* 其它字符不处理,指针向后移 */
       }
       if(StackEmpty(s)) /* 字符串结束时栈空 */
         printf("括号匹配\n");
       else
         printf("缺乏右括号\n");
   }
}

void main()
{
   check();
}

3、行编辑
      简单的行编辑程序的功能是:接受用户从终端输入的程序或数据,为了能发现错误并及时改正,再设立一个数据缓冲区,用以接受用户输入的一行字符,然后逐行存入用户数据区。
     具体例题:当用户发现刚刚键入的一个字符是错误的时,可以补进一个退格符“#”,以表示前面的一个字符无效,若发现当前键入的行内差错较多或难以补救时,则可以键入一个退行符“@”,以表示当前行中的字符均无效。
           eg:whli##ilr#e(s#*s)
                      outcha@putchar(*s=#++)
               则实际有效的是下列两行
                  while(* s)
                      putchar(*s++);
     算法:
 void lineedit( )
         {  initstack(s);
            ch=getchar( );
            while(ch!=eof)
           { while(ch!=eof && ch!=‘\n’)
                 {  switch(ch)
                          {    case ‘#’ : pop(s,c);
                               case ‘@’ : clearstack(s);
                               default : push(s,ch); 
                          }
                     ch=getchar( );
                 }
             clearstack(s);
             if(ch!=eof)
                  ch=getchar( );
           }
           destroystack(s);
   }

   具体代码的实现(C):
#include<string.h>
#include<ctype.h>
#include<malloc.h> /* malloc()等 */
#include<limits.h> /* INT_MAX等 */
#include<stdio.h> /* EOF(=^Z或F6),NULL */
#include<stdlib.h> /* atoi() */
#include<io.h> /* eof() */
#include<math.h> /* floor(),ceil(),abs() */
#include<process.h> /* exit() */
FILE *fp;
#define STACK_INIT_SIZE 10 /* 存储空间初始分配量 */
#define STACKINCREMENT 2 /* 存储空间分配增量 */
typedef struct SqStack
{
   char *base; /* 在栈构造之前和销毁之后,base的值为NULL */
   char *top; /* 栈顶指针 */
   int stacksize; /* 当前已分配的存储空间,以元素为单位 */
}SqStack; /* 顺序栈 */

int InitStack(SqStack *S)
{ /* 构造一个空栈S */
   (*S).base=(char *)malloc(STACK_INIT_SIZE*sizeof(char));
   if(!(*S).base)
     exit(-2); /* 存储分配失败 */
   (*S).top=(*S).base;
   (*S).stacksize=STACK_INIT_SIZE;
   return 1;
}

int DestroyStack(SqStack *S)
{ /* 销毁栈S,S不再存在 */
   free((*S).base);
   (*S).base=NULL;
   (*S).top=NULL;
   (*S).stacksize=0;
   return 1;
}

int ClearStack(SqStack *S)
{ /* 把S置为空栈 */
   (*S).top=(*S).base;
   return 1;
}

int StackEmpty(SqStack S)
{ /* 若栈S为空栈,则返回TRUE,否则返回FALSE */
   if(S.top==S.base)
     return 1;
   else
     return 0;
}


int GetTop(SqStack S,char *e)
{ /* 若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR */
   if(S.top>S.base)
   {
     *e=*(S.top-1);
     return 1;
   }
   else
     return 0;
}

int Push(SqStack *S,char e)
{ /* 插入元素e为新的栈顶元素 */
   if((*S).top-(*S).base>=(*S).stacksize) /* 栈满,追加存储空间 */
   {
     (*S).base=(char *)realloc((*S).base,((*S).stacksize+STACKINCREMENT)*sizeof(char));
     if(!(*S).base)
       exit(-2); /* 存储分配失败 */
     (*S).top=(*S).base+(*S).stacksize;
     (*S).stacksize+=STACKINCREMENT;
   }
   *((*S).top)++=e;
   return 1;
}

int Pop(SqStack *S,char *e)
{ /* 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR */
   if((*S).top==(*S).base)
     return 0;
   *e=*--(*S).top;
   return 1;
}

int StackTraverse(SqStack S,int(*visit)(char))
{ /* 从栈底到栈顶依次对栈中每个元素调用函数visit()。 */
   /* 一旦visit()失败,则操作失败 */
   while(S.top>S.base)
     visit(*S.base++);
   printf("\n");
   return 1;
}

int copy(char c)
{ /* 将字符c送至fp所指的文件中 */
   fputc(c,fp);
   return 1;
}

void LineEdit()
{ /* 利用字符栈s,从终端接收一行并送至调用过程的数据区。算法3.2 */
   SqStack s;
   char ch,c;
   InitStack(&s);
   printf("请输入一个文本文件,^Z结束输入:\n");
   ch=getchar();
   while(ch!=EOF)
   { /* EOF为^Z键,全文结束符 */
     while(ch!=EOF&&ch!='\n')
     {
       switch(ch)
       {
         case '#':Pop(&s,&c);
                  break; /* 仅当栈非空时退栈 */
         case '@':ClearStack(&s);
                  break; /* 重置s为空栈 */
         default :Push(&s,ch); /* 有效字符进栈 */
       }
       ch=getchar(); /* 从终端接收下一个字符 */
     }
     StackTraverse(s,copy); /* 将从栈底到栈顶的栈内字符传送至文件 */
     ClearStack(&s); /* 重置s为空栈 */
     fputc('\n',fp);
     if(ch!=EOF)
       ch=getchar();
   }
   DestroyStack(&s);
}

void main()
{
   fp=fopen("ED.DAT","w"); /* 在当前目录下建立ED.DAT文件,用于写数据, */
   if(fp)                  /* 如已有同名文件则先删除原文件 */
   {
     LineEdit();
     fclose(fp); /* 关闭fp所指的文件 */
   }
   else
     printf("建立文件失败!\n");
}

4、表达式求值
     表达式求值是程序设计语言中的一个最基本问题。在此应用栈的“后进先出”的特点,介绍一种“算法优先级”算法。
     算术四则运算的规则:
       (1) 先乘除,后加减。
       (2)从左算到右。
       (3)先括号内,后括号外。
为实现算符优先算法,可使用两个工作栈:

    OPND栈:存数据或运算结果 

     OPTR 栈:存运算符
算法原理:
    1 . 初态: 置 OPND 栈为空;将 # 作为 OPTR 栈的栈底元素

    2.依次读入表达式中的每个字符

    1)若是操作数,则进入OPND栈;

    2)若是运算符,则与OPTR栈的栈顶运算符进行优先权(级)的比较:

§  若读入运算符的优先权高,则进入 OPTR 栈;
§ 若读入运算符的优先权低,则 OPTR 退栈(退出

  原有的栈顶元素),OPND栈退出两个元素

 (先退出b,再退出a),中间结果再进入OPND栈;

§ 若读入 OPTR 栈的原有栈的栈顶元素若为

  ,则OPTR退出

§ 若读入 # OPTR 栈栈顶元素也为 # ,则 OPTR 栈退出 # ,结束
   
   算法:
 OperandType   EvaluateExpression( ){
  / /OPTR为运算符栈,OPND为运算数,OP为运算符集
   InitStack(OPTR);
   Push(OPTR,'#');
   InitStack(OPND);
   c=getchar();
   while(c!='#'||GetTop(OPTR)!='#'){
         if(! In(c,OP))
           { Push(OPND,c);c=getchar();}
         else
           switch (Precede(GetTop(OPTR),c)) {
               case '<':
                          Push(OPTR,c); c=getchar();break;
               case '=':
                          Pop(OPTR,x);c=getchar();break;
               case '>':
                          Pop(OPTR,theta);
                          Pop(OPND,b);Pop(OPND,a);
                          Push(OPND,OPerate(a,theta,b));break;
             }
     }
 return GetTop(OPND);
}

   具体代码的实现(C):
 #include<string.h>
 #include<ctype.h>
 #include<malloc.h> /* malloc()等 */
 #include<stdio.h> /* EOF(=^Z或F6),NULL */
 #include<process.h> /* exit() */
 #define STACK_INIT_SIZE 10 /* 存储空间初始分配量 */
 #define STACKINCREMENT 2 /* 存储空间分配增量 */
 typedef struct SqStack
 {
   char *base; /* 在栈构造之前和销毁之后,base的值为NULL */
   char *top; /* 栈顶指针 */
   int stacksize; /* 当前已分配的存储空间,以元素为单位 */
 }SqStack; /* 顺序栈 */

 int InitStack(SqStack *S)
 { /* 构造一个空栈S */
   (*S).base=(char *)malloc(STACK_INIT_SIZE*sizeof(char));
   if(!(*S).base)
     exit(-2); /* 存储分配失败 */
   (*S).top=(*S).base;
   (*S).stacksize=STACK_INIT_SIZE;
   return 1;
 }
 int GetTop(SqStack S,char *e)
 { /* 若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR */
   if(S.top>S.base)
   {
     *e=*(S.top-1);
     return 1;
   }
   else
     return 0;
 }

 int Push(SqStack *S,char e)
 { /* 插入元素e为新的栈顶元素 */
   if((*S).top-(*S).base>=(*S).stacksize) /* 栈满,追加存储空间 */
   {
     (*S).base=(char *)realloc((*S).base,((*S).stacksize+STACKINCREMENT)*sizeof(char));
     if(!(*S).base)
       exit(-2); /* 存储分配失败 */
     (*S).top=(*S).base+(*S).stacksize;
     (*S).stacksize+=STACKINCREMENT;
   }
   *((*S).top)++=e;
   return 1;
 }

 int Pop(SqStack *S,char *e)
 { /* 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR */
   if((*S).top==(*S).base)
     return 0;
   *e=*--(*S).top;
   return 1;
 }

 int StackTraverse(SqStack S,int(*visit)(char))
 { /* 从栈底到栈顶依次对栈中每个元素调用函数visit()。 */
   /* 一旦visit()失败,则操作失败 */
   while(S.top>S.base)
     visit(*S.base++);
   printf("\n");
   return 1;
 }

 char Precede(char t1,char t2)
 { /* 判断两符号的优先关系 */
   char f;
   switch(t2)
   {
     case '+':
     case '-':if(t1=='('||t1=='#')
                f='<';
              else
                f='>';
              break;
     case '*':
     case '/':if(t1=='*'||t1=='/'||t1==')')
                f='>';
              else
                f='<';
              break;
     case '(':if(t1==')')
              {
                printf("ERROR1\n");
                exit(0);
              }
              else
                f='<';
              break;
     case ')':switch(t1)
              {
                case '(':f='=';
                         break;
                case '#':printf("ERROR2\n");
                         exit(0);
                default: f='>';
              }
              break;
     case '#':switch(t1)
              {
                case '#':f='=';
                         break;
                case '(':printf("ERROR3\n");
                         exit(0);
                default: f='>';
              }
   }
   return f;
 }

 int In(char c)
 { /* 判断c是否为运算符 */
   switch(c)
   {
     case'+':
     case'-':
     case'*':
     case'/':
     case'(':
     case')':
     case'#':return 1;
     default:return 0;
   }
 }

 char Operate(char a,char theta,char b)
 {
   char c;
   a=a-48;
   b=b-48;
   switch(theta)
   {
     case'+':c=a+b+48;
             break;
     case'-':c=a-b+48;
             break;
     case'*':c=a*b+48;
             break;
     case'/':c=a/b+48;
   }
   return c;
 }

 char EvaluateExpression() 
 { /* 算术表达式求值的算符优先算法。设OPTR和OPND分别为运算符栈和运算数栈 */
   SqStack OPTR,OPND;
   char a,b,c,x,theta;
   InitStack(&OPTR);
   Push(&OPTR,'#');
   InitStack(&OPND);
   c=getchar();
   GetTop(OPTR,&x);
   while(c!='#'||x!='#')
   {
     if(In(c)) /* 是7种运算符之一 */
       switch(Precede(x,c))
       {
         case'<':Push(&OPTR,c); /* 栈顶元素优先权低 */
                 c=getchar();
                 break;
         case'=':Pop(&OPTR,&x); /* 脱括号并接收下一字符 */
                 c=getchar();
                 break;
         case'>':Pop(&OPTR,&theta); /* 退栈并将运算结果入栈 */
		 Pop(&OPND,&b);
                 Pop(&OPND,&a);
                 Push(&OPND,Operate(a,theta,b));
                 break;
       }
     else if(c>='0'&&c<='9') /* c是操作数 */
     {
       Push(&OPND,c);
       c=getchar();
     }
     else /* c是非法字符 */
     {
       printf("ERROR4\n");
       exit(-2);
     }
     GetTop(OPTR,&x);
   }
   GetTop(OPND,&x);
   return x;
 }

 void main()
 {
   printf("请输入算术表达式(中间值及最终结果要在0~9之间),并以#结束\n");
   printf("%c\n",EvaluateExpression());
 }






  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
LIN协议是一种用于低成本、低速率串行网络的通信协议,主要应用于车辆电子系统中。以下是关于LIN协议应用的一些分享。 首先,LIN协议在车辆电子系统中常用于连接各种低速率从设备,如门控制单元、窗户控制单元、座椅控制单元等。通过LIN总线,这些从设备可以与车辆主控制单元进行通信和控制。相比于其他高速率通信协议,如CAN协议,LIN协议更适用于这些低速率从设备的通信需求。 其次,LIN协议具有较低的成本优势。由于LIN协议使用的是普通的串行通信线路,不需要专用的硬件设备支持,因此整体成本相对较低。这使得LIN协议在汽车电子系统中得到广泛的应用,特别是在非关键性应用中。 此外,LIN协议还具有较低的功耗。由于LIN协议使用的是低速率通信,通信过程中的能耗相对较低。这在需要长时间运行的系统中尤为重要,例如关闭引擎后仍需要继续运行的车辆电子系统。 最后,LIN协议还支持多主从架构。这意味着在LIN总线上可以连接多个主设备和从设备,实现复杂的通信和控制功能。这种灵活性使得LIN协议在车辆电子系统中能够满足不同设备之间的通信需求。 总之,LIN协议在车辆电子系统中应用广泛,并且具有成本低、功耗低和多主从支持等优势。随着车辆电子化的发展,LIN协议在汽车行业中的应用前景将会更加广阔。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值