45 栈 stack

1 栈的顺序存储结构

通过线性表来实现

seqlist.h

#ifndef __MY_SEQLIST_H__
#define __MY_SEQLIST_H__

typedef void SeqList;
typedef void SeqListNode;

// 创建并且返回一个空的线性表
SeqList* SeqList_Create(int capacity);

// 销毁一个线性表list
void SeqList_Destory(SeqList* list);

// 将一个线性表list中的所有元素清空,线性表回到创建时的初始状态
void SeqList_Clear(SeqList* list);

// 返回一个线性表list中的元素个数
int SeqList_Length(SeqList* list);

int SeqList_Capacity(SeqList* list);

// 向一个线性表list的pos位置中插入新元素node
int SeqList_Insert(SeqList* list, SeqListNode* node, int pos);

// 获取一个线性表list的pos位置处的元素
SeqListNode* SeqList_Get(SeqList* list, int pos);

// 删除一个线性表list的pos处元素,返回值为被删除的元素,NULL表示删除失败
SeqListNode* SeqList_Delete(SeqList* list, int pos);

#endif 

seqstack.h

// seqstack.h

#ifndef _MY_SEQSTACK_H_
#define _MY_SEQSTACK_H_

#include"seqlist.h"

typedef void SeqStack;

SeqStack* SeqStack_Create(int capacity);

void SeqStack_Destory(SeqStack* stack);

void SeqStack_Clear(SeqStack* stack);

void SeqStack_Push(SeqStack* stack, void* item);

void* SeqStack_Pop(SeqStack* stack);

void* SeqStack_Top(SeqStack* stack);

int SeqStack_Size(SeqStack* stack);

int SeqStack_Capacity(SeqStack* stack);

#endif // !_MY_SEQSTACK_H_

seqlist.c

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include"seqlist.h"

//结构体套一级指针
typedef struct _tag_SeqList {
	int length;
	int capacity;
	unsigned int** node;	//int *node[] 指针数组
}TSeqList;

SeqList* SeqList_Create(int capacity) {
	TSeqList* tmp = NULL;
	tmp = (TSeqList*)malloc(sizeof(TSeqList));
	if (tmp == NULL) {
		printf("func SeqList_Create() error");
		return NULL;
	}

	memset(tmp, 0, sizeof(TSeqList));

	//根据capacity大小分配节点空间
	tmp->node = (unsigned int**)malloc(sizeof(unsigned int*) * capacity);
	if (tmp->node == NULL) {
		printf("func SeqList_Create()  tmp->node error  ");
		return NULL;
	}

	tmp->capacity = capacity;
	tmp->length = 0;

	return tmp;
}

// 销毁一个线性表list
void SeqList_Destory(SeqList* list) {
	TSeqList* tlist = NULL;
	if (list == NULL) {
		return;
	}
	tlist = (TSeqList*)list;
	if (tlist->node != NULL) {
		free(tlist->node);
	}
	free(tlist);
}

// 将一个线性表list中的所有元素清空,线性表回到创建时的初始状态
void SeqList_Clear(SeqList* list) {
	TSeqList* tlist = NULL;
	if (list == NULL) {
		return;
	}
	tlist = (TSeqList*)list;
	tlist->length = 0;
}

// 返回一个线性表list中的元素个数
int SeqList_Length(SeqList* list) {
	TSeqList* tlist = NULL;
	if (list == NULL) {
		return -1;
	}
	tlist = (TSeqList*)list;
	return tlist->length;
}

int SeqList_Capacity(SeqList* list) {
	TSeqList* tlist = NULL;
	if (list == NULL) {
		return -1;
	}
	tlist = (TSeqList*)list;
	return tlist->capacity;
}

