CXO的需求果真还在继续,深呼吸,深呼吸 .......golang
有人说数据结构是为算法服务的,我还要在加一句:数据结构和算法都是为业务服务的!!算法
CXO的需求果真不一样凡响,又让菜菜想到了新的数据结构:栈c#
栈(stack)又名堆栈,它是一种运算受限的线性表。其限制是仅容许在表的一端进行插入和删除运算。这一端被称为栈顶,相对地,把另外一端称为栈底。向一个栈插入新元素又称做进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称做出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。数组
栈做为一种数据结构,其中有几个特性须要提起你们注意:bash
在内存分布上栈是用是实现的呢?既然栈是一种线性结构,也就说能够用线性的内存分布数据结构来实现。数据结构
class MyStack
{
//数组容器
int[] container = new int[100];
//栈顶元素的索引
int TopIndex = -1;
//入栈操做
public void Push(int newValue)
{
if (TopIndex >= 99)
{
return ;
}
TopIndex++;
container[TopIndex] = newValue;
}
//出栈操做
public int Pop()
{
if (TopIndex < 0)
{
return 0;
}
var topValue = container[TopIndex];
TopIndex--;
return topValue;
}
}
复制代码
由以上能够看出,栈实际上是基于基础数据结构之上的一个具体业务形式的封装即:先进后出。并发
基于数组的栈咱们暂且只讨论未发生数组重建的场景下。不管是数组实现仍是链表实现,咱们发现栈的内部实际上是有一个指向栈顶元素的指针,不会发生遍历数组或者链表的情形,因此栈的出栈操做时间复杂度为O(1)。至于入栈,若是你看过我之前介绍数组和链表的文章,你能够知道,给一个数组下标元素赋值的操做时间复杂度为O(1),在链表头部添加一个元素的操做时间复杂度也是O(1)。因此不管是数组仍是链表实现栈,入栈操做时间复杂度也是O(1)。而且栈只有入栈出栈两种操做,比其余数据结构有N个操做方法要简单不少,也不容易出错。 至于发生数组重建,copy所有数据的过程实际上是一个顺序栈最坏的时间复杂度,由于和原数组的元素个数n有关,因此时间复杂度为O(n)app
那一个计算器怎么用栈来实现呢?其实不少编译器就是经过两个栈来实现的,其中一个栈保存操做的数,另外一个栈保存运算符。 咱们从左到右遍历表达式,当遇到数字,咱们直接压入操做数栈;当遇到操做符的时候,当前操做符与操做符栈顶的元素比较优先级(先乘除后加减的原则) 。若是当前运算符比栈顶运算符优先级高,那说明不须要执行栈顶运算符运算,咱们直接将当前运算符也入栈; 若是当前运算符比栈顶运算符优先级低,那说明该执行栈顶运算符的运算了。 而后出栈运算符栈顶元素,数据栈顶两个元素,而后进行相关运算,而后把运算结果再次压入数据栈。数据结构和算法
代码写的通常主要是演示栈的应用,特殊状况下计算结果可能有误,有兴趣的同窗能够重构一下函数
class Program
{
static void Main(string[] args)
{
List<string> lstAllData = new List<string>();
//读取输入的表达式,并整理
string inputStr = Console.ReadLine();
string tempData = "";
for (int i = 0; i < inputStr.Length; i++)
{
if (inputStr[i] == '+' || inputStr[i] == '-' || inputStr[i] == '*' || inputStr[i] == '/')
{
lstAllData.Add(tempData);
lstAllData.Add(inputStr[i].ToString());
tempData = "";
}
else
{
tempData += inputStr[i];
}
if(i== inputStr.Length - 1)
{
lstAllData.Add(tempData);
}
}
foreach (var item in lstAllData)
{
Calculator.Cal(item.ToString());
}
var ret = Calculator.GetResult();
Console.WriteLine(ret);
Console.Read();
}
}
//计算器
class Calculator
{
//存放计算数据的栈
static Stack<int> DataStack = new Stack<int>();
//存放操做符的栈
static Stack<string> OperatorStack = new Stack<string>();
public static int Cal(string dataOrOperator)
{
int data;
bool isData = int.TryParse(dataOrOperator, out data);
if (isData)
{
//若是是数据直接入数据栈
DataStack.Push(data);
}
else
{
//若是是操做符,和栈顶操做符比较优先级,若是大于栈顶,则直接入栈,不然栈顶元素出栈 进行操做
if (OperatorStack.Count <= 0)
{
OperatorStack.Push(dataOrOperator);
}
else
{
//当前运算符的优先级
var currentOpePrecedence = OperatorPrecedence(dataOrOperator);
//当前运算符栈顶元素的优先级
var stackTopOpePrecedence = OperatorPrecedence(OperatorStack.Peek());
if (currentOpePrecedence > stackTopOpePrecedence)
{
//若是当前运算符的优先级大于栈顶元素的优先级,则入栈
OperatorStack.Push(dataOrOperator);
}
else
{
//运算符栈顶元素出栈,数据栈出栈两个元素,而后进行运算
var stackOpe = OperatorStack.Pop();
var data2 = DataStack.Pop();
var data1 = DataStack.Pop();
var ret = CalculateData(stackOpe, data1, data2);
DataStack.Push(ret);
OperatorStack.Push(dataOrOperator);
}
}
}
return 0;
}
//获取表达式最后的计算结果
public static int GetResult()
{
var ret = 0;
while (OperatorStack.Count > 0)
{
var stackOpe = OperatorStack.Pop();
var data2 = DataStack.Pop();
var data1 = DataStack.Pop();
ret = CalculateData(stackOpe, data1, data2);
DataStack.Push(ret);
}
return ret;
}
//根据操做符进行运算,这里能够抽象出接口,请自行实现
static int CalculateData(string operatorString, int data1, int data2)
{
switch (operatorString)
{
case "+":
return data1 + data2;
case "-":
return data1 - data2;
case "*":
return data1 * data2;
case "/":
return data1 + data2;
default:
return 0;
}
}
//获取运算符优先级
public static int OperatorPrecedence(string a) //操做符优先级
{
int i = 0;
switch (a)
{
case "+": i = 1; break;
case "-": i = 1; break;
case "*": i = 2; break;
case "/": i = 2; break;
}
return i;
}
}
复制代码
运行结果:
10+20*3+10-10+20-20+60*2
190
复制代码
package stack
import (
"errors"
"fmt"
)
type Stack struct {
Element []interface{} //Element
}
func NewStack() *Stack {
return &Stack{}
}
func (stack *Stack) Push(value ...interface{}) {
stack.Element = append(stack.Element, value...)
}
//返回下一个元素
func (stack *Stack) Top() (value interface{}) {
if stack.Size() > 0 {
return stack.Element[stack.Size()-1]
}
return nil //read empty stack
}
//返回下一个元素,并从Stack移除元素
func (stack *Stack) Pop() (value interface{}) {
if stack.Size() > 0 {
d := stack.Element[stack.Size()-1]
stack.Element = stack.Element[:stack.Size()-1]
return d
}
return nil
}
//交换值
func (stack *Stack) Swap(other *Stack) {
switch {
case stack.Size() == 0 && other.Size() == 0:
return
case other.Size() == 0:
other.Element = stack.Element[:stack.Size()]
stack.Element = nil
case stack.Size() == 0:
stack.Element = other.Element
other.Element = nil
default:
stack.Element, other.Element = other.Element, stack.Element
}
return
}
//修改指定索引的元素
func (stack *Stack) Set(idx int, value interface{}) (err error) {
if idx >= 0 && stack.Size() > 0 && stack.Size() > idx {
stack.Element[idx] = value
return nil
}
return errors.New("Set失败!")
}
//返回指定索引的元素
func (stack *Stack) Get(idx int) (value interface{}) {
if idx >= 0 && stack.Size() > 0 && stack.Size() > idx {
return stack.Element[idx]
}
return nil //read empty stack
}
//Stack的size
func (stack *Stack) Size() int {
return len(stack.Element)
}
//是否为空
func (stack *Stack) Empty() bool {
if stack.Element == nil || stack.Size() == 0 {
return true
}
return false
}
//打印
func (stack *Stack) Print() {
for i := len(stack.Element) - 1; i >= 0; i-- {
fmt.Println(i, "=>", stack.Element[i])
}
}
package calculator
import (
"calculator/stack"
"strconv"
)
type Calculator struct{}
var DataStack *stack.Stack
var OperatorStack *stack.Stack
func NewCalculator() *Calculator {
DataStack = stack.NewStack()
OperatorStack = stack.NewStack()
return &Calculator{}
}
func (c *Calculator) Cal(dataOrOperator string) int {
if data, ok := strconv.ParseInt(dataOrOperator, 10, 64); ok == nil {
//若是是数据直接入数据栈
// fmt.Println(dataOrOperator)
DataStack.Push(data)
} else {
//若是是操做符,和栈顶操做符比较优先级,若是大于栈顶,则直接入栈,不然栈顶元素出栈 进行操做
if OperatorStack.Size() <= 0 {
OperatorStack.Push(dataOrOperator)
} else {
//当前运算符的优先级
currentOpePrecedence := operatorPrecedence(dataOrOperator)
//当前运算符栈顶元素的优先级
stackTopOpePrecedence := operatorPrecedence(OperatorStack.Top().(string))
if currentOpePrecedence > stackTopOpePrecedence {
//若是当前运算符的优先级大于栈顶元素的优先级,则入栈
OperatorStack.Push(dataOrOperator)
} else {
//运算符栈顶元素出栈,数据栈出栈两个元素,而后进行运算
stackOpe := OperatorStack.Pop()
data2 := DataStack.Pop()
data1 := DataStack.Pop()
ret := calculateData(stackOpe.(string), data1.(int64), data2.(int64))
DataStack.Push(ret)
OperatorStack.Push(dataOrOperator)
}
}
}
return 0
}
func (c *Calculator) GetResult() int64 {
var ret int64
for {
if OperatorStack.Size() > 0 {
stackOpe := OperatorStack.Pop()
data2 := DataStack.Pop()
data1 := DataStack.Pop()
ret = calculateData(stackOpe.(string), data1.(int64), data2.(int64))
DataStack.Push(ret)
} else {
break
}
}
return ret
}
func calculateData(operatorString string, data1, data2 int64) int64 {
switch operatorString {
case "+":
return data1 + data2
case "-":
return data1 - data2
case "*":
return data1 * data2
case "/":
return data1 + data2
default:
return 0
}
}
func operatorPrecedence(a string) int {
i := 0
switch a {
case "+":
i = 1
case "-":
i = 1
case "*":
i = 2
case "/":
i = 2
}
return i
}
package main
import (
"calculator/calculator"
"flag"
"fmt"
)
var (
inputStr = flag.String("input", "", "请输入...")
)
func main() {
flag.Parse()
var lstAllData []string
var tempData string
rs := []rune(*inputStr)
for i := 0; i < len(rs); i++ {
if string(rs[i]) == "+" || string(rs[i]) == "-" || string(rs[i]) == "*" || string(rs[i]) == "/" {
lstAllData = append(lstAllData, tempData)
lstAllData = append(lstAllData, string(rs[i]))
tempData = ""
} else {
tempData += string(rs[i])
}
if i == len(rs)-1 {
lstAllData = append(lstAllData, tempData)
}
}
ca := calculator.NewCalculator()
for _, v := range lstAllData {
ca.Cal(v)
}
ret := ca.GetResult()
fmt.Println(ret)
}
复制代码
运算结果:
go run program.go -input=1+2-1*3
结果:0
复制代码
添加关注,查看更精美版本,收获更多精彩