关于栈,这里的定义和前面的顺序表是一样,采用数组的形式,详细请见: 顺序表
栈相关处理类代码:
/// <summary>
/// Description of SequenceStack.
/// </summary>
public class SequenceStack<T> where T:IComparable
{
private Sequence<T> _sequence;
private int _size;
public SequenceStack(int size)
{
_size=size;
_sequence=new Sequence<T>(_size);
}
/// <summary>
/// Init the sequence stack
/// </summary>
public void Init()
{
_sequence.Current=0;
}
/// <summary>
/// Check whether the sequence stack is empty
/// </summary>
/// <returns>True or false</returns>
public bool IsEmpty()
{
if(_sequence.Current==0)
{
Console.WriteLine("SequenceStack is empty!");
return true;
}
return false;
}
/// <summary>
/// Check whether the sequence stack is full
/// </summary>
/// <returns>True or false</returns>
public bool IsFull()
{
if(_sequence.Current>=_sequence.Size)
{
Console.WriteLine("SequenceStack is full!");
return true;
}
return false;
}
/// <summary>
/// Get the top value
/// </summary>
/// <returns>The top value</returns>
public T GetTop()
{
if(IsEmpty()) return default(T);
return _sequence.Data[_sequence.Current-1];
}
/// <summary>
/// Push a value into the sequence stack
/// </summary>
/// <param name="x">the value want to be pushed</param>
public void Push(T x)
{
if(IsFull()) return;
_sequence.Data[_sequence.Current]=x;
_sequence.Current++;
}
/// <summary>
/// Pop a value from the sequence stack
/// </summary>
/// <returns>a value</returns>
public T Pop()
{
if(IsEmpty()) return default(T);
///Get the top value
T result= GetTop();
_sequence.Current--;
return result;
}
/// <summary>
/// Get the priority of a char
/// </summary>
/// <param name="op">the char</param>
/// <returns></returns>
public int GetPriority(char op)
{
switch(op)
{
case '#':
{
return -1;
}
case '(':
{
return 0;
}
case '+':
case '-':
{
return 1;
}
case '*':
case '/':
{
return 2;
}
default:
{
return -1;
}
}
}
/// <summary>
/// Check a char whether is a operation
/// </summary>
/// <param name="op">The char want to be checked</param>
/// <returns></returns>
public bool IsOperation(char op)
{
switch(op)
{
case '+':
case '-':
case '*':
case '/':
return true;
default:return false;
}
}
/// <summary>
/// Check a char array Whether is a brackets matched array
/// </summary>
/// <param name="s">The array need to be checked</param>
/// <returns>Match or not</returns>
public static bool MatchBrackets(char[] s)
{
SequenceStack<char> stack=new SequenceStack<char>(100);
int i=0;
while(s[i]!='#')
{
switch(s[i])
{
case '{':
case '[':
case '(':
{
stack.Push(s[i]);break;
}
case '}':
{
if(!stack.IsEmpty()&&stack.GetTop()=='{')
{
stack.Pop();break;
}
return false;
}
case ']':
{
if(!stack.IsEmpty()&&stack.GetTop()=='[')
{
stack.Pop();break;
}
return false;
}
case ')':
{
if(!stack.IsEmpty()&&stack.GetTop()=='(')
{
stack.Pop();break;
}
return false;
}
}
i++;
}
return stack.IsEmpty();
}
/// <summary>
/// Convert a char array to a double number
/// </summary>
/// <param name="s">The char array need to be converted</param>
/// <param name="index">The start position</param>
/// <param name="endIndex">The end position</param>
/// <returns>the double number</returns>
public static double ConvertNumber(char[] s,int index,out int endIndex)
{
double number=0.0d;
while(s[index]>='0'&&s[index]<='9')
{
number=number*10+int.Parse(s[index].ToString());
index++;
}
if(s[index]=='.')
{
int i=-1;
index++;
while(s[index]>='0'&&s[index]<='9')
{
number=number+int.Parse(s[index].ToString())*Math.Pow(10,i);
index++;
i--;
}
}
endIndex=index;
return number;
}
/// <summary>
/// Get the value of a postfix expression
/// </summary>
/// <param name="s">The postfix expression</param>
/// <returns>The value</returns>
public static double GetPostfixValue(char[] s)
{
SequenceStack<double> stack=new SequenceStack<double>(100);
double number1,number2;
int i=0;
while(s[i]!='#')
{
if(s[i]>='0'&&s[i]<='9')
{
stack.Push(ConvertNumber(s,i,out i));
continue;
}
if(s[i]==' ') {i++;continue;}
if(stack.IsOperation(s[i]))
{
number2=stack.Pop();
number1=stack.Pop();
switch(s[i])
{
case '+':
{
stack.Push(number1+number2);
i++;
break;
}
case '-':
{
stack.Push(number1-number2);
i++;
break;
}
case '*':
{
stack.Push(number1*number2);
i++;
break;
}
case '/':
{
stack.Push(number1/number2);
i++;
break;
}
}
}
}
return stack.Pop();
}
/// <summary>
/// Convert a infix expression to a postfix expression
/// </summary>
/// <param name="s">The infix expression</param>
/// <returns>The postfix expression</returns>
public static char[] ConvertPostfix(char[] s)
{
SequenceStack<char> stack=new SequenceStack<char>(100);
char[] postfixArray=new char[100];
int i=0,j=0;
stack.Push('#');
while(s[i]!='#')
{
if((s[i]>='0'&&s[i]<='9')||s[i]=='.')
{
postfixArray[j++]=s[i];
i++;
continue;
}
if(s[i]=='(')
{
stack.Push(s[i]);
i++;
continue;
}
if(s[i]==')')
{
char temp=stack.Pop();
while(temp!='(')
{
postfixArray[j++]=temp;
temp=stack.Pop();
}
i++;
continue;
}
if(stack.IsOperation(s[i]))
{
postfixArray[j++]=' ';
char temp=stack.Pop();
while(stack.GetPriority(temp)>=stack.GetPriority(s[i]))
{
postfixArray[j++]=temp;
temp=stack.Pop();
}
stack.Push(temp);
stack.Push(s[i]);
i++;
}
}
while(stack._sequence.Current>0)
{
postfixArray[j++]=stack.Pop();
}
postfixArray[j++]=stack.Pop();
return postfixArray;
}
}
为了验证各个功能是否能够良好运行,写一些代码测试一下:
#region test MatchBrackets method
string matchTestString=@"2(2[3]j)3#";
char[] matchTestArray=StringCommon.ConvertToArray(matchTestString);
bool matchResult=SequenceStack<int>.MatchBrackets(matchTestArray);
Console.WriteLine(matchResult);
#endregion
#region test ConvertNumber method
string convertTestString=@"2312.012#";
char[] convertTestArray=StringCommon.ConvertToArray(convertTestString);
int index=0;
double convertResult=SequenceStack<int>.ConvertNumber(convertTestArray,0,out index);
Console.WriteLine("{0},{1}",convertResult,index);
#endregion
#region test GetPostfixValue method
string getPostfixValueTestString=@"3 5 2 *-#";
char[] getPostfixValueTestArray=StringCommon.ConvertToArray(getPostfixValueTestString);
double getResult=SequenceStack<int>.GetPostfixValue(getPostfixValueTestArray);
Console.WriteLine("{0}",getResult);
#endregion
#region test ConvertPostfix method
string convertPostfixTestString=@"3*((30-2)+4*5/2)#";
char[] convertPostfixTestArray=StringCommon.ConvertToArray(convertPostfixTestString);
char[] convertPostfixResult=SequenceStack<int>.ConvertPostfix(convertPostfixTestArray);
double gets=SequenceStack<int>.GetPostfixValue(convertPostfixResult);
Console.WriteLine("{0}",gets);
#endregion
在测试代码中,用到了类StringCommon,其代码如下:
/// <summary>
/// Description of StringCommon.
/// </summary>
public class StringCommon
{
public StringCommon()
{
}
/// <summary>
/// Convert a string to a array
/// </summary>
/// <param name="s">The string need to be converted</param>
/// <returns>Converted array</returns>
public static char[] ConvertToArray(string s)
{
if(!IsEndWithChar(s,'#'))
{
throw new ApplicationException("The string is not end with '#'");
}
return s.ToCharArray();
}
/// <summary>
/// Check a string whether is end with specified char
/// </summary>
/// <param name="c">The end with char</param>
/// <returns>True or False</returns>
public static bool IsEndWithChar(string s,char c)
{
return s[s.Length-1]==c?true:false;
}
}