// 向一个线性表list的pos位置中插入新元素node
int SeqList_Insert(SeqList* list, SeqListNode* node, int pos) {
	int i = 0, ret = 0;
	TSeqList* tlist = NULL;
	if (list == NULL || node==NULL || pos < 0) {
		ret = -1;
		printf("SeqList_Insert() error : %d\n", ret);
		return ret;
	}

	tlist = (TSeqList*)list;

	//判断是不是链表空间满了
	if (tlist->length == tlist->capacity) {
		ret = -2;
		printf("SeqList_Insert() tlist->length == tlist->capacity error : %d\n", ret);
		return ret;

	}

	// 容错修正	长度为6,容量为20, 在pos=10插入,可以改为插入7位置
	if (pos >= tlist->length) {
		pos = tlist->length;
	}

	// 元素后移
	for (i = tlist->length; i > pos; i--) {
		tlist->node[i] = tlist->node[i-1];
	}
	// 元素插入
	tlist->node[i] = node;
	tlist->length++;
	return 0;
}

// 获取一个线性表list的pos位置处的元素
SeqListNode* SeqList_Get(SeqList* list, int pos) {
	int i = 0;
	SeqListNode* ret = 0;
	TSeqList* tlist = NULL;
	if (list == NULL ||  pos < 0) {
		printf("SeqList_Get() error : %d\n", ret);
		return NULL;
	}

	tlist = (TSeqList*)list;
	ret = (SeqListNode*)tlist->node[pos];
	return ret;
}

// 删除一个线性表list的pos处元素,返回值为被删除的元素,NULL表示删除失败
SeqListNode* SeqList_Delete(SeqList* list, int pos) {
	int i = 0;
	SeqListNode* ret = 0;
	TSeqList* tlist = NULL;
	if (list == NULL || pos < 0) {
		printf("SeqList_Delete() error : %d\n", ret);
		return NULL;
	}
	tlist = (TSeqList*)list;

	ret = (SeqListNode*)tlist->node[pos];

	for (i = pos + 1; i < tlist->length; i++) {
		tlist->node[i-1] = tlist->node[i];
	}
	tlist->length--;
	return ret;
}

seqstack.c

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"seqstack.h"
#include"seqlist.h"

// 创建栈相当于创建线性表
SeqStack* SeqStack_Create(int capacity) {
	return SeqList_Create(capacity);
}

// 销毁栈相当于销毁线性表
void SeqStack_Destory(SeqStack* stack) {
	SeqList_Destory(stack);
}

// 清空栈相当于清空线性表
void SeqStack_Clear(SeqStack* stack) {
	SeqList_Clear(stack);
}

// 压入栈 相当于链表尾部插入元素
void SeqStack_Push(SeqStack* stack, void* item) {
	SeqList_Insert(stack, item, SeqStack_Size(stack));	// 尾插法
}

// 弹出栈 相当于取出链表尾部元素 
void* SeqStack_Pop(SeqStack* stack) {
	return SeqList_Delete(stack, SeqStack_Size(stack) - 1);
} 

// 获取栈 相当于获取链表尾部元素 
void* SeqStack_Top(SeqStack* stack) {
	return SeqList_Get(stack, SeqStack_Size(stack) - 1);
}

// 获取栈的大小 相当于获取链表的实际长度
int SeqStack_Size(SeqStack* stack) {
	return SeqList_Length(stack);
}

// 获取栈的容量 相当于获取链表的容量
int SeqStack_Capacity(SeqStack* stack) {
	return SeqList_Capacity(stack);
}

源.c

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"seqstack.h"
#include"seqlist.h"

void main() {
	int i = 0;
	int a[10] = { 0 };

	SeqStack* stack = NULL;
	stack = SeqStack_Create(10);
	if (stack == NULL) {
		return;
	}

	// 遍历
	for (i = 0; i < 5; i++) {
		a[i] = i + 1;
		SeqStack_Push(stack, &(a[i]));
	}


	printf("capacity:%d \n", SeqStack_Capacity(stack));
	printf("length:%d \n", SeqStack_Size(stack));
	printf("top:%d \n", *((int*)(SeqStack_Top(stack))));

	while (SeqStack_Size(stack) > 0) {
		int tmp = *((int*)SeqStack_Pop(stack));
		printf("tmp:%d \t", tmp);
	}
	printf("\n");


}

