栈队列双端队列优先队列

Posted liugangjiayou

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了栈队列双端队列优先队列相关的知识,希望对你有一定的参考价值。

栈、队列、双端队列、优先队列

栈和队列的基本实现和特性

1.Stack:先入后出;添加、删除皆为O(1)
2.查询为 O(n)

时间复杂度

方法 复杂度
Access O(n)
Search O(n)
Insertion O(1)
Deletion O(1)

成员函数

  • 元素访问
    • top?访问栈顶元素
  • 容量
    • empty?检查底层的容器是否为空
    • size?返回容纳的元素数
  • 修改器
    • push?向栈顶插入元素
    • emplace?于顶原位构造元素
    • pop?删除栈顶元素
    • swap?交换内容

      示例代码-Stack

    Stack<Integer> stack = new Stack<>();
    stack.push(1); 
    stack.push(2); 
    stack.push(3); 
    stack.push(4); 
    System.out.println(stack); 
    System.out.println(stack.search(4)); 
    stack.pop();
    stack.pop(); 
    Integer topElement = stack.peek(); 
    System.out.println(topElement); 
    System.out.println(" 3的位置 " + stack.search(3));

队列

1.Queue:先入先出;添加、删除皆为O(1)
2.查询为 O(n)

时间复杂度

方法 复杂度
Access O(n)
Search O(n)
Insertion O(1)
Deletion O(1)

成员函数

  • 元素访问
    • front?访问第一个元素
    • back?访问最后一个元素
  • 容量
    • empty?检查底层的容器是否为空
    • size?返回容纳的元素数
  • 修改器
    • push?像队列尾部插入元素
    • emplace?于尾部原位构造元素
    • pop?删除栈顶元素
    • swap?交换内容

      示例代码-Queue

    Queue<String> queue = new LinkedList<String>(); 
    queue.offer("one"); 
    queue.offer("two"); 
    queue.offer("three"); 
    queue.offer("four"); 
    System.out.println(queue); 
    String polledElement = queue.poll(); 
    System.out.println(polledElement); 
    System.out.println(queue); 
    String peekedElement = queue.peek(); 
    System.out.println(peekedElement); 
    System.out.println(queue); 
    while(queue.size() > 0) {
         System.out.println(queue.poll()); 
         } 

    扩展

  • 双端队列
    • 简单理解:两端可以进出的
    • 插入和删除都是O(1)操作
    • QueueDeque - double ended queue
  • 优先队列
    • 插入操作:O(1)
    • 取出操作:O(logN) - 按照元素的优先级取出
    • 底层具体实现的数据结构较为多样和复杂:heap、bst(二叉搜索树)、treap

示例代码-Deque

Deque<String> deque = new LinkedList<String>(); 
deque.push("a"); 
deque.push("b"); 
deque.push("c"); 
System.out.println(deque); 
String str = deque.peek(); 
System.out.println(str); 
System.out.println(deque); 
while (deque.size() > 0) {
       System.out.println(deque.pop()); 
       }
System.out.println(deque)

第二节 LeetCode实战题目

有效的括号

class Solution {
public:
    bool isValid(string s) {
        if(s.length()%2!=0) return false;//一但是奇数说明不是有效的括号
        map<char,char> wordbook;//建立哈希表
        wordbook.insert(map<char,char>::value_type(')','('));
        wordbook.insert(map<char,char>::value_type(']','['));
        wordbook.insert(map<char,char>::value_type('}','{'));
        stack<char> mystack;//建立栈
        for(int i=0;i<s.length();i++)
        {
            if(s[i]=='['||s[i]=='{'||s[i]=='(')//匹配到左括号
                mystack.push(s[i]);//放入栈中
            else if(s[i]==']'||s[i]=='}'||s[i]==')')//匹配到右括号
            {
                if(mystack.empty()) return false;
                //匹配到右括号,栈中应该存在左括号。否则就是无效的括号
                if(wordbook[s[i]]==mystack.top())//与栈顶元素进行匹配
                {
                    mystack.pop();//匹配成功删除栈顶元素
                    continue;
                }
                else return false;
            }
        }
        if(mystack.empty()) return true;//有效的括号到最后检测结束栈中应没有元素
        else return false;
    }
};

最小栈

class MinStack {
private:
    vector<pair<int,int>> nums; // <value,current min>
    
public:
    MinStack() {
        nums = {};
    }
    
    void push(int x) {
        if ( nums.size() > 0 )
            nums.push_back(make_pair(x,min(x,nums[nums.size()-1].second)));
        else
            nums.push_back(make_pair(x,x));
    }
    
    void pop() {
        if ( nums.size() > 0 )
            nums.resize(nums.size()-1);
    }
    
    int top() {
        return nums[nums.size()-1].first;
    }
    
    int getMin() {
        return nums[nums.size()-1].second;
    }
};
/**
 * Your MinStack object will be instantiated and called as such:
 * MinStack* obj = new MinStack();
 * obj->push(x);
 * obj->pop();
 * int param_3 = obj->top();
 * int param_4 = obj->getMin();
 */

滑动窗口最大值

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        if(k==0)return {};
        vector<int>res;
        deque<size_t>window;
        /*Init K integers in the list*/
        for (size_t i = 0; i < k; i++) {
            while (!window.empty()  && nums[i] > nums[window.back()]) {
                window.pop_back();
            }
            window.push_back(i);
        }
        res.push_back(nums[window.front()]);
        /*End of initialization*/
        for (size_t i = k; i < nums.size(); i++) {
            if (!window.empty() && window.front() <= i - k) {
                window.pop_front();
            }
            while (!window.empty() && nums[i] > nums[window.back()]) {
                window.pop_back();
            }
            window.push_back(i);
            res.push_back(nums[window.front()]);
        }
        return res;
    }
};

