栈的应用------(括号匹配和表达式求值)

一、括号匹配

原理如下:
1、扫描整个存储括号数据的char型数组;
2、遇到左括号就入栈,即:{ [ ( 这三种之一就入栈,
3、遇到右括号就把之前的左括号出栈,因为每个右括号会跟其相邻同种类型的左括号配对,就跟if-else语句一样,else总跟最近未匹配的if配对。同时还要注意括号类型是否一样,比如:
右花括号} 不能跟左方括号 [ 配对,虽然是一右一左,但要跟 { 才能配对,每次正确配对消耗一个左括号
4、最后判断栈是否为空,如果为空,说明全部左括号都配对成功,顺利出栈,栈内没有元素。
 

定义节点

typedef struct CharStack
{
	int top;
	int data[MAXSIZE];
}*CharStackPtr;

栈的初始化

CharStackPtr charStackInit() {
	CharStackPtr resultPtr = (CharStackPtr)malloc(sizeof(struct CharStack));
	resultPtr->top = -1;
 
	return resultPtr;
}

入栈

void push(CharStackPtr paraStackPtr, int paraValue) 
{
    // Step 1. Space check. 
    if (paraStackPtr->top >= MAXSIZE - 1) 
	{
        printf("Cannot push element: stack full.\r\n");
        return;
    }//Of if

    // Step 2. Update the top.
	paraStackPtr->top ++;

	// Step 3. Push element.
    paraStackPtr->data[paraStackPtr->top] = paraValue;
}// Of push

出栈

char pop(CharStackPtr paraStackPtr)
{
	// Step 1. Space check.
	if(paraStackPtr->top < 0)
	{
		printf("Cannot pop element: stack empty.\r\n");
		return '\0';
	}
	// Step 2. Update the top.
	paraStackPtr->top --;
	// Step 3. Push element.
	return paraStackPtr->data[paraStackPtr->top + 1]; 
}

栈中的括号匹配

bool bracketMatching(char* paraString, int paraLength) {
  
    CharStackPtr tempStack = charStackInit();
    push(tempStack, '#');//让#成为栈底比-1更加方便,因为有时-1会被判定为ture
    char tempChar, tempPopedChar;
 
    for (int i = 0; i < paraLength; i++) {
        tempChar = paraString[i];
 
        switch (tempChar) {
        case '(':
        case '[':
        case '{':
            push(tempStack, tempChar);
            break;
        case ')':
            tempPopedChar = pop(tempStack);
            if (tempPopedChar != '(') {
                return false;
            } // Of if
            break;
        case ']':
            tempPopedChar = pop(tempStack);
            if (tempPopedChar != '[') {
                return false;
            } // Of if
            break;
        case '}':
            tempPopedChar = pop(tempStack);
            if (tempPopedChar != '{') {
                return false;
            } // Of if
            break;
        default:
            // Do nothing.
            break;
        }// Of switch
    } // Of for i
 
    tempPopedChar = pop(tempStack);
    if (tempPopedChar != '#') {
        return false;
    } // Of if
 
    return true;
}// Of bracketMatching

总代码

#include <stdio.h>
#include <malloc.h>
 
#define STACK_MAX_SIZE 10
 
 
typedef struct CharStack {
    int top;
 
    int data[STACK_MAX_SIZE]; 
} *CharStackPtr;
 
 
void outputStack(CharStackPtr paraStack) {
    for (int i = 0; i <= paraStack->top; i ++) {
        printf("%c ", paraStack->data[i]);
    }
    printf("\r\n");
}
 
 
CharStackPtr charStackInit() {
	CharStackPtr resultPtr = (CharStackPtr)malloc(sizeof(struct CharStack));
	resultPtr->top = -1;
 
	return resultPtr;
}
 
 
void push(CharStackPtr paraStackPtr, int paraValue) {
   
    if (paraStackPtr->top >= STACK_MAX_SIZE - 1) {
        printf("Cannot push element: stack full.\r\n");
        return;
    }
 
 
	paraStackPtr->top ++;
 
 
    paraStackPtr->data[paraStackPtr->top] = paraValue;
}
 
 
char pop(CharStackPtr paraStackPtr) {
   
    if (paraStackPtr->top < 0) {
        printf("Cannot pop element: stack empty.\r\n");
        return '\0';
    }
 
    
	paraStackPtr->top --;
 
 
    return paraStackPtr->data[paraStackPtr->top + 1];
}
 
void pushPopTest() {
    printf("---- pushPopTest begins. ----\r\n");
 
    CharStackPtr tempStack = charStackInit();
    printf("After initialization, the stack is: ");
	outputStack(tempStack);
 
	char ch;
	for ( ch = 'a'; ch < 'm'; ch ++) {
		printf("Pushing %c.\r\n", ch);
		push(tempStack, ch);
		outputStack(tempStack);
	}
 
	
	int i; 
	for ( i = 0; i < 3; i ++) {
		ch = pop(tempStack);
		printf("Pop %c.\r\n", ch);
		outputStack(tempStack);
	}
 
    printf("---- pushPopTest ends. ----\r\n");
}
 
 
bool bracketMatching(char* paraString, int paraLength) {
	
    CharStackPtr tempStack = charStackInit();
	push(tempStack, '#');
	char tempChar, tempPopedChar;
 
 
	for (int i = 0; i < paraLength; i++) {
		tempChar = paraString[i];
 
		switch (tempChar) {
		case '(':
		case '[':
		case '{':
			push(tempStack, tempChar);
			break;
		case ')':
			tempPopedChar = pop(tempStack);
			if (tempPopedChar != '(') {
				return false;
			} 
			break;
		case ']':
			tempPopedChar = pop(tempStack);
			if (tempPopedChar != '[') {
				return false;
			} 
			break;
		case '}':
			tempPopedChar = pop(tempStack);
			if (tempPopedChar != '{') {
				return false;
			}
			break;
		default:
			
			break;
		}
	} 
 
	tempPopedChar = pop(tempStack);
	if (tempPopedChar != '#') {
		return false;
	} 
 
	return true;
}
 
/**
 * Unit test.
 */
void bracketMatchingTest() {
	char* tempExpression = "(()(";
	bool tempMatch = bracketMatching(tempExpression, 17);
	printf("Is the expression '%s' bracket matching? %d \r\n", tempExpression, tempMatch);
 
 
	tempExpression = "( )  )";
	tempMatch = bracketMatching(tempExpression, 6);
	printf("Is the expression '%s' bracket matching? %d \r\n", tempExpression, tempMatch);
 
	tempExpression = "()()(())";
	tempMatch = bracketMatching(tempExpression, 8);
	printf("Is the expression '%s' bracket matching? %d \r\n", tempExpression, tempMatch);
 
	tempExpression = "({}[])";
	tempMatch = bracketMatching(tempExpression, 6);
	printf("Is the expression '%s' bracket matching? %d \r\n", tempExpression, tempMatch);
 
 
	tempExpression = ")(";
	tempMatch = bracketMatching(tempExpression, 2);
	printf("Is the expression '%s' bracket matching? %d \r\n", tempExpression, tempMatch);
}// Of bracketMatchingTest
 
/**
 The entrance.
 */
int main() {
	 pushPopTest();
	bracketMatchingTest();
}// Of main

运行结果

---- pushPopTest begins. ----
After initialization, the stack is:
Pushing a.
a
Pushing b.
a b
Pushing c.
a b c
Pushing d.
a b c d
Pushing e.
a b c d e
Pushing f.
a b c d e f
Pushing g.
a b c d e f g
Pushing h.
a b c d e f g h
Pushing i.
a b c d e f g h i
Pushing j.
a b c d e f g h i j
Pushing k.
Cannot push element: stack full.
a b c d e f g h i j
Pushing l.
Cannot push element: stack full.
a b c d e f g h i j
Pop j.
a b c d e f g h i
Pop i.
a b c d e f g h
Pop h.
a b c d e f g
---- pushPopTest ends. ----
Is the expression '(()(' bracket matching? 0
Is the expression '( )  )' bracket matching? 0
Is the expression '()()(())' bracket matching? 1
Is the expression '({}[])' bracket matching? 1
Is the expression ')(' bracket matching? 0

二、表达式求值

我们首先建立两个栈,一个用于存放运算符,一个用于存放操作数
然后获取一个表达式,对表达式从左向右扫描,因为要符合算术运算先乘除后加减的运算规则,故并不是遇见一个运算符就可以进行运算,要与上一次遇见的运算符进行比较,优先级大的可以进行计算。
‘()’优先级最高,‘(’和‘)’优先级相同,故若优先级相同,则说明是括号
如果栈顶运算符和扫描到的运算符相同,则栈顶运算符优先级高。例如:栈顶运算符为‘+’,扫描到的运算符为‘+’或‘-’,则栈顶运算符优先级高
例如:3+5*8-2,第一次遇见的数是3,我们将3存入操作数栈中,将‘+’存入运算符栈中;第二次遇见5,存入操作数栈中,‘ * ’ 和‘ + ’比较,优先级高于‘+’, 将5取出,和下一个操作数8进行乘法运算,然后将求出的40存入操作数栈中;在向后扫描,将‘-’和‘+’比较,优先级高,取出40与2,求出38存入操作数栈;假如读出的运算符是表达式结束符‘#’,则将运算符中最后一个‘+’取出并与操作数中仅剩的两个数做3+38计算;若读出的运算符是表达式结束符‘#’ 且运算符栈顶的运算符也为‘#’, 则表达式处理结束,输出操作数最后一个数

#include <stdio.h>
struct Sqstack {
	int data[100];
	int top;
};
char opset[10] = {'+', '-', '*', '/', '(', ')', '#'};
//用来进行比较运算符优先级的矩阵,3代表'=',2代表'>',1代表'<',0代表不可比 
int  cmp[7][7]  = {
        { 2, 2, 1, 1, 1, 2, 2 },
        { 2, 2, 1, 1, 1, 2, 2 },
        { 2, 2, 2, 2, 1, 2, 2 },
        { 2, 2, 2, 2, 1, 2, 2 },
        { 1, 1, 1, 1, 1, 3, 0 },
        { 2, 2, 2, 2, 0, 2, 2 },
        { 1, 1, 1, 1, 1, 0, 3 }  };
Sqstack Num;
Sqstack Oper;

void InitStack(Sqstack &s);//初始化栈
void Push(Sqstack &s, char ch);//入栈
char GetTop(Sqstack &s);//获取栈顶元素的值 
int In(char ch, char operArr[10]);//判断是否为运算符
int Cal();
int Pop (Sqstack &s, char &x);//出栈 
char Compare(char oper1, char oper2); 
int Count(int x1, char op, int x2);

void InitStack(Sqstack &s) {
	s.top = -1;
}

void Push(Sqstack &s, char ch) {
	
	if(s.top == 99) {//栈满 
		return ;
	}
	s.top++;
	s.data[s.top] = ch;
	return ;
	
}

char GetTop(Sqstack &s) {
	
	if(s.top == -1) {
		return 0;
	}
	char ch;
	ch = s.data[s.top];
	return ch;
	
}

int Pop(Sqstack &s, char &x) {
	
     if(s.top == -1)
         return 0;
     x = s.data[s.top];
     --(s.top);
     return 1;
     
 }

int In(char ch, char operArr[10]) {
	
	for(int i = 0; i < 7; i++) {
		if(ch == operArr[i]) {
			return 1;
		}
	}
	return 0;
	
}

char Compare(char oper1, char oper2) {
	int m = 0, n = 0, i, ans;
	char ch;
	for(i = 0; i < 7; i++) {
		if(oper1 == opset[i]) {
			m = i;
		}
		if(oper2 == opset[i]) {
			n = i;
		}
	}
	ans = cmp[m][n];
	switch (ans) {
		case 2:
        	return (char)('<');
    	case 1:
       		return (char)('>');
    	case 3:
        	return (char)('=');
    	default:
     	    printf("表达式错误!\n");
       		break;
    }
}

int Count(int x1, char op, int x2) {
	int val;
	switch(op) {
		case '+': val = x1 + x2; break;
		case '-': val = x1 - x2; break;
		case '*': val = x1 * x2; break;
		case '/': val = x1 / x2; break;
	}
	return val;
}

int Cal() {
	
	char ch, x, op, a1, a2, val;
	int data, ans;
	InitStack(Num);//初始化操作数栈 
	InitStack(Oper);//初始化运算符栈
	Push(Oper, '#');//在运算符栈中加入终止符为了进行比较,结束运算
	printf("请输入一个表达式:\n");
	ch = getchar();
	while(ch != '#' || GetTop(Oper) != '#') {
		//opset为运算符集合 
		if(!In(ch, opset)) {//如果读入的是操作数 
			data = ch - '0';
			ch = getchar();
			while(!In(ch, opset)){//读入的不是运算符,是操作数
			 	data = data * 10 + ch - '0';//读入操作数的各位数码,并转化为十进制数data 
			 	ch = getchar();
			}
			Push(Num, data);//操作数入栈
		} else {
			switch(Compare(GetTop(Oper), ch)) {
				case '>': 
					Push(Oper, ch); 
					ch = getchar(); 
					break;
				case '=': 
					Pop(Oper, x); 
					ch = getchar(); 
					break;
				case '<': 
					Pop(Oper, op); 
					Pop(Num, a2); 
					Pop(Num, a1); 
					val = Count(a1, op, a2); 
					Push(Num, val); 
					break;
			}
		}
	}
	val = GetTop(Num);
	return val; 
	
} 

int main() {
	int answer;
	answer = Cal();
	printf("%d", answer);
}

运行结果

请输入一个表达式:
3*(5+7)-8#
-114

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值