先进先出。STL中与队列对应的类模板为queue ,常用操作:front()返回第一个元素;back()返回最后一个元素;push()向队尾插入元素;pop()删除第一个元素;empty()检查容器是否为空;size()返回容器的元素数。所有操作都在O(1)时间内完成。 关于队列的实现方式,详见: 栈与队列-顺序队列与链队列类模板的实现(数据结构基础 第3周)
题目:用两个栈实现一个队列。请实现它的两个函数appendTail和deleteHead,分别完成在队列尾部插入节点和在队列头部删除结点的功能。 分析:相关题目:用两个队列实现一个栈。 代码实现
template<typename T> class CQueue { public: CQueue(void); ~CQueue(void); void appendTail(const T& node); T deleteHead(); private: stack<T> stack1; stack<T> stack2; }; template<typename T> CQueue<T>::CQueue(void) {} template<typename T> CQueue<T>::~CQueue(void) {} template<typename T> void CQueue<T>::appendTail(const T& node) { stack1.push(node); } template<typename T> T CQueue<T>::deleteHead() { if(stack2.empty()) { while(!stack1.empty()) { T data=stack1.top(); stack1.pop(); stack2.push(data); } } if(stack2.empty()) throw "The queue is empty."; T head=stack2.top(); stack2.pop(); return head; }测试用例
题目:给定一个数组和滑动窗口的大小,请找出所有滑动窗口里的最大值。例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,它们的最大值分别为{4,4,6,6,6,5},如表8.3所示。 分析方法1,笨方法,老老实实滑动;方法2,对方法1找冗余,一句话核心思想:维护一个队列,一直保持队列的头元素为滑动至当前位置时滑窗内的最大元素;方法3,我们实现过用 O(1) 时间得到最大值的栈,也实现过用两个栈实现队列,把这两者结合起来就是能够在 O(1) 时间获得最大值的队列。 代码实现
//笨方法,时间复杂度$O(nk)$ int SlidingWindowMaximum_1(const vector<int>& input, int windowSize, vector<int>& result) { int dataSize = input.size(); if (windowSize < 1) return 1; if (dataSize < windowSize) return 1; deque<int> cache(input.begin(), input.begin()+ windowSize-1); for (int i = windowSize - 1; i<dataSize; i++) { cache.push_back(input.at(i)); result.push_back(*max_element(cache.begin(), cache.end())); //此句时间复杂度为O(K) cache.pop_front(); } return 0; } //找冗余,时间复杂度$O(n)$ //核心思想:维护一个队列,一直保持队列的头元素为滑动至位置i时滑窗内的最大元素。 int SlidingWindowMaximum_2(const vector<int>& input, int windowSize, vector<int>& result) { int dataSize = input.size(); if (windowSize < 1) return 1; if (dataSize < windowSize) return 1; deque<int> cache(input.begin(), input.begin() + windowSize - 1); for (int i = windowSize - 1; i<dataSize; i++) { if (cache.size() >= windowSize) { //队列已满 cache.pop_front(); //取出第一个 cache.push_back(input.at(i)); cache.erase(cache.begin(), max_element(cache.begin(), cache.end()) ); //队列中最大元素之前的元素已毫无意义 } else { if (!cache.empty() && input.at(i) > cache.front()) { //如果元素i大于队列中的最大元素(即头元素),则队列中已存的所有元素已毫无意义。此处一定要判断队列是否为空,要不然怎么能取头元素front()呢? cache.clear(); } cache.push_back(input.at(i)); } result.push_back(cache.front()); //此句时间复杂度为O(K) } return 0; }测试用例
vector<int> input = { 2, 3, 4, 2, 6, 2, 5, 1 };题目: 从上往下打印出二叉树的每个结点,同一层的结点按照从左到右的顺序打印。 分析: 也就是树的层序遍历了。 代码实现
int SequenceTraversalByQueue(BinaryTreeNode* root) { if(!root) return 1; queue<BinaryTreeNode*> q; q.push(root); BinaryTreeNode* p=NULL; while(!q.emtpy()){ p=q.front(); cout << p->value << " "; if(p->left) q.push(p->left); if(p->right) q.push(p->right); q.pop(); } return 0; }