柱状图中最大的矩形

// 扩展一下横排宽度不一样的情况
class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        stack<int> s;
        s.push(-1);
        int max_area = 0, height, width;
        for(int i = 0; i < heights.size(); ++i) {
            while(s.top() != -1 && heights[i] <= heights[s.top()]) {
                height = heights[s.top()];
                s.pop();
                width = i-s.top()-1;
                //cout<<"height:"<<height<<" width:" <<width<<endl;
                max_area = max(max_area, width*height);
                //cout<<max_area<<endl;
            }
            s.push(i);
        }
        while(s.top() != -1) {
            height = heights[s.top()];
            s.pop();
            width = heights.size() - s.top() - 1;
            max_area = max(max_area, width*height);
            //cout<<max_area<<endl;
        }
        return max_area;
    }
};

Design Circular Deque

class MyCircularDeque {
public:
    vector<int> q;
    int front,rear;
    /** Initialize your data structure here. Set the size of the deque to be k. */
    MyCircularDeque(int k) {
        q.resize(k,0); //resizing the vector(arraysize) with the given size k.
        front=-1; //intially front and rear both points to the -1 location as in case of circular queue happens.
        rear=-1;
    }
    
    /** Adds an item at the front of Deque. Return true if the operation is successful. */
    bool insertFront(int value) {
        if(isFull()){ //checking for queue is full or not.
            return false;
        }
        else{
            if(front==-1){ //in case we are pushing the element in the queue for the first time.
                insertLast(value);
            }
            else{
                front=(front+(q.size()-1))%q.size(); //by this formula front will move to the 1 pos back where it is currently if it is on 0th postion then it will take the last index (Nth) location of the array/vector. just use copy pen and tried this out.
                q[front]=value; //put the value in q of front newly location 
            }
        }
        return true;
    }
    
    /** Adds an item at the rear of Deque. Return true if the operation is successful. */
    bool insertLast(int value) {
        if(isFull()){ //checking for queue is full or not.
            return false;
        }
        else{
            if(front==-1){ //in case we are pushing the element in the queue for the first time.
                front=0;
            }
            rear=(rear+1)%q.size(); //move rear by 1 location after where it is currently. If rear is on Nth location of the index in the array then it will move to the 0th location of the array. Remember we have alreay checked for the array full cond. in above if condition.just use copy pen and tried out this formula. 
            q[rear]=value;
        }
        return true;
    }
    
    /** Deletes an item from the front of Deque. Return true if the operation is successful. */
    bool deleteFront() {
        if(isEmpty()){
            return false;
        }
        else{
            if(front==rear){ //if there is only 1 element in the queue.
                front=-1;
                rear=-1;
            }
            else{
                front=(front+1)%q.size();  //moving front by 1
            }
        }
        return true;
    }
    
    /** Deletes an item from the rear of Deque. Return true if the operation is successful. */
    bool deleteLast() {
        if(isEmpty()){
            return false;
        }
        else{
            if(front==rear){
                front=-1;
                rear=-1;
            }
            else{
                rear=(rear+(q.size()-1))%q.size();
            }
        }
        return true;
    }
    
    /** Get the front item from the deque. */
    int getFront() {
        if(isEmpty()){
            return -1;
        }
        return q[front];
    }
    
    /** Get the last item from the deque. */
    int getRear() {
        if(isEmpty()){
            return -1;
        }
        return q[rear];
    }
    
    /** Checks whether the circular deque is empty or not. */
    bool isEmpty() {
        if(front==-1 && rear==-1){
            return true;
        }
        return false;
    }
    
    /** Checks whether the circular deque is full or not. */
    bool isFull() {
        if((rear+1)%q.size()==front){
            return true;
        }
        return false;
    }
};


/**
 * Your MyCircularDeque object will be instantiated and called as such:
 * MyCircularDeque* obj = new MyCircularDeque(k);
 * bool param_1 = obj->insertFront(value);
 * bool param_2 = obj->insertLast(value);
 * bool param_3 = obj->deleteFront();
 * bool param_4 = obj->deleteLast();
 * int param_5 = obj->getFront();
 * int param_6 = obj->getRear();
 * bool param_7 = obj->isEmpty();
 * bool param_8 = obj->isFull();
 */

Trapping Rain Water

class Solution {
public:
    int trap(vector<int>& height) {
        if (height.size() < 3) return 0;
        
        register int i = 0, j = height.size() - 1;
        register int leftMax = 0, rightMax = 0, water = 0;
        
        while (i <= j) {
            if (height[i] > leftMax) leftMax = height[i];
            if (height[j] > rightMax) rightMax = height[j];
            
            if (leftMax <= rightMax) {
                water += leftMax - height[i];
                ++i;
            } else {
                water += rightMax - height[j];
                --j;
            }        
        }
        
        return water;
    }
};

以上是关于栈队列双端队列优先队列的主要内容,如果未能解决你的问题,请参考以下文章

Java Deque接口 使用方法(栈队列双端队列)

算法---队列

Python实现栈队列双端队列

Python数据结构学习笔记——队列和双端队列

《算法实战策略》-chaper19-队列栈和双端队列

第十一节 双端队列的概念和python代码实现