结果

capacity:10
length:5
top:5
tmp:5   tmp:4   tmp:3   tmp:2   tmp:1

另一个例子

SqStack.h

#ifndef _SQSTACK_H
#define _SQSTACK_H

#define MAXSIZE 50
typedef struct _SQSTACK
{
	int top;	// 栈顶指针
	unsigned int data[MAXSIZE];
}SqStack;

// 初始化,建立一个空栈S
void InitStack(SqStack *S);

// 将栈清空
void ClearStack(SqStack *S);

// 若栈为空则返回true,否则返回false
int StackEmpty(SqStack S);

// 若栈存在且非空,用e返回S的栈顶元素
void GetTop(SqStack S, void **e);

// 若栈S存在,插入新元素e到栈S中并成为其栈顶元素
void Push(SqStack *S, void *e);

// 删除栈S中的栈顶元素,并用e返回其值
void Pop(SqStack *S, void **e);

// 返回栈S的元素个数
int StackLength(SqStack S);

#endif // _SQSTACK_H

SqStack.c

#include "SqStack.h"
#include <string.h>

void InitStack(SqStack *S)
{
	// 空栈
	S->top = -1;
	memset(S->data, 0, sizeof(S->data));
}

void ClearStack(SqStack *S)
{
	S->top = -1;
}

int StackEmpty(SqStack S)
{
	if (S.top == -1)
	{
		return 1;
	}
	return 0;
}

void GetTop(SqStack S, void **e)
{
	// 栈为空
	if (S.top == -1)
	{
		return;
	}
	*e = (void*)S.data[S.top];
}

void Push(SqStack *S, void *e)
{
	// 栈已经满了
	if (S->top == MAXSIZE - 1)
	{
		return;
	}
	// 栈顶上移
	S->top++;
	// 赋值
	S->data[S->top] = (unsigned int)e;
}

void Pop(SqStack *S, void **e)
{
	// 栈为空
	if (S->top == -1)
	{
		return;
	}
	// 赋值
	*e = S->data[S->top];
	// 栈顶指针下移
	S->top--;
}

int StackLength(SqStack S)
{
	return S.top + 1;
}

main.c

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


typedef struct stu
{
	int id;
	int age;
}Student;

void main()
{
	Student stu[10];

	// 定义栈变量
	SqStack st;
	// 初始化栈
	InitStack(&st);
	// 压栈
	for (int i = 0; i < 10; ++i)
	{
		stu[i].id = i;
		stu[i].age = i + 20;
		// 压栈
		Push(&st, (void*)&stu[i]);
	}

	printf("stack size = %d\n", StackLength(st));

	// 出栈
	while (StackEmpty(st) != 1)
	{
		Student* p;
		// 取栈顶元素
		GetTop(st, (void**)&p);
		printf("stack top elem id = %d, age=%d\n", p->id, p->age);

		// 删除栈顶元素
		Pop(&st, (void*)&p);
		printf("Delete stack elem id = %d, age=%d\n", p->id, p->age);
	}
	system("pause");
}

结果

stack size = 10
stack top elem id = 9, age=29
Delete stack elem id = 9, age=29
stack top elem id = 8, age=28
Delete stack elem id = 8, age=28
stack top elem id = 7, age=27
Delete stack elem id = 7, age=27
stack top elem id = 6, age=26
Delete stack elem id = 6, age=26
stack top elem id = 5, age=25
Delete stack elem id = 5, age=25
stack top elem id = 4, age=24
Delete stack elem id = 4, age=24
stack top elem id = 3, age=23
Delete stack elem id = 3, age=23
stack top elem id = 2, age=22
Delete stack elem id = 2, age=22
stack top elem id = 1, age=21
Delete stack elem id = 1, age=21
stack top elem id = 0, age=20
Delete stack elem id = 0, age=20

