栈的结构比较简单,跟链表差不多底层还是一个数组,代码实现也比较容易,主要利用的就是他的先进后出的特点,java代码如下:
<span style="font-size:14px;">package Stack;
/*
* 栈的实现
* 基本思路还是利用数组来做实现
*/
public class MyStack {
private static final int DEFUALT_LENGTH=10;
private int theLength=0;
private Object[] theItems;
/*
* 构造一个空栈
*/
public MyStack(){
clearStack();
}
/*
* 销毁一个栈
*/
public void destroyStack(){}
/*
* 清空一个栈
*/
public void clearStack(){
theLength=0;
ensureCapacity(DEFUALT_LENGTH);
}
/*
* 判断一个栈是否为空
*/
public boolean isEmpty(){
return theLength==0;
}
/*
* 返回栈的长度
*/
public int stackLength(){
return theLength;
}
/*
* 返回栈顶元素
*/
public Object geTop(){
if(isEmpty()){
throw new IndexOutOfBoundsException();
}
Object obj=theItems[theLength-1];
//theLength--;
return obj;
}
/*
* 压栈
*/
public void push(Object obj){
if(theLength>=theItems.length){
ensureCapacity(theLength*2+1);
}
theItems[theLength]=obj;
theLength++;
}
/*
* 出栈
*/
public Object pop(){
if(isEmpty()){
return null;
}
Object obj=theItems[theLength-1];
theLength--;
//ensureCapacity(theLength);
return obj;
}
/*
*数组的扩展
*/
public void ensureCapacity(int newCapaciyty){
if(theLength>newCapaciyty){
return;
}
Object [] old=theItems;
theItems=new Object[newCapaciyty];
for(int i=0;i<theLength;i++){
theItems[i]=old[i];
}
}
}
</span>
实现还是比较简单的,下面来几个实际应用:
1 十进制数转换成其他任意进制的数,这个原理很简单,将迭代的余数倒过来输出即可
代码如下:
<span style="font-size:14px;">///十进制数转换成其他任意进制的数
private static String toOther(int tenNum, int otherNum) {
// TODO Auto-generated method stub
MyStack ms=new MyStack();
int result=0;
String results="";
while(tenNum!=0){
result=tenNum%otherNum;
ms.push(result);
tenNum=tenNum/otherNum;
}
result=0;
while(!ms.isEmpty()){
results+=ms.pop()+"";
}
return results;
}</span>
测试代码
System.out.println("请输入一个十进制的数");
int tenNum=sc.nextInt();
System.out.println("请输入要转换的进制数");
int otherNum=sc.nextInt();
String resultnum=toOther(tenNum,otherNum);
System.out.println(resultnum);
结果如下:
请输入一个十进制的数
12
请输入要转换的进制数
8
14
2 表达式的求值 ,直接上代码
//表达式的的求值
/*
* 基本的原理是,构建两个栈,一个用来存放操作数,一个用来存放运算符
* 依次输入表达式中的每一个字符,
* 若是数字则直接将数字压入存放操作数的那个栈
* 若是运算符则与运算符的栈顶元素进行比较,
* 如果运算符的优先级低于栈顶元素,就要弹出两个操作数和一个运算符进行运算操作
* 如果运算符的优先级高于栈顶元素,就直接将运算符压栈
* 如果是等于(在次规定只有”(“与“)”是想等的其他的相等取大于)
*/
/*
* 运算操作,根据两个操作数和传入的运算符来进行计算
*/
private static double operate(double x,double y,char operator){
double result=0.0;
switch (operator){
case '+':
result=x+y;
break;
case '-':
result=x-y;
break;
case '*':
result=x*y;
break;
case '/':
result=x/y;
break;
}
return result;
}
/*
* 比较两个运算符的优先级,第一个参数是存放运算符的栈顶元素,第二个参数是要压入的元素。
* 正数表示大于,0表示等于,负数表示小于
*/
private static int precede(char stackTop,char toPush){
int result=-1;
if(stackTop=='-')
stackTop='+';//这里是比较优先级,所以同一个优先级的运算符可以看作是一样的,方便与下面的数组操作
if(stackTop=='/')
stackTop='*';
if(toPush=='-')
toPush='+';
if(toPush=='/')
toPush='*';
char [] operators=new char[]{'#',')','+','*','('};
if((stackTop=='('&&toPush==')')||(stackTop=='#'&&toPush=='#')){///这里面只有这一种情况,因为运算符的栈必须是先有(,而且一旦遇到)除非出错否则就会立刻弹出两个括号
result=0;
}else{
int inOfTop=getIndex(stackTop, operators);//得到栈顶元素的下标
int inOfPush=getIndex(toPush, operators);
if(inOfPush==-1||inOfTop==-1){
throw new IndexOutOfBoundsException();//如果返回值是-1则表示不存在,这是出错的情况,先抛出异常。
}else{
if(inOfTop>=inOfPush){//相等或者大于军则返回正值
result=1;
}else{
result=-1;
}
}
}
return result;
}
//用于返回字符在再付数组中的位置
private static int getIndex(char ele,char[] chars){
int index=-1;
for(int i=0;i<chars.length;i++){
if(chars[i]==ele){
index=i;
break;
}
}
return index;
}
//判断是不是字符
private static boolean isChar(char ele){
boolean flage=true;
if(ele>='0'&&ele<='9')
flage=false;
return flage;
}
/*
* 真正开始操作
*/
private static double getResult(String evalueExpression){
double result=0.0;
//构建两个栈
MyStack Optr=new MyStack();//存放运算符的栈
Optr.push('#');
MyStack Opnd=new MyStack();//存放数字的栈
int i=0;
char[] chars=evalueExpression.toCharArray();//转换成字符数组
char operOrType=' ';
while(!Optr.isEmpty()){
if(i<chars.length){
operOrType=chars[i++];
}
char typeTop=(char) Optr.geTop();
if(!isChar(operOrType))//不是运算符就直接压入数字栈
Opnd.push(operOrType);
else{
if(typeTop=='('&&operOrType!=')'){//但栈顶是(就得另说
Optr.push(operOrType);
}else{
switch(precede(typeTop, operOrType)){
case -1:
Optr.push(operOrType);
break;
case 0://相等就意味着是一对括号或者#相遇,那么必然的括号里面的运算操作已经完成,所以要脱去括号
Optr.pop();
break;
case 1://栈顶的优先级高就先计算,
double num1=Double.parseDouble(Opnd.pop()+"") ;
double num2=Double.parseDouble(Opnd.pop()+"");
char opType=(char) Optr.pop();
result=operate(num2, num1, opType);
Opnd.push(result);
i--;//计算完成之后当前的操作符不能丢,因为前面的计算完成之后还要将其压栈判断
break;
}
}
}
}
return result;
}
测试代码:
System.out.println("请输入一个算术表达式以#结尾");
String evalueExpression=sc.nextLine();
System.out.println(getResult(evalueExpression));
结果如下:
请输入一个算术表达式以#结尾
3*(3+2/4)+9*6/2#
37.5