关于栈,这里的定义和前面的顺序表是一样,采用数组的形式,详细请见: 顺序表
栈相关处理类代码:
/// <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; } }