编程之美--3.7队列中取最大值操作问题
参考资料:
http://www.cnblogs.com/pangxiaodong/archive/2011/09/10/2172833.html
http://blog.csdn.net/linyunzju/article/details/7765324
问题:
假设有这样一个拥有3个操作的队列:
1. EnQueue(v):将v加入队列中
2. DeQueue:使队列中的对首元素删除并返回此元素
3. MaxElement:返回队列中的最大元素
请设计一个数据结构和算法,让MaxElement操作的时间复杂度尽可能的低。
解法1:(不正确)在队列的数据结构中添加一个MaxVal变量,每次EnQueue(v),就将元素和MaxElement进行比较。但是存在问题是,当值为最大的元素出队时,无法判断现在最大的元素。如果想正确得到MaxVal,在每次最大元素出队的时候,都要重新判断一次最大元素。
解法2:采用最大堆。用最大堆来维护队列中的节点,队列用单链表表示,每个节点包含数据,而最大堆用数组表示,数组元素为节点的指针。入队和出队的时间复杂度为O(logn),取最大值的时间复杂度为O(1)。
解法3:用两个栈来当做队列。
两个栈的方法:
A栈,B栈
取最值:返回A栈的最值和B栈的最值相比后的最值。复杂度O(1)。
入队操作:直接入到B栈中。复杂度O(1)。
出队操作:如果A栈不为空,直接A栈出栈,复杂度为O(1),如果A栈为空,那么将B栈内容逐个出栈并且逐个入栈到A中,然后A栈出栈,复杂度O(N),实际上是B栈的长度。
因此这个问题的关键在于如何设计栈的数据结构和操作函数。
队列类,利用了两个栈构成,操作方法在前面已经叙述。
class Queue{ //使用两个栈构成的队列 private Stack stackA; private Stack stackB; public Queue(){ this.stackA = new Stack(); this.stackB = new Stack(); } public int MaxVal(){ //先获得stackA和stackB两个栈各自的最大值,这二者的最大值就是队列的最大值 int x = stackA.getMax(); int y = stackB.getMax(); return x>y?x:y; } public void enQueue(int element){ stackB.push(element); } public int deQueue(){ if(stackA.isEmpty()){ while(!stackB.isEmpty()){ stackA.push(stackB.pop()); } } return stackA.pop(); } public boolean isEmpty(){ if(stackA.isEmpty()&&stackB.isEmpty()) return true; else return false; } }
栈类:入栈和出栈都经过了改造
class Stack{ private int MAXN= 20; //设定一个栈元素最多为20个 private int[] stackItem; //存放栈内元素 private int stackTop; //指示栈顶 private int[] link2NextMax; //存放下一个最大值的index,实际上为下标从0到栈顶前一个元素的最大值,方便当前元素出栈后找到最大值 private int maxStackItemIndex; //最大值的index public Stack(){ stackTop = -1; maxStackItemIndex = -1; stackItem = new int[MAXN]; link2NextMax = new int[MAXN]; } public void push(int x){ stackTop++; if(stackTop>MAXN){ System.out.println("栈超过最大容量"); return; } else{ stackItem[stackTop]=x; if(x>getMax()){ link2NextMax[stackTop]=maxStackItemIndex; //保存之前的最大值所在位置的下标 maxStackItemIndex = stackTop; //更新最大值位置的下标 } else{ link2NextMax[stackTop]=-1; } } } public int pop(){ int result = Integer.MIN_VALUE ; if(stackTop<0) System.out.println("没有元素了"); else{ result = stackItem[stackTop]; if(stackTop==maxStackItemIndex){ maxStackItemIndex=link2NextMax[stackTop]; } stackTop--; } return result; } public int getMax(){ if(maxStackItemIndex>=0) return stackItem[maxStackItemIndex]; else return Integer.MIN_VALUE; } public boolean isEmpty(){ if(stackTop==-1) //栈空 return true; else return false; } }
main()
public class MyGetMax { public static void main(String args[]){ Queue myQue = new Queue(); myQue.enQueue(6); myQue.enQueue(1); myQue.enQueue(9); myQue.enQueue(7); myQue.enQueue(4); myQue.enQueue(5); myQue.enQueue(0); myQue.enQueue(2); while(!myQue.isEmpty()){ System.out.print("当前队列内最大元素为:"+myQue.MaxVal()); System.out.println(", 出队元素为:"+myQue.deQueue()); } } }
运行结果:
当前队列内最大元素为:9, 出队元素为:6 当前队列内最大元素为:9, 出队元素为:1 当前队列内最大元素为:9, 出队元素为:9 当前队列内最大元素为:7, 出队元素为:7 当前队列内最大元素为:5, 出队元素为:4 当前队列内最大元素为:5, 出队元素为:5 当前队列内最大元素为:2, 出队元素为:0 当前队列内最大元素为:2, 出队元素为:2

浙公网安备 33010602011771号