编程之美——队列中取最大值操作

为实现O(1)的时间复杂度完成取队列中最大元素,使用maxStackItemIndex记录队列(使用两个栈实现)中最大元素下标,使用数组link2NextMaxItem[]记录数组中次大值的下标,这也就是使用两个栈(先进后出)模拟队列二不是直接使用队列(先进先出)的原因:先进后出可以保证当执行pop操作(pop出最大值)时可以更新maxStackItemIndex=link2NextMaxItem[stackTop];而队列则不具有这种回溯特性;

代码:

  1 #include<iostream>
  2 using namespace std;
  3 const int INF=10000;
  4 const int MAXN=100;
  5
  6 class maxStack
  7 {
  8 private:
  9     int stackItem[MAXN];
 10     int stackTop;
 11     int link2NextMaxItem[MAXN]; //记录栈中第二大数字的下标
 12     int maxStackItemIndex;  //记录站中最大数字下标
 13
 14 public:
 15     maxStack()
 16     {
 17         stackTop=-1;
 18         maxStackItemIndex=-1;
 19     }
 20
 21     void push(int x);
 22     int pop();
 23     int max()
 24     {
 25         if(maxStackItemIndex>=0)
 26             return stackItem[maxStackItemIndex];
 27         else
 28             return -INF;
 29     }
 30     bool empty()
 31     {
 32         return stackTop==-1;
 33     }
 34 };
 35
 36 void maxStack::push(int x)
 37 {
 38     ++stackTop;
 39     if(stackTop>MAXN)
 40         //throw new Exception("stack is full!");
 41         cout<<"stack is full!"<<endl;
 42     else
 43     {
 44         stackItem[stackTop]=x;
 45         if(x>max())
 46         {
 47             //更新过程
 48             link2NextMaxItem[stackTop]=maxStackItemIndex;
 49             maxStackItemIndex=stackTop;
 50         }
 51         else
 52             link2NextMaxItem[stackTop]=-1;
 53     }
 54 }
 55
 56 int maxStack::pop()
 57 {
 58     if(stackTop==-1)
 59         //throw new Exception("stack is empty!");
 60         cout<<"stack is empty!"<<endl;
 61
 62     int value=stackItem[stackTop];
 63     if(value==max())
 64     {
 65         //回溯第二大数字下标
 66         maxStackItemIndex=link2NextMaxItem[stackTop];
 67     }
 68     --stackTop;
 69     return value;
 70 }
 71
 72 //使用两个栈模拟队列
 73 class maxQueue
 74 {
 75 private:
 76     maxStack A,B;
 77 public:
 78     void enQueue(int x)
 79     {
 80         B.push(x);
 81     }
 82     int deQueue()
 83     {
 84         if(A.empty())
 85             while(!B.empty())
 86                 A.push(B.pop());
 87         return A.pop();
 88     }
 89     int maxValue()
 90     {
 91         return A.max()>B.max() ? A.max():B.max();
 92     }
 93 };
 94
 95 int main()
 96 {
 97     maxQueue queue;
 98     for(int i=5;i>0;--i)
 99         queue.enQueue(i);
100     for(int i=0;i<5;++i)
101     {
102         cout<<queue.maxValue()<<ends;
103         queue.deQueue();
104     }
105     return 0;
106 }

上面是以栈为基础构造队列实现O(1)的取队列中最小元素,当然也可以直接使用队列实现,这里使用效率较高的循环队列;

具体:若入对元素大于队尾元素,则将队尾元素弹出,入队,这样可以保证队尾元素始终为最大值,直接返回即可;

代码:

 1 #include<iostream>
 2 using namespace std;
 3
 4 class maxQueue
 5 {
 6 private:
 7     int *queueItem;
 8     int front,rear;
 9     int maxSize;
10 public:
11     maxQueue(int size=5)
12     {
13         queueItem=new int[size];
14         maxSize=size;
15         front=rear=1;
16     }
17     int rearValue()
18     {
19         return queueItem[rear];
20     }
21     void doubleSpace();
22     void enQueue(int x);
23     int deQueue();
24     int maxValue()
25     {
26         return queueItem[front];
27     }
28     bool isEmpty()
29     {
30         return front==rear;
31     }
32     ~maxQueue()
33     {
34         delete [] queueItem;
35     }
36 };
37
38 void maxQueue::enQueue(int x)
39 {
40     if((rear+1)%maxSize==front)
41         doubleSpace();
42
43     while(x>=rearValue())
44     {
45         --rear;
46     }
47     rear=(rear+1)%maxSize;
48     queueItem[rear]=x;
49 }
50
51 int maxQueue::deQueue()
52 {
53     if(front==rear)
54         cout<<"the queue is empty"<<endl;
55
56     int value=queueItem[front];
57     front=(front+1)%maxSize;
58     return value;
59 }
60
61 void maxQueue::doubleSpace()
62 {
63     int *tmp=queueItem;
64
65     queueItem=new int[2*maxSize];
66     for(int i=1;i<maxSize;++i)
67         queueItem[i]=queueItem[front+i];
68
69     maxSize*=2;
70     delete tmp;
71 }
72
73 int main()
74 {
75     maxQueue queue;
76     int arr[9]={4,3,2,1,5,4,3,2,1};
77     for(int i=0;i<9;++i)
78     {
79         queue.enQueue(arr[i]);
80         cout<<"max:"<<queue.maxValue()<<endl;
81     }
82     cout<<endl;
83     while(!queue.isEmpty())
84     {
85
86         cout<<"max:"<<queue.maxValue()<<endl;
87         queue.deQueue();
88     }
89
90     return 0;
91 }

