数据结构第五天——栈及部分应用

包含栈的一些基本功能,还有部分应用,括号匹配和表达式求值

一、栈的基本功能

1.建立

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

2.初始化

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

3.压栈

void push(CharStackPtr paraStackPtr, int paraValue) {
	if (paraStackPtr->top >= 9) {
		printf("Cannot push element: stack full.\n");
		return;
	}
	
	paraStackPtr->top ++;
	paraStackPtr->data[paraStackPtr->top] = paraValue;
}

4.出栈

char pop(CharStackPtr paraStackPtr) {
	if (paraStackPtr->top < 0) {
		printf("Cannot pop element: stack empty.\n");
		return '\0';
	}
	
	paraStackPtr->top --;
	return paraStackPtr->data[paraStackPtr->top + 1];
}

5.总代码

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

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

/**
 *输出
 */
 
void outputStack(CharStackPtr paraStack) {
	int i; 
	for (i = 0; i <= paraStack->top; i ++) {
		printf("%c ", paraStack->data[i]);
	}
	printf("\n");
} 

/**
 *初始化
 */
 
CharStackPtr charStackInit() {
	CharStackPtr resultPtr = (CharStackPtr)malloc(sizeof(struct CharStack));
	resultPtr->top = -1;
	
	return resultPtr;
}

/**
 *压栈
 */
 
void push(CharStackPtr paraStackPtr, int paraValue) {
	if (paraStackPtr->top >= 9) {
		printf("Cannot push element: stack full.\n");
		return;
	}
	
	paraStackPtr->top ++;
	paraStackPtr->data[paraStackPtr->top] = paraValue;
}

/**
 *出栈
 */
 
char pop(CharStackPtr paraStackPtr) {
	if (paraStackPtr->top < 0) {
		printf("Cannot pop element: stack empty.\n");
		return '\0';
	}
	
	paraStackPtr->top --;
	return paraStackPtr->data[paraStackPtr->top + 1];
}

void pushPopTest() {
	char ch;
	int i;
	
	printf("---- pushPopTest begins. ----\n");
	
	CharStackPtr tempStack = charStackInit();
	printf("After initialization, the stack is: ");
	outputStack(tempStack);
	
	for (ch = 'a'; ch < 'm'; ch ++) {
		printf("Pushing %c.\n", ch);
		push(tempStack, ch);
		outputStack(tempStack);
	}
	
	for (i = 0; i < 3; i ++) {
		ch = pop(tempStack);
		printf("Pop %c.\n", ch);
		outputStack(tempStack);
	}
	
	printf("---- pushPopTest ends. ----\n");
}


int main() {
	pushPopTest();
	
	return 0;
}

运行结果

二、 括号匹配

前面其实和第一部分相差不大,就只把核心代码列出来

int bracketMatching(char *paraString, int paraLength) {
	int i;
	
	CharStackPtr tempStack = charStackInit();
	push(tempStack, '#');
	char tempChar, tempPopedChar;
	
	for (i = 0; i < paraLength; i ++) {
		tempChar = paraString[i];
		
		switch(tempChar) {
			case '(':
			case '[':
			case '{':
				push(tempStack, tempChar);
				break;
			case ')':
				tempPopedChar = pop(tempStack);
				if (tempPopedChar != '(') {
					return 0;
				}
				break;
			case ']':
				tempPopedChar = pop(tempStack);
				if (tempPopedChar != '[') {
					return 0;
				}
				break;
			case '}':
				tempPopedChar = pop(tempStack);
				if (tempPopedChar != '{') {
					return 0;
				}
				break;
			default:
				break;
		}
	}
	
	tempPopedChar = pop(tempStack);
	if (tempPopedChar != '#') {
		return 0;
	}
	
	return 1;
}

一开始加入了‘#’号到栈里,方便后续的判断

