第四次作业

1.栈

栈限定仅在表尾进行插入和删除操作的线性表。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻成为新的栈顶元素。

  在这个过程中 指针一开始指向-1,在指针加一后再放入元素,这个过程为入栈。出栈相同先指针减一再出元素。

代码

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

#define STACK_MAX_SIZE 10

/**
 * Linear stack of integers. The key is data.
 */
typedef struct CharStack {
	int top;

	int data[STACK_MAX_SIZE]; //The maximum length is fixed.
} *CharStackPtr;

/**
 * Output the stack.
 */
void outputStack(CharStackPtr paraStack) {
	for (int i = 0; i <= paraStack->top; i++) {
		printf("%c ", paraStack->data[i]);
	}// Of for i
	printf("\r\n");
}// Of outputStack

/**
 * Initialize an empty char stack. No error checking for this function.
 * @param paraStackPtr The pointer to the stack. It must be a pointer to change the stack.
 * @param paraValues An int array storing all elements.
 */
CharStackPtr charStackInit() {
	CharStackPtr resultPtr = (CharStackPtr)malloc(sizeof(CharStack));
	resultPtr->top = -1;

	return resultPtr;
}//Of charStackInit

/**
 * Push an element to the stack.
 * @param paraValue The value to be pushed.
 */
void push(CharStackPtr paraStackPtr, int paraValue) {
	// Step 1. Space check.
	if (paraStackPtr->top >= STACK_MAX_SIZE - 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

/**
 * Pop an element from the stack.
 * @return The poped value.
 */
char pop(CharStackPtr paraStackPtr) {
	// Step 1. Space check.
	if (paraStackPtr->top < 0) {
		printf("Cannot pop element: stack empty.\r\n");
		return '\0';
	}//Of if

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

	// Step 3. Push element.
	return paraStackPtr->data[paraStackPtr->top + 1];
}// Of pop

/**
 * Test the push function.
 */
void pushPopTest() {
	printf("---- pushPopTest begins. ----\r\n");

	// Initialize.
	CharStackPtr tempStack = charStackInit();
	printf("After initialization, the stack is: ");
	outputStack(tempStack);

	// Pop.
	for (char ch = 'd'; ch < 'm'; ch++) {
		printf("Pushing %c.\r\n", ch);
		push(tempStack, ch);
		outputStack(tempStack);
	}//Of for i

	// Pop.
	for (int i = 0; i < 3; i++) {
		 char ch = pop(tempStack);
		printf("Pop %c.\r\n", ch);
		outputStack(tempStack);
	}
	//Of for i

	printf("---- pushPopTest ends. ----\r\n");
}// Of pushPopTest

/**
 The entrance.
 */
void main() {
	pushPopTest();
}
// Of main

运行结果 

2.表达式求值

  1. 初始化两个栈,操作数栈和运算符栈;
  2. 若扫描到操作数,压入操作数栈;
  3. 若扫描到运算符或界限符,则按照“中缀转后缀”相同的逻辑压入运算符栈(期间也会弹出运算符,每当弹出一个运算符时,就需要再弹出两个操作数栈的栈顶元素并执行相应运算,运算结果再压回操作数栈;

 代码

/*
	栈的应用----表达式求值。 
*/
#include <stdio.h>		// 引用输入(scanf)、输出(printf)函数的头文件; 
#include <stdlib.h>		// 引用 malloc free 函数的头文件; 

//构建栈的结构 
typedef struct LinkNode{
	char str;
	LinkNode *next;
}LinkNode, *LinkStack; 

//栈的初始化 
void InitStack(LinkStack &S)
{
	S = NULL;
}

//栈空的判断 
bool EmptyStack(LinkStack S)
{
	if (S == NULL)
		return true;
	else
		return false;
}

//进栈操作;单链表的前插操作 
void InsertStack(LinkStack &S, char str)
{
	LinkNode *p;		//定义一个指针结点; 
	p = (LinkNode *)malloc(sizeof(LinkNode));	//分配空间; 
	p->str = str;		//赋值该节点的str属性值; 
	p->next = S;		
	S = p;				//修改 S 的指向 
}

//出栈操作 
bool DeleteStack(LinkStack &S, char &str)
{
	if (EmptyStack(S))	//栈空报错; 
		return false;
	LinkNode *p = S;	//定义一个指针结点,使其指向要被删除的栈顶结点; 
	str = p->str;		//用str记录要被弹出栈的元素值,并传递出去; 
	S = p->next;		//修改S指针指向的位置; 
	free(p);			//释放要被删除的结点 
	return true;
}

//获取栈顶元素,用str传递栈顶元素; 
bool GetStack(LinkStack S, char &str) 
{
	if (EmptyStack(S))	//栈空报错; 
		return false;
	str = S->str;
	return true;
}

//进行 + - * / 运算,将计算结果用Lnum传递; 
bool Operation(char &Lnum, char Rnum, char operation) 
{
	switch (operation)
	{
		case '+':
			Lnum = Lnum + Rnum;
			break;
		case '-':
			Lnum = Lnum - Rnum;
			break;
		case '*':
			Lnum = Lnum * Rnum;
			break;
		case '/':
			if (Rnum == 0)
			{
				printf("除数不能为0!\n");
				return false;
			}
			Lnum = Lnum / Rnum;
			break;
		default:
			printf("有不合法的运算符!\n");
			return false; 
			break;
	}
	return true;
} 

//比较运算符的顺序;用result传递比较结果; 
bool Compare(char one, char topchar, char &result) 
{
	switch (one)
	{
		case '+':
		case '-':
			if (topchar == '(')
				result = '<';	//'+' '-' 进栈; 
			else
				result = '>';	
			break;
		case '*':
		case '/':
			if (topchar == '*' or topchar == '/')
				result = '>';
			else
				result = '<';	//'*' '/' 进栈; 
			break;
		case '(':
			result = '<';
			break;
		case ')':
			result = '=';
			break;
		default :
			printf("有不合法的运算符!\n"); 
			return false;
			break;
	}
	return true;
}

int main() 
{
	LinkStack Snum, Schar;
	InitStack(Snum);		//初始化操作数栈; 
	InitStack(Schar);		//初始化运算符栈; 
	printf("Function:\n"); 
	printf("栈的应用-----表达式求值\n");
	printf("input what you want to calculator:");
	char *op = (char *)malloc(sizeof(char));	//为指针op分配空间; 
	gets(op);			//赋值;
	char topstr,result;		//记录栈顶符号和比较之后的结果; 
	char Lnum,Rnum;			//记录左,右操作数; 
	while (*op)				//循环指针op,直到找到结束符'\0'结束; 
	{
		//如果此时是操作数,循环判断下一位是否是数字; 
		if (*op >= '0' and *op <= '9')
		{
			char num = 0; 
			//eg:读入数据是19,则从左到右读取:1*10+9; 
			while (*op >= '0' and *op <= '9')
			{
				num = *op - '0' + num * 10;
				*op++;
			}
			InsertStack(Snum,num);		//将操作数入栈; 
			*op--;						//恢复上一个指针指向; 
		}else if (*op == '+' or *op == '-' or *op == '*' or *op == '/' or *op == '(' or *op == ')') 
		{
			//比较操作大小,再考虑是否入栈或者进行计算;
			if (!EmptyStack(Schar))				//栈不为空; 
			{	
				GetStack(Schar, topstr);		//获取栈顶操作符; 
				Compare(*op, topstr, result);
				switch (result) 
				{
					case '>':
						//弹出栈顶操作符,进行运算;
						DeleteStack(Schar,topstr);
						if (!DeleteStack(Snum,Rnum))
						{
							printf("右操作数匹配失败。\n");
							return 1;
						}
						if (!DeleteStack(Snum,Lnum))
						{
							printf("左操作数匹配失败。\n");
							return 1;
						}						
						if (!Operation(Lnum,Rnum,topstr))
							return 1;
						InsertStack(Snum,Lnum);		//将计算后的结果重新放入操作数栈;	
						InsertStack(Schar,*op);		//将操作符放入操作符栈; 
						break;
					case '<':
						InsertStack(Schar, *op);	//将操作符入栈;
						break;
					case '=':
						//弹出栈顶操作符,进行运算,直到找到‘(’;
						GetStack(Schar,topstr);		//读取栈顶操作符; 
						while(topstr != '(') 
						{
							DeleteStack(Schar,topstr);
							if (!DeleteStack(Snum,Rnum))
							{
								printf("右操作数匹配失败。\n");
								return 1;
							}
							if (!DeleteStack(Snum,Lnum))
							{
								printf("左操作数匹配失败。\n");
								return 1;
							}						
							if (!Operation(Lnum,Rnum,topstr))
								return 1;
							InsertStack(Snum,Lnum);		//将计算后的结果重新放入操作数栈;							
							GetStack(Schar,topstr);		//读取栈顶操作符;
						}
						DeleteStack(Schar,topstr);
						break;
				}
			}else{
				//栈空操作符直接进栈; 
				InsertStack(Schar, *op);	//将操作符入栈;
			} 		
		}else if(*op != ' ')				//完善程序的健壮性,不是空格符报错; 
		{
			printf("发现不法符号!退出程序。\n");
			return 1; 
		}	 
		*op++;
	}
	while(!EmptyStack(Schar)) 
	{
		//弹出栈顶操作符,进行运算;
		DeleteStack(Schar,topstr);
		if (!DeleteStack(Snum,Rnum))
		{
			printf("右操作数匹配失败。\n");
			return 1;
		}
		if (!DeleteStack(Snum,Lnum))
		{
			printf("左操作数匹配失败。\n");
			return 1;
		}						
		if (!Operation(Lnum,Rnum,topstr))
			return 1;
		InsertStack(Snum,Lnum);		//将计算后的结果重新放入操作数栈;
	}
	DeleteStack(Snum,topstr);
	printf("%d",topstr);	
	return 0;
}


结果

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值