2 栈的链式存储

链式存储时,对头部元素进行操作比较方便 用链表实现栈

linklist.h

#ifndef _MYLINKLIST_H_
#define _MYLINKLIST_H_

typedef void LinkList;
/*
typedef struct _tag_LinkListNode LinkListNode;
struct _tag_LinkListNode{
	LinkListNode *next;
}

*/

typedef struct _tag_LinkListNode {
	struct _tag_LinkListNode* next;
}LinkListNode;

LinkList* LinkList_Create();

void LinkList_Destory(LinkList* list);

void LinkList_Clear(LinkList* list);

int LinkList_Length(LinkList* list);

int LinkList_Insert(LinkList* list, LinkListNode* node, int pos);

LinkListNode* LinkList_Get(LinkList* list, int pos);

LinkListNode* LinkList_Delete(LinkList* list, int pos); 

#endif

linkstack.h

#ifndef _MY_LINKSTACK_H_
#define _MY_LINKSTACK_H_

typedef void LinkStack;

LinkStack* LinkStack_Create();

void LinkStack_Destroy(LinkStack* stack);

void LinkStack_Clear(LinkStack* stack);

int LinkStack_Push(LinkStack* stack, void* item);

void* LinkStack_Pop(LinkStack* stack);

void* LinkStack_Top(LinkStack* stack);

int LinkStack_Size(LinkStack* stack);

#endif //_MY_LINKSTACK_H_

linklist.c

#include<stdlib.h>
#include<string.h>
#include<stdio.h>
#include"linklist.h"


typedef struct _tag_LinkList {
	LinkListNode head;
	int length;
}TLinkList;

LinkList* LinkList_Create() {
	TLinkList* ret = NULL;
	ret = (TLinkList*)malloc(sizeof(TLinkList));
	memset(ret, 0, sizeof(TLinkList));
	ret->length = 0;
	ret->head.next = NULL;
	
	return ret;
}

void LinkList_Destory(LinkList* list) {
	if (list != NULL) {
		free(list);
		list = NULL;
	}
	return;
}

// 让链表变为初始值
void LinkList_Clear(LinkList* list) {
	TLinkList* tList = 0;
	if (list == NULL) {
		return;
	}
	tList = (TLinkList*)list;

	tList->length = 0;
	tList->head.next = NULL;

	return;
}

int LinkList_Length(LinkList* list) {
	TLinkList* tList = 0;
	if (list == NULL) {
		return;
	}
	tList = (TLinkList*)list;
	return tList->length;
}

int LinkList_Insert(LinkList* list, LinkListNode* node, int pos) {
	int ret = 0, i = 0;
	TLinkList* tList = NULL;
	LinkListNode* current = NULL;

	if (list == NULL || node == NULL || pos < 0) {
		ret = -1;
		printf("LinkList_Insert error %d\n",ret); 
		return ret;
	}
	
	tList = (TLinkList*)list;
	current = &(tList->head);

	for (i = 0; i < pos && current->next != NULL; i++) {
		current = current->next;
	}
	// 1 node连接后续链表
	node->next = current->next;
	// 2 前面链表连接新的链表
	current->next = node;

	tList->length++;
	return ret;
}

LinkListNode* LinkList_Get(LinkList* list, int pos) {
	int i = 0;
	TLinkList* tList = NULL;
	LinkListNode* current = NULL;

	if (list == NULL || pos < 0) {
		printf("LinkList_Get error %d\n");
		return NULL;
	}

	tList = (TLinkList*)list;
	current = &(tList->head);	//辅助指针变量指向链表头部

	for (i = 0; i < pos && current->next != NULL; i++) {
		current = current->next;
	}
	return current->next;
}

