小白学算法1.1——栈
标签: 小白学算法
1.什么是栈
先解释一下什么是算法和数据结构吧~
- 简单地说,算法就是解决一个问题的方法。有一个很流行的笑话:请问如何把大象放到冰箱里?答:第一步,打开冰箱;第二步,把大象塞进去;第三步,关上冰箱。当然,这是一个非常糟糕甚至失败的算法,因为谁都知道在第二步中大象是塞不进冰箱的,大象相对于冰箱来说实在是太大了。
- 数据结构是算法的副产品,因为大部分的算法都需要适当的组织数据,而为了组织数据就产生了数据结构。简单地说,数据结构就是就是计算机存储和组织数据的方式。
现在我们来看一下什么是栈吧~
- 栈是一种非常常见的数据结构,遵循后进先出(last in first out)的规则。可以把栈看做羽毛球筒,数据看成羽毛球,羽毛球可以放在羽毛球筒里面,显而易见,先放进去的羽毛球只能后取出来;后放进去的羽毛球只能先取出来。
- 栈常见的实现方法有数组和链表
- 栈常见的操作的有三种:
- 入栈(push),向栈添加一个元素
- 出栈(pop),删除栈中最近添加的一个元素并将其作为操作的返回值
- 检查是否为空(isEmpty)
2.实现一个栈
为了简单快速的说明栈的作用,本文将使用数组的方式来实现栈。首先需要定义一个全局数组和全局const变量,数组用来存储数据,const变量用来定义栈的大小,再定义一个变量用来记录栈顶元素的位置。
const int N = 20;
int Value[N] = {0};//初始化为0
int valPos = 0;
2.1入栈
void push_val(int data)
{
Value[valPos++] = data;//valPos指向栈顶元素的下一个位置
}
2.2出栈
int pop_val()
{
return Value[--valPos];
}
2.3检查是否为空
bool is_val_empty()
{
return !valPos;
}
3.利用双栈求表达式的值
Dijkstra在20世纪60年代发明了一个非常简单的计算算术表达式的算法,该算法需要两个栈来完成计算。一个栈用来存放运算符,一个栈用来保存操作数。表达式由括号、运算符和数值组成。为了简单起见,所有的单元都需要用括号括起来,如(1+((2+3)*(4*5)))
算法流程如下:
- 读入一个字符
- 如果该字符是左括号,忽略
- 如果该字符是数值,压入操作数栈
- 如果该字符是操作符,压入操作符栈
- 如果该字符是右括号,弹出一个操作符和两个数值,运算之并将运算结果压入操作数栈
- 重复1~5直到把表达式的字符读完
- 操作数栈最后只会剩下一个元素,就是该表达式的运算结果
C语言实现如下(输入的数值只能是10以内):
#include "stdafx.h"
#include <STDIO.H>
/*************数值栈*************/
const int N = 20;
int Value[N] = {0};//初始化为0
int valPos = 0;
void push_val(int data)
{
Value[valPos++] = data;
}
int pop_val()
{
return Value[--valPos];
}
bool is_val_empty()
{
return !valPos;
}
/*************符号栈*************/
int Operation[N] = {0};//初始化为0
int opePos = 0;
void push_ope(int data)
{
Operation[opePos++] = data;
}
int pop_ope()
{
return Operation[--opePos];
}
bool is_ope_empty()
{
return !opePos;
}
int main(int argc, char* argv[])
{
printf("欢迎访问我的博客:http://blog.csdn.net/xuelabizp\n");
printf("请输入算术表达式:\n");
char ch;
while((ch=getchar()) != '\n')
{
switch(ch)
{//读取字符,如果是运算符则入栈
case '(': ;
break;
case '+':
case '-':
case '*':
case '/': push_ope(ch);
break;
case ')':
{
//如果字符为右括号,弹出运算符和操作数,计算结果并入栈
int myVal = pop_val();
int myOpe = pop_ope();
switch (myOpe)
{
case '+': myVal = pop_val() + myVal;
break;
case '-': myVal = pop_val() - myVal;
break;
case '*': myVal = pop_val() * myVal;
break;
case '/': myVal = pop_val() / myVal;
break;
}
push_val(myVal);
}
break;
default: push_val(ch - '0');//把字符转化为真正的数值
}
}
printf("The calculation is %d\n", pop_val());
return 0;
}
运行结果:
4.总结
- 栈是非常常见的数据结构,所以主流语言的标准库都有栈模板,使用起来非常的方便,而且功能更加的丰富。但是,对于新手来说最好能自己实现一次栈,尤其是通过链表来实现栈,不仅非常有意思还能加深对栈的理解
- 如果不用把每一个括号都打上的话其实也非常得简单,不要忽略左括号即可
- 本节的代码有一个小小的问题,不知道有人能发现不:-P