时间: 2024-10-07 14:10:56

编程之美——队列中取最大值操作的相关文章

编程之美---队列中取最大值操作问题

如何快速获取队列中的最大值? 最简单的办法,用一个for循环遍历,复杂度为o(n). 解法二:用大顶堆来实现,复杂度为哦o(1),但是入队和出队复杂度变为o(logN),堆中的每一个元素还得有个指针指向它的后继元素. 解法三:可以使用两个栈来模拟队列,从右边的栈进入元素相当于入队,出队时,只有当左边的栈为空时,才把右边栈的元素全部出栈到左边的栈. 1 class stack 2 { 3 public: 4 stack() 5 { 6 stackTop = -1; 7 maxItemIndex =

&lt;&lt;编程之美&gt;&gt; -- 队列中取最大值操作的问题

不得不说编程之美是一本好书,虽然很多题目在做acm中的过程中遇到过,不过还是有很多值得思考的地方 这是今天在编程之美上看到的一个问题,对于栈转化成队列的一个思考 平时都太过依赖c++内函数库中的栈和队列,但是对于他们的扩展我们还是应该自己进行手写栈和队列来实现更简单的算法 题目大意: 假设有这样一个拥有3个操作的队列: 1. EnQueue(v) : 将 v 加入队列 2. DeQueue: 使队列中队首元素删除并返回此元素 3.MaxElement: 返回队列中的最大元素 设计一种数据结构和算

编程之美之队列中取最大值操作

问题: 假设有这样一个拥有3个操作的队列: 1. EnQueue(v): 将v加入队列中 2. DeQueue(): 使队列中的队首元素删除并返回此元素 3. MaxElement: 返回队列中的最大元素 设计一种数据结构和算法,让MaxElement操作的时间复杂度尽可能地低. #include<iostream> #include<limits.h> using namespace std; class Stack { public: Stack() { stackTop =

队列中取最大值操作

假设有这样一个拥有3个操作的队列: 1.EnQueue(v):将v加入队列 2.DeQueue:使队列中的队首元素删除并返回元素 3.MaxElement:返回队列中的最大元素 请设计一种数据结构和算法,让MaxElement操作的时间复杂度尽可能低 研究这个问题之前,先研究两个子问题: 1.设计一个包含min操作的栈 2.用栈实现队列 一.设计一个包含min操作的栈 考虑给栈增加一个成员变量MinValue,有元素入栈的时候,将入栈元素与MinValue相比,如果小于MinValue,用入栈元

队列中取最大值操作问题

问题: 假设有这样一个拥有3个操作的队列: 1. EnQueue(v): 将v加入队列中 2. DeQueue(): 使队列中的队首元素删除并返回此元素 3. MaxElement: 返回队列中的最大元素 设计一种数据结构和算法,让MaxElement操作的时间复杂度尽可能地低. 思路: (1)用两个栈设计一个新的数据类型(数据类型定义为MyStack),其中一个栈用来存放数据,另一个栈用来存放最大值, 当插入数据时,第一个栈接受数据进行入栈操作,第二栈首先判断一下栈顶元素和插入元素的大小,如果

3.7 队列中取最大值操作问题

问题: 假设有这样一个拥有3个操作的队列: 1. EnQueue(v): 将v加入队列中 2. DeQueue(): 使队列中的队首元素删除并返回此元素 3. MaxElement: 返回队列中的最大元素 设计一种数据结构和算法,让MaxElement操作的时间复杂度尽可能地低. 方法:用两个栈来模拟队列 在代码中,maxStackItemIndex代表栈中最大的数的下标 link2NextMaxItem[index]表示当前index这个下标代表的数字(当前是最大的)如果没有的话,那么最大的那

程之美第3章结构之法-字符串及链表的探索3.7 队列中取最大值操作问题

#include<iostream> #include<vector> using namespace std; class stack { private: vector<int> vec;//用来保存当前进栈的值 vector<int> max_vec; public: void push(int a) { vec.push_back(a); if(max_vec.size()==0||a>vec[max_vec[max_vec.size()-1]

编程之美---桶中取黑白球

题目:有一个桶,里面有白球.黑球各100个,人们必须按照以下的规则把球取出来: 1.每次从桶里面拿出来两个球: 2.如果是两个同色的球,就再放入一个黑球: 3.如果是两个异色的球,就再放入一个白球: 问:最后桶里面只剩下一个黑球的概率是多少? 解法一:用黑白球各两个,来模拟,从小到多,化繁为简,进行分析和推断,找出其内在的规律,并归纳总结.推断出:每次减少一个球,每次拿球后,白球数要么不变,要么两个两个的减少.所以最后必然只剩一个黑球. 解法二:把黑球编号0,白球编号1,然后就相当于是异或操作了

编程之美——子数组和最大值

解法一:直接求解下标i~j的子数组和最大值:复杂度O(N^2): 代码如下: 1 #include<iostream> 2 using namespace std; 3 const int INF=1000000; 4 5 int maxSum(int arr[],int n); 6 7 int main() 8 { 9 int arr[7]={-2,5,3,-6,4,-8,6}; 10 cout<<maxSum(arr,7)<<endl; 11 return 0; 1