LinkListNode* LinkList_Delete(LinkList* list, int pos) {
	int i = 0;
	TLinkList* tList = NULL;
	LinkListNode* current = NULL;
	LinkListNode* ret = NULL;

	if (list == NULL || pos < 0) {

		printf("LinkList_Delete error \n");
		return NULL;
	}

	tList = (TLinkList*)list;
	current = &(tList->head);

	for (i = 0; i < pos && current->next != NULL; i++) {
		current = current->next;
	}
	// 缓存被删除节点
	ret = current->next;
	current->next = ret->next; 

	tList->length--;
	return ret;
}

linkstack.c

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"linkstack.h"
#include"linklist.h"

// 链表业务节点
typedef struct Teacher {
	LinkListNode node;
	void* item;	//栈业务节点
}Teacher;

// 链表业务节点
typedef struct _tag_LinkStackNode {
	LinkListNode node;
	void* item;	//栈业务节点
}TLinkListNode;


// 创建栈 相当于创建表
LinkStack* LinkStack_Create() {
	return LinkList_Create();
}

// 销毁栈相当于销毁线性表
void LinkStack_Destroy(LinkStack* stack) {
	LinkStack_Clear(stack);
	LinkList_Destory(stack);
}

// 清空栈相当于清空线性表 涉及到栈元素生命周期管理
// 所有入栈节点都是malloc,若要清空栈,把栈中元素弹出,并且释放节点
void LinkStack_Clear(LinkStack* stack) {
	if (stack == NULL) {
		return;
	}
	while (LinkStack_Size(stack) > 0) {
		LinkStack_Pop(stack);
	}
}

// 栈添加元素相当于线性表头部插入元素
// *item栈的业务节点转化为链表业务节点
int LinkStack_Push(LinkStack* stack, void* item) {
	TLinkListNode* tmp = NULL;
	int ret = 0;

	tmp = (TLinkListNode*)malloc(sizeof(TLinkListNode));
	if (tmp == NULL) {
		return -1;
	}
	memset(tmp, 0, sizeof(TLinkListNode));
	tmp->item = item;
	ret = LinkList_Insert(stack, (LinkListNode*)tmp, 0);
	if (ret != 0) {
		printf("func LinkList_Insert error\n");
		if (tmp != NULL) {
			free(tmp);
		}
		return ret;
	}
	return 0;


}

// 从栈中弹出元素 相当于 从线性表的头部删除元素
// 把线性表 业务节点 转化成 栈的业务节点
void* LinkStack_Pop(LinkStack* stack) {
	void* item = NULL;	// 栈的业务节点
	TLinkListNode* tmp = NULL; 
	tmp = (TLinkListNode*)LinkList_Delete(stack, 0);
	if (tmp == NULL) {
		return NULL;
	}
	item = tmp->item;
	// 因为LinkList_Insert分配内存 所以LinkList_Delete释放内存
	free(tmp);
	return item;

}

// 获取栈顶元素相当于获取线性表的0号位置
void* LinkStack_Top(LinkStack* stack) {
	TLinkListNode* tmp = NULL;
	tmp = (TLinkListNode*)LinkList_Get(stack, 0);
	if (tmp == NULL) {
		return NULL;
	}
	return tmp->item;
}

// 求栈的大小相当于求线性表len
int LinkStack_Size(LinkStack* stack) {
	return LinkList_Length(stack);
}

源.c

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"linkstack.h"

void main() {
	int i = 0;
	int a[10] = { 0 };

	LinkStack* stack = NULL;
	stack = LinkStack_Create();
	if (stack == NULL) {
		return;
	}

	// 添加元素
	for (i = 0; i < 5; i++) {
		a[i] = i + 1;
		LinkStack_Push(stack, &a[i]);
	}

	// 获取栈的基本属性
	printf("len:%d \n", LinkStack_Size(stack));
	printf("top:%d \n", *((int*)(LinkStack_Top(stack))));

	// 删除栈元素
	while (LinkStack_Size(stack) > 0) {
		int tmp = *((int*)LinkStack_Pop(stack));
		printf("tmp=%d ", tmp);
	}

	// 销毁栈
	LinkStack_Destroy(stack);
}

