栈的应用

栈的应用

栈在括号匹配中的应用

  1. 假设表达式中允许包含两种括号:圆括号和方括号,其嵌套的顺序任意,([]) 或者[([ ][ ])]为正确的格式;[)(] 等为不正确的格式。 判断表达式是否是正确的格式。

    算法思想 :

    1. 初始化一个栈,顺序读入表达式。
    2. 如果是读到字符是左括号(包含 ‘(’ ,’[’ ,’{’) ),则将字符压入栈中。
    3. 否则如果读到的是右括号,则如果和当前栈顶字符匹配,就将栈顶元素弹出,否则括号不匹配。
  // 括号匹配 
       for(int i = 0 ;i<str.length() ; i++ ) {
          if(str[i] == '(' || str[i] == '[' || str[i] == '{'){
              // 如果是左括号,直接压栈
              st.push(str[i]) ; 
          }
          else{
              char t = st.top() ;
              if(str[i] == ')' && t =='('){
                 st.pop() ; // 弹出栈  
              }else if(str[i] == ']' && t == '['){
                  st.pop() ; 
              }else if(str[i] == '}' && t == '{'){
                  st.pop() ;
              }else{
                  cout<<"not matching !" ;
                  break ;
              }
          }
       }
       if(st.empty()){ // 匹配
           cout<<"yes!"<<endl; 
       }else {
           cout<<"no!"<<endl;
       }
  1. 栈在表达式求值中的应用

    由于中缀表达式求值时需要考虑运算符的优先级,而且还要处理括号。而中缀表达式不需要考虑。

    中缀表达式转后缀表达式算法流程 :

    1)如果遇到操作数,我们就直接将其输出。

    2)如果遇到操作符,则我们将其放入到栈中,遇到左括号时我们也将其放入栈中。

    3)如果遇到一个右括号,则将栈元素弹出,将弹出的操作符输出直到遇到左括号为止。注意,左括 号只弹出并不输出。

    4)如果遇到任何其他的操作符,如**(“+”, “*”,“(”)**等,从栈中弹出元素直到遇到发现更低优先 级的元素(或者栈为空)为止。弹出完这些元素后,才将遇到的操作符压入到栈中。有一点需要注意,只有在遇到" ) “的情况下我们才弹出” ( “,其他情况我们都不会弹出” ( "。

    5)如果我们读到了输入的末尾,则将栈中所有元素依次弹出。

    a. 若为’(’ , 入栈 ;

    b. 若为’)’ , 则依次把栈中的运算符加入到后缀表达式中,直到出现 ’ (’, 并从栈中删除’(’ ;

    c. 若为 ’ +’ , ‘-’ , ‘*’ , ‘/’ ,

    • 栈空,入栈 ;
    • 栈顶元素为 ‘C’ ,入栈
    • 高于栈顶元素优先级,入栈 ;
    • 否则,依次弹出栈顶运算符,直到一个优先级比它低的运算符或’(’ 为止 ;

    d. 遍历完成,若栈非空依次弹出所有元素加入后缀表达式中。

    代码 :

  //中缀表达式转后缀
   
   #include
   #include
   #include
   
   using namespace std;
   
   int prio(char op) {                 //给运算符优先级排序
       int priority;
       if (op == '*' || op == '/')
           priority = 2;
       if (op == '+' || op == '-')
           priority = 1;
       if (op == '(')
           priority = 0;
       return priority;
   }
   bool Trans(string &str,string &str1) {   //引用传递
       stack<char> s;                   //定义一个char类型的栈s
       int i;
       for (i = 0; i<str.size(); i++) {
           if (str[i] >= '0' && str[i] <= '9') {    //如果是数字,直接入栈
               str1+=str[i];
           }
           else {                        //否则不是数字
               if (s.empty())            //栈空则入站
                   s.push(str[i]);
               else if (str[i] == '(')   //左括号入栈
                   s.push(str[i]);
               else if (str[i] == ')') {  //如果是右括号,只要栈顶不是左括号,就弹出并输出
                   while (s.top() != '(') {  
                       str1+= s.top();
                       s.pop();
                   }
                   s.pop();                 //弹出左括号,但不输出
               }
               else {
                   while (prio(str[i]) <= prio(s.top())) { //栈顶优先级大于等于当前运算符,则输出
                       str1+= s.top();
                       s.pop();
                       if (s.empty())      //栈为空,停止
                           break;
                   }
                   s.push(str[i]);   //把当前运算符入栈
               }
           }
       }
    while (!s.empty()) {      //最后,如果栈不空,则弹出所有元素并输出
           str1+= s.top();
           s.pop();
       }
       return true;
   }
   int main() {                //主程序
       string infix;
       string postfix;
       cout << "zhong" << infix << endl;
       cin >> infix;
       Trans(infix,postfix);
       cout << "hou" <<endl;
       cout<< postfix << endl;
       return 1;
   }
后缀表达式求值 : 
  1. 顺序扫描表达式
  2. 如果是操作数,则将其压入栈中;
  3. 如果是操作符,则连续从栈中退出两个操作数 X 和 Y,形成运算指令 X Y ,并将结果重新压入栈中。并将结果重新压入栈中。
  4. 当表达式每一项都扫描并处理完后,栈顶存放的就是最后的结果。

int cal_value(string s) {
    // 后缀表达式求值
    // 仅限个位数
    stack<int> p  ;
    for(int i = 0 ; i<s.length() ; i++) {
        if(s[i] >='0' && s[i]<='9'){
            p.push(int(s[i]-'0')) ; 
        }else {
            int a = p.top() ;
            p.pop() ; 
            int b = p.top() ;
            p.pop() ;
            switch(s[i]) {
                case '+':
                    p.push(a+b) ;
                    break ;
                case '-':
                      p.push(a-b) ;
                    break ;
                case '*':
                     p.push(a*b) ;
                    break ; 
                case '/':
                    p.push(a/b) ;
                    break ; 
            }
        }

    }
    return p.top() ;
}
  1. 栈在求进制转换的应用

void conversion(int n ,int r) {
    stack<char> s ;
    string ans = "" ; 
    while(n){
        s.push(n%r +'0') ; 
        n/=r; 
    }
    while(!s.empty()){
        ans+=s.top() ;
        s.pop();
    }
    cout<<ans<<endl; 
}

该代码仅限非负十进制转换成小于10进制。

  1. 栈在dfs时的应用
   void dfs(Point start ,Point end)
   {
   	bool find ;
   	Point head ;
   	STACK a ;
   	Stack *s ;
   	a.InitStack(s);
   	start.di = -1 ;// 开始点,且还没有尝试 ;
   	a.Push(s,start);
   	mg[start.x][start.y] = -1 ;
   	while(!a.StackEmpty(s))
   	{
   		head;// 栈顶元素
   		a.GetTop(s,head) ;
   		if(head.x == end.x && head.y == end.y)
   		{
   			count++ ;
   			printf("Map   %d :\n",count-1);
   			for(int k = 0 ;k<=s->top ;k++)
   			{
   				printf("(%d ,%d) ",s->data[k].x,s->data[k].y);
   				
   				if((k+1)%5==0)
   				cout<<endl;
   			}
   			
   			printf("\n\n");
   			if(s->top+1 <minlen)
   			{
   				for(int k = 0 ;k<=s->top ;k++)
   				{
   					path[k] = s->data[k] ;
   				}
   				// 更新最短路径
   				minlen = s->top+1 ;
   			}
   			// 退栈,重新走
   			mg[s->data[s->top].x][s->data[s->top].y] = 0 ;
   			s->top--;
   			head.x = s->data[s->top].x ;
   			head.y = s->data[s->top].y ;
   			head.di = s->data[s->top].di ;
   			
   		}
   		find = false ;
   	
   		while(head.di<4 && !find)
   		{
   			head.di++ ;
   			switch(head.di){
   				
   				case 0:head.x=s->data[s->top].x -1 ;head.y =s->data[s->top].y;break;   //上面
    
                   case 1:head.x=s->data[s->top].x ;head.y =s->data[s->top].y+1;break;   //右边
    
                   case 2:head.x=s->data[s->top].x +1 ;head.y =s->data[s->top].y;break;   //下面
    
                   case 3:head.x=s->data[s->top].x  ;head.y =s->data[s->top].y-1;break;   //左边
   			}
   				
   			if(mg[head.x][head.y]==0)
   			{
   				find = true ;
   			}
    
   		}
   		
   		if(find)
   		{
   			//如果有路
   			s->data[s->top].di = head.di ; // 修改原来栈顶的方向值
   			s->top++;
   			s->data[s->top].x = head.x ;// 入栈
   			s->data[s->top].y = head.y ;
   			s->data[s->top].di = -1 ;// 此点还没有进行过尝试
   			mg[head.x][head.y] = -1 ;//访问过了
   		}
   		else
   		{
   			//回溯
   			mg[s->data[s->top].x][s->data[s->top].y] = 0 ;
   			s->top --;
   		}
   	
   	}
   		
   		printf("最短路径长度为 :%d\t",minlen);
   		printf("最短路径 : \n");
   		for(int k = 0 ;k <minlen ;k++)
   		{
   			printf("\t\t\t(%d,%d)\n",path[k].x,path[k].y) ;
   		}
   		cout<<endl;
   	
   }
   ————————————————
   版权声明:本文为CSDN博主「不想悲伤到天明」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
   原文链接:https://blog.csdn.net/qq_41661809/article/details/83185835

你可能感兴趣的:(计算机上机复试)