标签:java数据结构和算法 后缀表达式 队列 栈
队列,queqe,就是现实生活中的排队。
1、简单队列:
public class Queqe {
private int array[];
private int front;
private int end;
private int number;
private int max;
private Queqe(int maxsize){
array = new int[maxsize];
max = maxsize;
front = 0;
end = 0;
number = 0;
}
private void insert(int item){
if(isFull()){
System.out.println("is full,can not insert");
return;
}
array[end++] = item;
number++;
}
private int remove(){
if(isEmpty()){
System.out.println("is empty,can not remove");
return -1;
}
number--;
return array[front++];
}
private boolean isFull(){
return number == max;
}
private boolean isEmpty(){
return number == 0;
}
private int size(){
return number;
}
private int peekFront(){
return array[front];
}
public static void main(String[] args) {
Queqe q = new Queqe(4);
System.out.println("queqe is empty:"+q.isEmpty());
q.insert(1);
q.insert(2);
q.insert(3);
q.insert(4);
q.insert(5);
System.out.println(q.size());
System.out.println("front is "+q.peekFront());
while(!q.isEmpty())
System.out.println(q.remove());
}
}
result:
queqe is empty:true
is full,can not insert
4
front is 1
1
2
3
4
先进的元素排在前面,那么移除的时候就是先移除队头,达到先进先出的效果,·插入和移除并不用移动整个数组,只需改变队头和队列的指向,所以时间复杂度和栈一样都是O(1)。
2、不用number之后的方法改变
前面用了number统计队列中元素个数,其实不用这个变量,单靠队头和队尾也是可以实现队列。
private boolean isFull(){
return end == max;
}
private boolean isEmpty(){
return (front ==0&&end ==0)||front == max;
}
private int size(){
return end -front;
}而判断是不是满了更简单,队尾移到数组尾部即是满了。
空的话会复杂一些,一种是一开始front为零,但是有元素插入,此时end不为零,如果两者为零那就是空了,还有就是不停remove之后,front移到最后,证明之前的元素全部remove掉了,此时也为空。
作者根据的是front和end的变化,然后再insert和remove中直接改变front和end的值,在isEmpty和isFull中,例如在isFull()中:
private boolean isFull(){
return end+2 == front||(front+max-2==end);
}这样更复杂。因为这样类似循环队列,超出之后又重头开始插入。
其实在isEmpty和isFull中直接进行判断就可以了。然后真的超出的时候直接打印错误后return。
3、优先级队列
银行办业务当然要排队,但是,银行的vip用户不需要,因为他存的钱比你多,银行重视这种客户,优先级高,所以他虽然比你晚来到银行,但是排号的时候拿到的号比你还前。
那这样的话,优先级队列就像是一开始就根据优先级排列好顺序的队列。
private void insert(int item){
if(isFull()){
System.out.println("is full,can not insert");
return;
}
if(end == 0){
array[end++] = item;
}else{
int i;
for ( i = number-1; i >=0; i--) {
if(item > array[i]){
array[i+1] = array[i];
}
}
array[i+1]= item;
end++;
}
number++;
}
result:
queqe is empty:true
size:0
is full,can not insert
queqe is empty:false
size:4
front is 4
4
3
2
1
4、算术表达式的解析
1+2+3=?
由于我们从小接受的教育就是从左到右,有括号计算括号里面,先乘除后加减这样的思路,然后看到上面那个算式的时候一下子就得出结果,这是中缀表达式。也就是我们脑里面计算算式的方式。
从左到右,1+2看后面,是+号,那可以直接算1+2的值为3,3+3后面是=号了,直接计算3+3=6。
1+2*3=?
从左到右,1+2看后面,是*号,那不能直接算1+2的值,先计算2*3=6,再看后面为=,所以计算1+6=7。
1*(2+3)=?
从左到右,1后面是*,所以本来先计算的,但是后面是(所以先看括号,括号里面是2+3=5后面是=,所以直接计算1*5=5。
但是计算机并不像人脑这么聪明。一眼看过去基本可以心算。计算机认后缀表达式比较容易,如果我们从小就接受的是后缀表达式的方式的话,那对于我们来说一样可以。
后缀表达式的话就用符号a,b,c表示了,因为多位数字的话,写成1242132+,根本就不知道是那两个数字相加,那么就要有分隔符,但是无疑会增加难度。
a+b-c转后缀:
读a,读到+,继续读到b,写成ab,再读到-号可以将+放在ab后面,即ab+,读入c,后面结束了则ab+c-。
a+b*c转后缀:
读a,读+,读b,放置为ab,再读后面,*优先级大于+号,暂时不能放+,再读c,c后面结束,所以可以放入*,在放+,即abc*+。
a*(b+c)转后缀:
读a,读*,后面发现(不能放置*,(里比*优先级高,读b+c,后面为),可变为bc+,再和a*合,即abc+*。
这篇虽然讲得是队列,但是要用到的结构是栈,因为进来进去的。这里的算数不用压入栈,直接输出。
a+b-c转后缀:
直接输出a,读+,栈空压入栈,再输出b,栈非空,弹出+,读到-,+优先级>= -,输出+,压-入栈,输出c,结束了,弹出-。
最后结果:ab+c-。
a+b*c转后缀:
直接输出a,读+,栈空压入栈,再输出b,栈非空,弹出+,读到*,+优先级< -,所以先+压入栈,再压*,输出c,结束了,弹出*,再弹+。
最后结果:abc*+。
a*(b+c)转后缀:
直接输出a,读*,栈空压入栈,读到(压(入栈,输出b,读+,压入栈,输出c,读),发现后面结束可以弹出+并输出,弹出(不输出,弹出*。
最后结果:abc+*。
看了这个分析过程之后,就是利用栈,对操作符进行栈的压入和弹出。
如果纯粹用高级语言写计算器,直接使用中缀表达式即可,但是到了底层的编译器,就是需要后缀表达式实现,还要考虑到位数和其他操作符,可想代码远远比上面的复杂。
整体的思路就是这样,代码的实现就是通过栈和条件判断进行入栈和出栈即可。
标签:java数据结构和算法 后缀表达式 队列 栈
原文地址:http://blog.csdn.net/iaiti/article/details/39856781