结果

len:5
top:5
tmp=5 tmp=4 tmp=3 tmp=2 tmp=1

3 栈的应用

案例1:就近匹配

需要上面的linkstack.h依赖文件

main.c

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"linkstack.h"
int isLeft(char c) {
	int ret = 0;

	switch (c) {
	case'<':
	case'(':
	case'[':
	case'{':
	case'\'':
	case'\"':
		ret = 1;
		break;
	default:
		ret = 0;
		break;
	}
	return ret;
}

int isRight(char c) {
	int ret = 0;

	switch (c) {
	case'>':
	case')':
	case']':
	case'}':
	case'\'':
	case'\"':
		ret = 1;
		break;
	default:
		ret = 0;
		break;
	}
	return ret;
}

int match(char left, char right) {
	int ret = 0;
	switch (left)
	{
	case'<': 
		ret = (right == '>');
		break;
	case'(':
		ret = (right == ')');
		break;
	case'[':
		ret = (right == ']');
		break;
	case'{':
		ret = (right == '}');
		break;
	case'\'':
		ret = (right == '\'');
		break;
	case'\"':
		ret = (right == '\"');
		break;
	default:
		ret = 0;
		break;
	}
}

int scanner(const char* code) {
	LinkStack* stack = LinkStack_Create();
	int ret = 0;
	int i = 0;

	while (code[i] != '\0') {
		if (isLeft(code[i])) {
			LinkStack_Push(stack, (void*)(code + i));	//&code[i]
		}
		if (isRight(code[i])) {
			char* c = (char*)LinkStack_Pop(stack);

			if ((c == NULL) || !match(*c, code[i])) {
				printf("%c does not match!\n", code[i]);
				ret = 0;
				break;
			}
		}
		i++;
	}
	if (LinkStack_Size(stack) == 0 && (code[i] == '\0')){
		printf("Succeed!\n");
		ret = 1;
	}
	else {
		printf("Invalid code\n");
		ret = 0;
	}

	LinkStack_Destroy(stack);
	return ret;
}

void main() {
	const char* code = "#include <stdio.h> int main() { int a[4][4]; int (*p)[4]; p = a[0]; return 0;}";
	scanner(code);
}

案例2:中缀表达式和后缀表达式

中缀转后缀:

遍历中缀表达式中的数字和符号

对于数字:直接输出

对于符号:

左括号:进栈

运算符号:与栈顶符号进行优先级比较

若栈顶符号优先级低:此符合进栈 (默认栈顶若是左括号,左括号优先级最低)

若栈顶符号优先级不低:将栈顶符号弹出并输出,之后进栈

右括号:将栈顶符号弹出并输出,直到匹配左括号

遍历结束:将栈中的所有符号弹出并输出

中缀转后缀

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"linkstack.h"

int isNumber(char c) {
	return('0' <= c) && (c <= '9');
}

int isOperator(char c) {
	return(c == '+') || (c == '-') || (c == '*') || (c == '/');
}

int isLeft(char c) {
	return(c == '(');
}

int isRight(char c) {
	return(c == ')');
}

int priority(char c) {
	int ret = 0;
	if ((c == '+') || (c == '-')) {
		ret = 1;
	}

	if ((c == '*') || (c == '/')) {
		ret = 2;
	}
	return ret;
}

void output(char c) {
	if (c != '\0') {
		printf("%c", c);
	}
}


