数据结构--2.1 栈

今天敲得是栈。栈是一种特殊的存储方式,这种方式就像往箱子里面放东西,先放进去的后拿出来,后放进去的先拿出来。老师是用数组的形式实现,我用链表的形式实现。来看代码吧。

老师版

创建

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

#define STACK_MAX_SIZE 10

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

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

我们在结构体里设置了一个名为top的变量,它的作用就是始终指向最顶部,也就是最后放进去的元素。

压栈

在这里插入图片描述
这副动态图很形象的解释了压榨,每放入一个元素,都使top往后移一位,使之始终指向栈顶的元素。

void push(CharStackPtr paraStackPtr,int paraValue)
{
	if((paraStackPtr->top)>=STACK_MAX_SIZE -1)
	{
		printf("Can not push element:stack is full.");
		return;
	}

	paraStackPtr->top ++;

	paraStackPtr->data[paraStackPtr->top] = paraValue;
}

出栈

在这里插入图片描述
出栈操作也十分简单,元素移出,让top前移。

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

测试代码

void pushPopTest() {
	char ch;
	int i;
	
    printf("---- pushPopTest begins. ----\r\n");

    CharStackPtr tempStack = CharStackInit();
    printf("After initialization, the stack is: ");
	outputStack(tempStack);

	for ( ch = 'a'; ch < 'm'; ch ++) {
		printf("Pushing %c.\r\n", ch);
		push(tempStack, ch);
		outputStack(tempStack);
	}
	for ( i = 0; i < 3; i ++) {
		ch = pop(tempStack);
		printf("Pop %c.\r\n", ch);
		outputStack(tempStack);
	}

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

int main() {
	pushPopTest();
}

运行结果

---- 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.
Can not push element:stack is full.a b c d e f g h i j
Pushing l.
Can not push element:stack is 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. ----

自己版

我自己写了链式栈的基本算法的代码,附在下方

创建

链式栈需要两个结构体,一个定义节点,另外一个定义栈顶和栈底。

typedef struct Node
{
	int data;
	struct Node *next;
}NODE,*PNODE;

typedef struct Stack
{
	PNODE pTop;
	PNODE pBottom;
}STACK,*PSTACK;

void initStack(PSTACK pS)
{
	printf("init\r\n");
	
	pS->pTop = (PNODE)malloc(sizeof(NODE));
	
	pS->pBottom = pS->pTop ;
	pS->pTop ->next=NULL;
	
	return;
}

在写创建这代码的时候,我遇到了一个令我百思不得其解的问题。因为创建其实理解起来很简单,让栈顶和栈底相等,然后栈顶指向为空即可。
一开始,我让栈顶和栈底相等是这样写的:

pS->pTop = pS->pBottom ;

但是却怎么也无法压栈和出栈,我甚至为此把所有代码重新敲了一遍。后来,再一次对我的代码的修改时我将这两者互换了位置,突然就全部都运行了。
然后我看了这一小段代码的网课,原来在我已经给pTop动态分配了内存,但是pBottom却仍然是一堆垃圾值,而我们应该给pBottom赋值并且使他们指向同一处。而把pTop赋值给pBottom才能使他们指向同一处。

压栈

void pushStack(PSTACK pS,int val)
{
	printf("push\r\n");
	
	PNODE p;
	p=(PNODE)malloc(sizeof(NODE));
	
	p->data =val;
	p->next =pS->pTop ;
	pS->pTop =p;
}

出栈

void popStack(PSTACK pS)
{
	printf("pop\r\n");
	
	PNODE p;
	p=(PNODE)malloc(sizeof(NODE));
	
	p=pS->pTop ;
	pS->pTop =p->next ;
	free(p);
	p=NULL;
}

运行结果

init
11
push
push
push
push
22
print
4 3 2 1 33
pop
print
3 2 1

总结

实际上栈的算法很好理解,无非是先进后出,后进先出八字。
在这里插入图片描述

但是栈虽然简单,却能解决生活中很多问题,比如下面的括号匹配问题。

栈的应用–括号匹配

由于栈的实现和之前的完全一样,所以这里我只列出最主要的括号匹配部分的代码。

bool bracketMatching(char* String, int Length)
{
	CharStackPtr stack = initStack();
	int i;
	
	char tempch,popch;
	pushStack(stack,'#');
	
	for(i=0;i<Length;i++)
	{
		tempch=String[i];
		
		switch(tempch)
		{
			case '(':
			case '[':
			case '{':
				pushStack(stack,tempch);
				break;
			case')':
				popch=popStack(stack);
				if(popch!='(')
				{
					return false;
				}	
				break;	
			case']':
				popch=popStack(stack);
				if(popch!='[')
				{
					return false;
				}	
				break;
			case'}':
				popch=popStack(stack);
				if(popch!='}')
				{
					return false;
				}	
				break;
			default:
				break;
		}
	}
	
	popch=popStack(stack);
	if(popch!='#')
	{
		return false;
	}
	
	return true;
}

这一段代码的逻辑思想也很简单,理解之后敲起来就十分顺手。当我们在表达式中遇到了‘(,【,}’这几个括号时,我们进行压栈操作,将这几个括号存入栈中,接着,如果我们遇到了‘),】,}’这几个括号中的一个时,我们进行出栈操作,如果此时弹出的元素和此时遇到的括号对应,就接着循环找到下一个括号,否则就返回‘0’,也就是不匹配。
在代码中,我们还设置了“#”标识符,当我们匹配结束却仍然没有弹出“#”,证明我们多了一个括号没有匹配到,也会返回“0”。
另外,代码中的变量和老师的略有差异,因为我是自己敲得,所以改变了部分变量名。

运行结果

Is the expression '[2 + (1 - 3)] * 4' bracket matching? 1
Is the expression '( )  )' bracket matching? 0
Is the expression '()()(())' bracket matching? 1
Is the expression '({}[])' bracket matching? 0
Is the expression ')(' bracket matching? 0
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言结构实现:编程实现四则运算表达式的运算。 输入说明:通过控制台输入四则运算表达式,表达式不超过40个字符,以“=”作为结束符,例如:3 + 2 *(5+2)=。 输入假设:所有操作数均为正数。 输出说明:计算结果从控制台输出给用户,结果精确到小数点后2位。或者输出错误ERROR。 1、创建运算符优级静态表,并实现运算符优级查找函数Precede(x, y)。参数x,y是四则运算符,包括+、-、*、\、(、)、=。 2、应用Precede()函数,编写程序计算中缀表达式(一般表达式)的值。 三、问题分析 采用中缀表达式求解过程中,首需要按照顺序读取数字和操作符,将它们分别保存。如果最保存的操作符优级不大于接下来保存的操作符,将一直不被调用指导上一级操作符被调用,满足进后出的数据结构,所以用来保存操作符(本实验称之为符号)。对于保存的数字,每次调用操作符时,同时将最后保存的两位数字调用,满足进后出的数据结构,所以用来保存操作符(本实验称之为数字)。运算后由下一个操作符和顶操作符的优级确定,当发现下一个符号的优级小于顶符号的优级,则需要进行顶符号的运算,此时数字的最上面两个数字恰好是该符号的运算数。 测试用例 输入(2.3*4+1.6/2)*2.1-1.3+2.1*2= 输出 The result is:23.9
05-25

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值