原理就是当读入左括号,如‘(’、‘[’、‘{’时,将它们压入栈,当读到右括号时‘)’、']'、'}',判断栈顶的符号是否符合,符合则返回1,否则返回0

最后加入一个判断,当式子里左右括号数量不对等时,返回0

总代码

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

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

/**
 *输出
 */
 
void outputStack(CharStackPtr paraStack) {
	int i; 
	for (i = 0; i <= paraStack->top; i ++) {
		printf("%c ", paraStack->data[i]);
	}
	printf("\n");
} 

/**
 *初始化
 */
 
CharStackPtr charStackInit() {
	CharStackPtr resultPtr = (CharStackPtr)malloc(sizeof(struct CharStack));
	resultPtr->top = -1;
	
	return resultPtr;
}

/**
 *压栈
 */
 
void push(CharStackPtr paraStackPtr, int paraValue) {
	if (paraStackPtr->top >= 9) {
		printf("Cannot push element: stack full.\n");
		return;
	}
	
	paraStackPtr->top ++;
	paraStackPtr->data[paraStackPtr->top] = paraValue;
}

/**
 *出栈
 */
 
char pop(CharStackPtr paraStackPtr) {
	if (paraStackPtr->top < 0) {
		printf("Cannot pop element: stack empty.\n");
		return '\0';
	}
	
	paraStackPtr->top --;
	return paraStackPtr->data[paraStackPtr->top + 1];
}

int bracketMatching(char *paraString, int paraLength) {
	int i;
	
	CharStackPtr tempStack = charStackInit();
	push(tempStack, '#');
	char tempChar, tempPopedChar;
	
	for (i = 0; i < paraLength; i ++) {
		tempChar = paraString[i];
		
		switch(tempChar) {
			case '(':
			case '[':
			case '{':
				push(tempStack, tempChar);
				break;
			case ')':
				tempPopedChar = pop(tempStack);
				if (tempPopedChar != '(') {
					return 0;
				}
				break;
			case ']':
				tempPopedChar = pop(tempStack);
				if (tempPopedChar != '[') {
					return 0;
				}
				break;
			case '}':
				tempPopedChar = pop(tempStack);
				if (tempPopedChar != '{') {
					return 0;
				}
				break;
			default:
				break;
		}
	}
	
	tempPopedChar = pop(tempStack);
	if (tempPopedChar != '#') {
		return 0;
	}
	
	return 1;
}

void bracketMatchingTest() {
	char *tempExpression = "[2 + (1 - 3)] * 4";
	int tempMatch = bracketMatching(tempExpression, 17);
	printf("Is the expression '%s' bracket matching? %d\n", tempExpression, tempMatch);
	
	tempExpression = "( )  )";
	tempMatch = bracketMatching(tempExpression, 6);
	printf("Is the expression '%s' bracket matching? %d\n", tempExpression, tempMatch);
	
	tempExpression = "()()(())";
	tempMatch = bracketMatching(tempExpression, 8);
	printf("Is the expression '%s' bracket matching? %d\n", tempExpression, tempMatch);
	
	tempExpression = "({}[])";
	tempMatch = bracketMatching(tempExpression, 6);
	printf("Is the expression '%s' bracket matching? %d\n", tempExpression, tempMatch);
	
	tempExpression = ")(";
	tempMatch = bracketMatching(tempExpression, 2);
	printf("Is the expression '%s' bracket matching? %d\n", tempExpression, tempMatch);
}

int main() {
	bracketMatchingTest();
	
	return 0;
}

运行结果

三、表达式求值

思路还是借鉴的学长的思路,只能说确实很厉害

1、创建

typedef struct CharAndIntStack{
	int topInt;
	int topChar;
	
	int dataInt[100];
	char dataChar[100];
} *CharAndIntStackPtr;

 这个其实里面包含了两个栈,一个专门用来存放数字,一个用来存放符号,等下计算的时候方便使用

2、压栈

void pushInt(CharAndIntStackPtr paraStackPtr, int paraValue) {
	if (paraStackPtr->topInt >= 99) {
		printf("Cannot push element: stack full.\n");
		return;
	}
	
	paraStackPtr->topInt ++;
	
	paraStackPtr->dataInt[paraStackPtr->topInt] = paraValue;
}

void pushChar(CharAndIntStackPtr paraStackPtr, char paraValue) {
	if (paraStackPtr->topChar >= 99) {
		printf("Cannot push element: stack full.\n");
		return;
	}
	
	paraStackPtr->topChar ++;
	
	paraStackPtr->dataChar[paraStackPtr->topChar] = paraValue; 
}

同理,有两种栈,就有两种压栈方式,但是原理相差不大

3、出栈

int popInt(CharAndIntStackPtr paraStackPtr) {
	if (paraStackPtr->topInt < 0) {
		printf("Cannot pop element: stack empty.\n");
		return 0;
	}
	
	paraStackPtr->topInt --;
	
	return paraStackPtr->dataInt[paraStackPtr->topInt + 1];
}

char popChar(CharAndIntStackPtr paraStackPtr) {
	if (paraStackPtr->topChar < 0) {
		printf("Cannot pop element: stack empty.\n");
		return '\0';
	}
	
	paraStackPtr->topChar --;
	
	return paraStackPtr->dataChar[paraStackPtr->topChar + 1];
}

4、判断优先级

int Priority(char temp) {
	if (temp == '+' || temp == '-') {
		return 1;
	} else if (temp == '*' || temp == '/') {
		return 2;
	} else {
		return 0;
	}
} 

判断+、-、*、/的优先级

5、判断数字

int judgenumber(char temp) {
	if (temp >= '0' && temp <= '9') {
		return 1;
	} else {
		return 0;
	}
}

6、计算

void compute(CharAndIntStackPtr tempStack) {
	int b = popInt(tempStack);
	int a = popInt(tempStack);
	char c = popChar(tempStack);
	int x;
	if (c == '+') {
		x = a + b;
	} else if (c == '-') {
		x = a - b;
	} else if (c == '*') {
		x = a * b;
	} else {
		x = a / b;
	}
	pushInt(tempStack, x);
}

7、判断符号栈里是否还有剩余

int judgeSize(CharAndIntStackPtr paraStackPtr) {
	if (paraStackPtr->topChar == -1) {
		return 0;
	}
	
	if (paraStackPtr->dataChar[paraStackPtr->topChar] != '\0') {
		return 1;
	} else {
		return 0;
	}
}

8.总代码

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

typedef struct CharAndIntStack{
	int topInt;
	int topChar;
	
	int dataInt[100];
	char dataChar[100];
} *CharAndIntStackPtr;

/**
 *初始化
 */
  
CharAndIntStackPtr charandintStackInit() {
	CharAndIntStackPtr resultPtr = (CharAndIntStackPtr)malloc(sizeof(struct CharAndIntStack));
	
	resultPtr->topChar = -1;
	resultPtr->topInt = -1;
	
	return resultPtr;
}

/**
 *压栈
 */
 
void pushInt(CharAndIntStackPtr paraStackPtr, int paraValue) {
	if (paraStackPtr->topInt >= 99) {
		printf("Cannot push element: stack full.\n");
		return;
	}
	
	paraStackPtr->topInt ++;
	
	paraStackPtr->dataInt[paraStackPtr->topInt] = paraValue;
}

void pushChar(CharAndIntStackPtr paraStackPtr, char paraValue) {
	if (paraStackPtr->topChar >= 99) {
		printf("Cannot push element: stack full.\n");
		return;
	}
	
	paraStackPtr->topChar ++;
	
	paraStackPtr->dataChar[paraStackPtr->topChar] = paraValue; 
}

/**
 *出栈
 */
 
int popInt(CharAndIntStackPtr paraStackPtr) {
	if (paraStackPtr->topInt < 0) {
		printf("Cannot pop element: stack empty.\n");
		return 0;
	}
	
	paraStackPtr->topInt --;
	
	return paraStackPtr->dataInt[paraStackPtr->topInt + 1];
}

char popChar(CharAndIntStackPtr paraStackPtr) {
	if (paraStackPtr->topChar < 0) {
		printf("Cannot pop element: stack empty.\n");
		return '\0';
	}
	
	paraStackPtr->topChar --;
	
	return paraStackPtr->dataChar[paraStackPtr->topChar + 1];
}

/**
 *优先级
 */
 
int Priority(char temp) {
	if (temp == '+' || temp == '-') {
		return 1;
	} else if (temp == '*' || temp == '/') {
		return 2;
	} else {
		return 0;
	}
} 

/**
 *判断数字
 */
  
int judgenumber(char temp) {
	if (temp >= '0' && temp <= '9') {
		return 1;
	} else {
		return 0;
	}
}

/**
 *计算
 */
 
void compute(CharAndIntStackPtr tempStack) {
	int b = popInt(tempStack);
	int a = popInt(tempStack);
	char c = popChar(tempStack);
	int x;
	if (c == '+') {
		x = a + b;
	} else if (c == '-') {
		x = a - b;
	} else if (c == '*') {
		x = a * b;
	} else {
		x = a / b;
	}
	pushInt(tempStack, x);
}

/**
 *判断符号剩余
 */
  
int judgeSize(CharAndIntStackPtr paraStackPtr) {
	if (paraStackPtr->topChar == -1) {
		return 0;
	}
	
	if (paraStackPtr->dataChar[paraStackPtr->topChar] != '\0') {
		return 1;
	} else {
		return 0;
	}
}

int main() {
	CharAndIntStackPtr tempStack = charandintStackInit();
	char test[100];
	gets(test);
	
	int testLength = 0, i;
	for (i = 0; test[i] != '\0'; i ++) {
		testLength ++;
	}
	
	for (i = 0; i < testLength; i ++) {
		char c = test[i];
		
		if (judgenumber(c) == 1) {
			int x = 0, j = i;
			while (j < testLength && judgenumber(test[j])) {
				x = x * 10 + test[j ++] - '0';
			}
			i = j - 1;
			pushInt(tempStack, x);
		} else if (c == '(') {
			pushChar(tempStack, c);
		} else if (c == ')') {
			while (tempStack->dataChar[tempStack->topChar] != '(') {
				compute(tempStack);
			}
			popChar(tempStack);
		} else {
			while (judgeSize(tempStack) == 1 && tempStack->dataChar[tempStack->topChar] != '(' && Priority(tempStack->dataChar[tempStack->topChar]) >= Priority(c)) {
				compute(tempStack);
			}
			pushChar(tempStack, c);
		}
	}
	
	while (judgeSize(tempStack) == 1) {
		compute(tempStack);
	}
	
	printf("%d", tempStack->dataInt[tempStack->topInt]);
	
	return 0;
}

9、测试结果

测试用例1:12*(2*(1+2))

测试用例2:81/(3*3)-10

总结

1、注意的点有运算的数不知一位数,而是两位数,三位数,当读取的第一个值是数字的话,得往后再判断判断,是否为多位数

2、运行完之后应检查符号栈里是否有剩余

3、存在的缺陷,我没有做除以0的判断(等以后有空在做),同时输入负数时不能直接输入,可以用(0-x)的形式输入

4、在写括号匹配时,swtich函数,括号里输入一个判断式子时,会直接进入第一个case(大概),导致一致判断错误,所以写的时候还得注意规范

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值