void transform(const char* exp) {
	int i = 0;
	LinkStack* stack = LinkStack_Create();

	while (exp[i] != '\0') {
		if (isNumber(exp[i])) {
			output(exp[i]);
		}
		else if (isOperator(exp[i])) {
			while (priority(exp[i]) <= priority((char)(int)LinkStack_Top(stack))) {
				output((char)(int)LinkStack_Pop(stack));
			}
			LinkStack_Push(stack,(void *)(int)exp[i]);
		}
		else if (isLeft(exp[i])) {
			LinkStack_Push(stack, (void*)(int)exp[i]);
		}
		else if (isRight(exp[i])) {
			// char c = '\0'
			while (!isLeft((char)(int)LinkStack_Top(stack))) {
				output((char)(int)LinkStack_Pop(stack));
			}
			LinkStack_Pop(stack);
		}
		else {
			printf("Invalid expression!");
			break;
		}
		i++;
	}
	while (LinkStack_Size(stack) > 0&&exp[i]=='\0') {
		output((char)(int)LinkStack_Top(stack));
		LinkStack_Pop(stack);
	}
}


void main() {
	transform("8+(3-1)*5");
}

结果

831-5*+

后缀转中缀

遍历后缀表达式中的数字和符号

对于数字:进栈

对于符号:

从栈中弹出右操作数

从栈中弹出左操作数

根据符号进行运算

将运算结果压入栈中

遍历结束:栈中的唯一数字为计算结果

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"linkstack.h"
int isNumber3(char c) {
	return('0' <= c) && (c <= '9');
}

int isOperator3(char c) {
	return(c == '+') || (c == '-') || (c == '*') || (c == '/');
}

int value(char c) {
	return (c - '0');
}

int express(int left, int right, char op) {
	int ret = 0;

	switch (op) {
	case'+':
		ret = left + right;
		break;
	case'-':
		ret = left - right;
		break;
	case'*':
		ret = left * right;
		break;
	case'/':
		ret = left / right;
		break;
	default:
		break;
	}
	return ret;
}


int compute(const char* exp) {
	LinkStack* stack = LinkStack_Create();
	int ret = 0;
	int i = 0;

	while (exp[i] != '\0') {
		if (isNumber3(exp[i])) {
			LinkStack_Push(stack, (void*)value(exp[i]));
		}
		else if (isOperator3(exp[i])) {
			int right = (int)LinkStack_Pop(stack);
			int left = (int)LinkStack_Pop(stack);
			int result = express(left, right, exp[i]);

			LinkStack_Push(stack, (void*)result);
		}
		else {
			printf("Invalid expression!");
			break;
		}
		i++;
	}

	if (LinkStack_Size(stack) == 1 && (exp[i] == '\0')) {
		ret = (int)LinkStack_Pop(stack);
	}
	else {
		printf("Invaild expression!");
	}
	LinkStack_Destroy(stack);

	return ret;
}

void main() {
	printf("8+(3-1)*5 = %d\n", compute("831-5*+"));
}

结果

8+(3-1)*5 = 18

#include <iostream>
#include <stack>
using namespace std;

bool isNumber(char c)
{
	return c >= '0' && c <= '9';
}

bool isLeft(char c)
{
	return c == '(';
}

bool isRight(char c)
{
	return c == ')';
}


bool isOperator(char c)
{
	return c == '+' || c == '-' || c == '*' || c == '/';
}

int priority(char c)
{
	int ret = 0;
	switch (c)
	{
	case '+':
	case '-':
		ret = 1;
		break;
	case '*':
	case '/':
		ret = 2;
		break;
	default:
		break;
	}
	return ret;
}

