一、栈
栈,LIFO表,只允许在栈的一端进行操作,称为栈顶。不允许操作得一端称为栈底。
栈有几个基本操作,分别是:
(1)Stack()
构造一个空栈S。
(2)Empty()
判栈空。若为空栈,则返回TRUE,否则返回FALSE。
(3)Full()
判栈满。若为满栈,则返回TRUE,否则返回FALSE。
注意:
该运算只适用于栈的顺序存储结构。
(4)Push(x)
进栈。若栈S不满,则将元素x插入S的栈顶。
(5)Pop()
退栈。若栈S非空,则将S的栈顶元素删去,并返回该元素。
(6)GetTop()
取栈顶元素。若栈S非空,则返回栈顶元素,但不改变栈的状态。
我想的是用栈完成表达式的计算,但是花了两天时间都没搞定。本来是想使用微软提供得Stack()类,其定义如下:
Code
public class Stack<T> : IEnumerable<T>, ICollection, IEnumerable
{
public Stack();
public Stack(int capacity);
public int Count {get;}
public void Clear();
//确定某元素是否在Stack<T>中,
//如果在Stack<T>中找到item,则为true;否则为false。
public bool Contains(T item);
//从指定数组索引开始将Stack<T>复制到现有一维Array中。
public void CopyTo(T[] array, int arrayIndex);
//返回位于Stack<T>顶部的对象但不将其移除。
public T Peek();
public T Pop();
public void Push(T item);
//将Stack<T>复制到新数组中。
public T[] ToArray();
//如果元素数小于当前容量的90%,
//将容量设置为Stack<T>中的实际元素数。
public void TrimExcess();
}
但是,有很多问题不能解决,比如判断栈的非空,我想的办法是:stack.Count!=0,获得栈顶元素想的办法是:(char)stack.Peek(),但是Peek()在栈为空的情况下,返回是会出错的。想了很久,还是自己写一个符合要求得栈来试一试。参照网上于是有了下面的myStack()类:
Code
using System;
public class myStack
{
int maxsize;
object[] data;
int top;
//索引
public object this[int index]
{
get{return data[index];}
set{data[index]=value;}
}
public int Maxsize{get;set;}
public int Top{get;set;}
//构造函数
public myStack(int size)
{
data = new object[size];
maxsize = size;
top=-1;
}
//返回栈长
public int Length()
{
return top+1;
}
//清空栈
public void Clear()
{
top=-1;
}
//判断栈是否为空
public bool IsEmpty()
{
if(top==-1)
{
return true;
}
else
{
return false;
}
}
//判断栈是否为满
public bool IsFull()
{
if(top==maxsize-1)
{
return true;
}
else
{
return false;
}
}
//压栈
public void Push(object e)
{
if(IsFull())
{
Console.WriteLine("栈已满!");
return ;
}
data[++top]=e;
}
//出栈
public object Pop()
{
object temp=null;
if(IsEmpty())
{
Console.WriteLine("栈为空!");
return temp;
}
temp = data[top];
top--;
return temp;
}
//获得栈顶元素
public object GetTop()
{
if(IsEmpty())
{
Console.WriteLine("栈为空!");
return null;
}
return data[top];
}
}
这样便可满足我所需要得条件,于是又写一个类来完成表达式得计算。
Code
using System;
using System.Collections.Generic;
public class calculator
{
private Stack<int> nums; //整数栈,用于存储计算结果
private myStack ops; //表达式栈,存储表达式
private string expression; //中缀表达式
private string poststr; //输出后缀表达式
public calculator(string str)
{
nums= new Stack<int>();
ops=new myStack(str.Length);
expression=str+"#";
}
//将中缀表达式转换为后缀表达式
public string toPostfix()
{
char cout;
int i=0,j=0;
while(expression[i]!='#') //表达式末尾
{
switch(expression[i])
{
case '+':
case '-': while(!ops.IsEmpty() && (char)ops.GetTop()!='(')
poststr+=ops.Pop();
ops.Push(expression[i++]);
break;
case '*':
case '/': while(!ops.IsEmpty() && (char)ops.GetTop()=='*' || (char)ops.GetTop()=='/')
poststr+=ops.Pop();
ops.Push(expression[i++]);
break;
case '(': ops.Push(expression[i++]);
break;
case ')': cout=(char)ops.Pop();
while(!ops.IsEmpty() && cout!='(')
{
poststr+=cout;
cout=(char)ops.Pop();
}
i++;
break;
default: while(isNumeric(expression[i])&& expression[i]!='#')
poststr+=expression[i++];
poststr+=' ';
break;
}
}
while(!ops.IsEmpty())
poststr+=ops.Pop();
poststr+='#'; //表达式末尾
return poststr;
}
//计算后缀表达式
public int Compute()
{
int i=0,z=0;
int x,y;
while(poststr[i]!='#')
{
if(isNumeric(poststr[i]))
{
z=0;
while(poststr[i]!=' ')
{
z=z*10+poststr[i]-'0';
//Console.WriteLine(z);
i++;
}
i++;
nums.Push(z);
}
else
{
if(poststr[i]!=' ')
{
y=nums.Pop();
x=nums.Pop();
switch(poststr[i])
{
case '+':z=x+y; break;
case '-':z=x-y; break;
case '*':z=x*y; break;
case '/':z=x/y; break;
}
nums.Push(z);
}
i++;
}
}
return nums.Pop();
}
/* 测试
public void test()
{
// int i=0,j=0;
// 测试字符串结束
while(expression[i]!='#')
{
switch(expresstion[i])
{
case '+':
case '-':
}
}
Console.Write("bad");
// 测试空栈
while(expression[i]!='#')
nums.Push(i++);
while(nums.Count!=0)
nums.Pop();
Console.Writelllll("null");
// 测试数字判断
while(expression[i]!='#')
{
i++;
if(isNumeric(expression[i]))
Console.WriteLine(expression[i]+":yes");
}
Console.WriteLine(poststr);
//Console.WriteLine();
}
*/
public bool isNumeric(char chs)
{
return char.IsDigit(chs);
}
public static void Main()
{
string str="2+3*5*(4+6)";
calculator clr=new calculator(str);
clr.toPostfix();
int max=clr.Compute();
Console.WriteLine(max);
}
}
总算完成了栈的部分,中缀表达式转后缀表达式得准则,网上很多介绍,我摘抄到了本子上。接下来,自己再不查
资料的情况下完成一次就ok啦。