标签: 编程数据结构classstruct算法优化
2012-07-19 23:39 3386人阅读 收藏 举报
问题:
假设有这样一个拥有3个操作的队列:
1. EnQueue(v): 将v加入队列中
2. DeQueue(): 使队列中的队首元素删除并返回此元素
3. MaxElement: 返回队列中的最大元素
设计一种数据结构和算法,让MaxElement操作的时间复杂度尽可能地低。
解法1:
用最大堆来维护队列中的节点,队列用单链表表示,每个节点包含数据,而最大堆用数组表示,数组元素为节点的指针。入队的时间复杂度为O(logn),出队的时间复杂度为O(n),达不到书上的O(logn),取最大值的时间复杂度为O(1)。
- <span style="font-size:18px;">#include <iostream>
- #include <algorithm>
- #include <vector>
- using namespace std;
-
-
-
- class Queue
- {
- public:
-
- struct Node
- {
- Node(int d):data(d),next(0){}
- int data;
- Node *next;
- };
-
- Queue() {begin=end=0;vec.push_back(NULL);}
-
- void EnQueue(int data)
- {
- Node *nd = new Node(data);
-
- if (vec.size() == 1)
- {
- begin = end = 1;
- vec.push_back(nd);
- return;
- }
-
- vec.push_back(nd);
- vec[end]->next = nd;
-
- end = vec.size()-1;
- while (end>>1 >= 1)
- {
- if (nd->data <= vec[end>>1]->data)
- break;
- vec[end] = vec[end>>1];
-
- if (end>>1 == begin)
- begin = end;
- end >>= 1;
- }
- vec[end] = nd;
- }
-
- int DeQueue()
- {
-
- if (vec.size() == 1)
- {
- begin = end = 0;
- return 0;
- }
-
- int data = vec[begin]->data;
- Node *nextnd = vec[begin]->next;
- delete vec[begin];
-
- if (begin < vec.size()-1)
- {
- Node *nd = vec[vec.size()-1];
- vec.pop_back();
-
- int nextbegin = begin<<1;
- while (nextbegin <= vec.size()-1)
- {
-
- if (nextbegin+1 <= vec.size()-1 &&
- vec[nextbegin+1]->data > vec[nextbegin]->data)
- nextbegin++;
-
- if (nd ->data >= vec[nextbegin]->data)
- break;
- vec[begin] = vec[nextbegin];
-
- if (nextbegin == end)
- end = begin;
- begin = nextbegin;
- nextbegin <<= 1;
- }
- vec[begin] = nd;
-
- if (end >= vec.size())
- end = begin;
- }
- else
-
- vec.pop_back();
-
- int i;
- for (i=1; i<vec.size(); ++i)
- if (vec[i] == nextnd)
- break;
- begin = i;
- return data;
- }
-
-
- int maxElement()
- {
- return vec[1]->data;
- }
-
- private:
- vector<Node*> vec;
- int begin, end;
- };
-
-
- int main()
- {
- const int n = 11;
- int data[] = {7, 4, 15, 9, 5, 10, 13, 3, 20, 17, 19};
- int i;
- Queue q;
- for (i=0; i<n/2; i++)
- q.EnQueue(data[i]);
- int d = q.DeQueue();
- d = q.DeQueue();
- d = q.DeQueue();
- d = q.DeQueue();
- d = q.DeQueue();
- d = q.DeQueue();
- d = q.DeQueue();
- for (; i<n; i++)
- q.EnQueue(data[i]);
- }</span>
解法2:将队列用两个栈来表示。栈在加入数据时,判断最大数是否发生改变,若改变,要记录新的最大数的位置。栈在删除数据时,要判断被删除的数是否是最大数,若是,则要弹出当前的最大数的位置。队列的入队操作的时间复杂度为O(1)。对于出队操作,虽然如果栈sa为空时,栈sb会将所有数据弹出并压入到栈sa中,这个操作不是O(1),但经过平摊分析的记账方法(具体见算法导论)可知其平均时间时间复杂度为O(1)。取最大值的时间复杂度为O(1)。
- <span style="font-size:18px;">#include <iostream>
- #include <algorithm>
- #include <vector>
- using namespace std;
-
-
- class Stack
- {
- public:
- void Push(int d)
- {
- vec.push_back(d);
-
- if (maxvec.size()==0 || d>vec[maxvec[maxvec.size()-1]])
- {
- maxvec.push_back(vec.size()-1);
- }
- }
-
- int Pop()
- {
- if (vec.size()==0)
- return 0;
-
- if (vec.size()-1 == maxvec[maxvec.size()-1])
- maxvec.pop_back();
- int d = vec[vec.size()-1];
- vec.pop_back();
- return d;
- }
-
- bool empty()
- {
- return maxvec.size()==0;
- }
-
- int maxElement()
- {
- int maxpos = maxvec[maxvec.size()-1];
- return vec[maxpos];
- }
-
- private:
- vector<int> vec;
- vector<int> maxvec;
- };
-
-
- class Queue
- {
- public:
- void EnQueue(int d)
- {
- sb.Push(d);
- }
-
- int DeQueue()
- {
- if (sa.empty())
- {
- while (!sb.empty())
- {
- sa.Push(sb.Pop());
- }
- }
- return sa.Pop();
- }
- int maxElement()
- {
- return max(sa.maxElement(), sb.maxElement());
- }
-
- private:
- Stack sa, sb;
- };
-
-
- int main()
- {
- const int n = 11;
- int data[] = {7, 4, 15, 9, 5, 10, 13, 3, 20, 17, 19};
- int i;
- Queue q;
- for (i=0; i<n/2; i++)
- q.EnQueue(data[i]);
- int d = q.DeQueue();
- d = q.DeQueue();
- d = q.DeQueue();
- d = q.DeQueue();
- d = q.DeQueue();
- d = q.DeQueue();
- d = q.DeQueue();
- for (; i<n; i++)
- q.EnQueue(data[i]);
- }</span>