void Transform(const char* p)
{
// 	int i = 0;
// 	stack<char> st;
// 	while (p[i] != '\0')
// 	{
// 		// 数字
// 		if (isNumber(p[i]))
// 		{
// 			// 直接输出
// 			cout << p[i];
// 		}
// 		// 左括号
// 		else if (isLeft(p[i]))
// 		{
// 			// 进栈
// 			st.push(p[i]);
// 		}
// 		// 运算符
// 		else if (isOperator(p[i]))
// 		{
// 			// 优先级的比较 
// 			while (!st.empty() && priority(st.top()) >= priority(p[i]))
// 			{
// 				// 输出
// 				cout << st.top();
// 				st.pop();
// 			}
// 			// 进栈
// 			st.push(p[i]);
// 		}
// 		// 右括号
// 		else if (isRight(p[i]))
// 		{
// 			// 如果不是左括号, 弹出并输出
// 			while (!isLeft(st.top()))
// 			{
// 				cout << st.top();
// 				st.pop();
// 			}
// 			// 弹出左括号
// 			st.pop();
// 		}
// 		i++;
// 	}
// 
// 	while (!st.empty())
// 	{
// 		cout << st.top();
// 		st.pop();
// 	}

	/*
	中缀转后缀算法:
	遍历中缀表达式中的数字和符号:
		对于数字:直接输出
		对于符号:
			左括号:进栈
			运算符号:与栈顶符号进行优先级比较
					若栈顶符号优先级低:此符号进栈
					(默认栈顶若是左括号,左括号优先级最低)
					若栈顶符号优先级不低:将栈顶符号弹出并输出,之后进栈
			右括号:将栈顶符号弹出并输出,直到匹配左括号
	遍历结束:将栈中的所有符号弹出并输出
	*/
	int i = 0;
	stack<char> st;
	while (p[i] != '\0')
	{
		// 数字
		if (isNumber(p[i]))
		{
			// 直接输出
			cout << p[i];
		}
		// 左括号
		else if (isLeft(p[i]))
		{
			// 进栈
			st.push(p[i]);
		}
		// 运算符
		else if (isOperator(p[i]))
		{
			// 优先级比较
			// 当前字符优先级低, 直接进栈
// 			if (priority(st.top() < priority(p[i])))
// 			{
// 				// 直接进栈
// 				st.push(p[i]);
// 			}
			// 若栈顶符号优先级不低
			while (!st.empty() && priority(st.top()) >= priority(p[i]))
			{
				// 输出
				cout << st.top();
				// 弹出栈顶
				st.pop();
			}
			// 当前字符进栈
			st.push(p[i]);
		}
		else if (isRight(p[i]))
		{
			// 寻找左括号
			while (!st.empty() && !isLeft(st.top()))
			{
				// 输出
				cout << st.top();
				// 弹出栈顶符号
				st.pop();
			}
			if (!st.empty())
			{
				// 弹出左括号
				st.pop();
			}
		}
		i++;
	}

	// 遍历结束
	if (p[i] == '\0')
	{
		// 遍历结束
		while (!st.empty())
		{
			// 输出
			cout << st.top();
			// 弹出
			st.pop();
		}
	}
	else
	{
		cout << "遍历没有完成..." << endl;
	}
}

// 后缀表达式的计算
/*
	计算规则
	遍历后缀表达式中的数字和符号
	对于数字:进栈
	对于符号:
	从栈中弹出右操作数
	从栈中弹出左操作数
	根据符号进行运算
	将运算结果压入栈中
	遍历结束:栈中的唯一数字为计算结果
*/

int express(int left, int right, char op)
{
	int ret = -1000000;
	switch (op)
	{
	case '+':
		ret = left + right;
		break;
	case '-':
		ret = left - right;
		break;
	case '*':
		ret = left * right;
		break;
	case '/':
		ret = left / right;
		break;
	default:
		break;
	}
	return ret;
}


int compute(const char* p)
{
	int i = 0;
	stack<int> st;
	while (p[i] != '\0')
	{
		// 数字
		if (isNumber(p[i]))
		{
			// 进栈
			st.push(p[i]-'0');
		}
		else if (isOperator(p[i]))
		{
			// 右操作数
			int right = st.top();
			st.pop();
			// 左操作数
			int left = st.top();
			st.pop();
			// 计算
			int res = express(left, right, p[i]);
			// 结果压入栈中
			st.push(res);
		}
		i++;
	}

	if (p[i] == '\0' && st.size() == 1)
	{
		return st.top();
	}
	else
	{
		return -100000;
	}
}

void main()
{
	Transform("8+(3-1)*5");

	cout << endl;
	cout << "计算结果: " << compute("831-5*+") << endl;

	system("pause");
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值