📜  使用 STL 设计前中后队列

📅  最后修改于: 2021-09-07 05:14:13             🧑  作者: Mango

设计一个数据结构,有效支持队列中的以下操作:

  • push__front(x):在队列前面插入一个元素。
  • push__middle(x):在队列中间插入元素。
  • push__back(x):在队列后面插入元素。
  • pop__front()移除队列的前端元素并返回它。如果队列为空,则返回-1。
  • pop__middle():移除队列的中间元素并返回。如果队列为空,则返回-1。
  • pop__back():移除队列的后部元素并返回。如果队列为空,则返回-1。

例子:

Operations Queue Return
push__front(4) 4 _
push__back(2) 4, 2 _
push__middle(1) 4, 1, 2 _
pop_front() 1, 2 4
pop__middle() 2 1
pop__front() _ 2
pop__front() _ -1

基于双端队列的方法:这个问题可以使用两个双端队列来解决。这个想法是使用两个双端队列。队列后面的操作在第二个双端队列的末尾进行,中间的操作在第一个双端队列的末尾进行。请按照以下步骤解决问题:

  • 如果第一个 deque 的大小大于第二个 deque 的大小,则删除第一个 deque 的 end 元素并将其添加到第二个 deque 的前面。
  • 如果第二个双端队列的大小超过第一个双端队列的大小 1,则移除第二个双端队列的前端元素并将其推入第一个双端队列的末尾。
  • 如果第一个双端队列的大小大于第二个双端队列,则从第一个双端队列中取出 back 元素并插入到第二个双端队列中。
  • push__front(x):使用 push_front() 在第一个双端队列的前面插入一个元素 x。
  • push__back(x):使用 push_back() 在第二个双端队列的末尾插入一个元素 x
  • push__middle(x):使用 push_back() 在第一个双端队列的末尾插入元素 x。
  • pop__front():如果 deque 的大小大于 0,则使用 pop_front() 删除第一个 deque 的前端元素。
  • pop__back():如果 deque 的大小大于 0,则使用 pop_back() 删除第二个 deque 的结束元素。
  • pop__middle():如果 deque 的大小大于使用 pop_back(),则删除第一个 deque 的结束元素。

下面是上述方法的实现:

C++
// C++ pogram to implement
// the above approach
  
#include 
using namespace std;
  
// Create class Queue.
class Queue {
  
    // Initalize two deques
    deque first, second;
  
    // Function to balance the size of
    // first ans second deque
    void equalizeSizedeque1deque2()
    {
  
        // If size of less than second
        if (first.size() <= second.size())
            return;
  
        // Insert the last element of
        // first deque into second deque
        second.push_front(first.back());
  
        // Pop the front element
        // of the deque
        first.pop_back();
    }
  
    // Function to balance the size of
    // second and first deque
    void equalizeSizedeque2deque1()
    {
  
        // if size of second deque deceed
        // the first deque by 1
        if (second.size() <= first.size() + 1)
            return;
  
        // Insert front element of second
        // deque into the first
        first.push_back(second.front());
  
        // Remove front element of
        // second deque
        second.pop_front();
    }
  
public:
    // Function to insert element
    // at front of queue
    void push__front(int val)
    {
  
        // Insert val into first deque
        first.push_front(val);
  
        // Balancing the size of second
        equalizeSizedeque1deque2();
    }
  
    // Function to insert val
    // into the middle of queue
    void push__middle(int val)
    {
  
        // Insert val into first deque
        first.push_back(val);
  
        // Balancing the size of
        // second deque
        equalizeSizedeque1deque2();
    }
  
    // Function to insert val
    // into back of queue
    void push__back(int val)
    {
  
        // Insert val into second deque
        second.push_back(val);
  
        // Balancing the size of
        // second deque
        equalizeSizedeque2deque1();
    }
  
    // Function to pop front
    // element from queue
    int pop__front()
    {
  
        // If first deque and second
        // deque is empty
        if (first.empty() && second.empty())
            return -1;
  
        int ans;
  
        // If the first deque
        // is empty
        if (first.empty()) {
  
            // Stores front element
            // of second deque
            ans = second.front();
  
            // Pop front element of
            // second deque
            second.pop_front();
        }
        else {
  
            // Stores front element
            // of first deque
            ans = first.front();
  
            // Pop front element of
            // first deque
            first.pop_front();
  
            // Balancing the size of first
            equalizeSizedeque2deque1();
        }
        return ans;
    }
  
    // Function to pop middle
    // element of queue
    int pop__middle()
    {
  
        // If both deques are empty
        if (first.empty() && second.empty())
            return -1;
  
        // Stores mid element
        // of queue
        int ans;
  
        // If size of both deque is equal
        if (first.size() == second.size()) {
  
            // Stores back element
            // of first deque
            ans = first.back();
  
            // Pop back element of
            // first deque
            first.pop_back();
        }
        else {
  
            // Stores front element
            // of second deque
            ans = second.front();
  
            // Pop front element
            // from second deque
            second.pop_front();
        }
        return ans;
    }
  
    // Function to remove mid
    // element from queue
    int pop__back()
    {
  
        // If both the deque are empty
        if (first.empty() && second.empty())
            return -1;
  
        // Stores back element from
        // second deque
        int ans = second.back();
  
        // Pop back element from
        // second deque
        second.pop_back();
  
        // Balancing the size of second
        equalizeSizedeque1deque2();
        return ans;
    }
};
  
// Driver code
int main()
{
    Queue q;
    q.push__front(1);
    q.push__back(2);
    q.push__middle(3);
    cout << q.pop__middle() << " ";
    cout << q.pop__back() << " ";
    cout << q.pop__front() << " ";
    return 0;
}


C++
// C++ program to implement
// the above approach
  
#include 
using namespace std;
  
// Create structure of queue
class Queue {
  
    list l;
  
public:
    // Function to push element
    // at front of the queue
    void push__front(int val)
    {
        l.push_front(val);
    }
  
    // Function to push element
    // at middle of the queue
    void push__middle(int val)
    {
  
        auto itr = l.begin();
  
        // Traverse the list
        advance(itr, l.size() / 2);
  
        // Insert element into
        // middle of the list
        l.insert(itr, val);
    }
  
    // Function to insert element
    // at the back of the queue
    void push__back(int val)
    {
        l.push_back(val);
    }
  
    // Function to pop element from
    // front of the queue
    int pop__front()
    {
  
        // Stores front element
        // of queue
        int val = -1;
        if (l.size()) {
            val = l.front();
            l.pop_front();
        }
        return val;
    }
  
    // Function to pop middle element
    // of the queue
    int pop__middle()
    {
        int val = -1;
        if (l.size()) {
            auto itr = l.begin();
  
            // Traverse the list
            advance(itr, (l.size() - 1) / 2);
            val = *itr;
  
            // Remove mid element
            // from queue
            l.erase(itr);
        }
        return val;
    }
  
    // Function to pop end
    // element of the queue
    int pop__back()
    {
  
        // Stores back element
        // of the queue
        int val = -1;
  
        if (l.size()) {
            val = l.back();
            l.pop_back();
        }
        return val;
    }
};
  
// Drivers code
int main()
{
    Queue q;
    q.push__front(1);
    q.push__back(2);
    q.push__middle(3);
    cout << q.pop__middle() << " ";
    cout << q.pop__back() << " ";
    cout << q.pop__front() << " ";
    return 0;
}


C++
// C++ program to implement
// the above approach
  
#include 
using namespace std;
  
// Structure of Queue class
class Queue {
public:
    // Create node structure
    struct node {
  
        // Stores data value
        // of a node
        int value;
  
        // Stores pointer to
        // next node
        node* next;
  
        // Stores pointer to
        // previous node
        node* previous;
  
        // Constructor
        node(int value)
            : value(value), next(NULL), previous(NULL)
        {
        }
    };
  
    typedef struct node node;
  
    // Sizeof the queue
    int capacity = 0;
  
    // Stores address of
    // head node
    node* head;
  
    // Stores address of
    // last node
    node* last;
  
    // Constructor
    Queue()
    {
        head = new node(-1);
        last = new node(-1);
        head->next = last;
        head->previous = NULL;
        last->previous = head;
        last->next = NULL;
    }
  
    // Function to insert element
    // at front of queue
    void push__front(int val)
    {
  
        // Stores address of current node
        node* current = new node(val);
  
        // Stores address of next node
        current->next = head->next;
        head->next->previous = current;
  
        // Update next node of head node
        head->next = current;
  
        // Update previous node
        // of current node
        current->previous = head;
  
        // Update capacity
        capacity++;
    }
  
    // Function to insert element
    // at middle of queue
    void push__middle(int val)
    {
  
        // Stores half of total
        // count of elements
        int middle = capacity / 2;
  
        // Stores head node
        node* temp = head;
  
        // Traverse the list
        for (int i = 0; i < middle; i++) {
  
            // Update temp
            temp = temp->next;
        }
  
        // Initialize a node
        node* current = new node(val);
  
        // Update next node
        // of current node
        current->next = temp->next;
  
        // Update previous node
        // of current node
        current->previous = temp;
        temp->next->previous = current;
        temp->next = current;
  
        // Update capacity
        capacity++;
    }
  
    // Function to insert element at
    // the back of queue
    void push__back(int val)
    {
  
        // Initialize a new node
        node* current = new node(val);
  
        // Update next node of
        // current node
        current->next = last;
  
        // Update previous node of
        // current node
        current->previous = last->previous;
        last->previous->next = current;
        last->previous = current;
  
        // Update capacity
        capacity++;
    }
  
    // Function to pop element
    // from front of queue
    int pop__front()
    {
        if (capacity > 0) {
  
            // Stores data value
            // of next node
            int result
                = head->next->value;
  
            head->next->next->previous
                = head;
  
            // Update next node head node
            head->next = head->next->next;
  
            // Update capacity
            capacity--;
            return result;
        }
        return -1;
    }
  
    // Function to pop middle
    // element of queue
    int pop__middle()
    {
  
        // If count of elements
        // greater than 0
        if (capacity > 0) {
  
            // Stores half of total count
            // of elements of queue
            int middle = (capacity + 1) / 2;
  
            // Stores head node
            node* temp = head;
  
            // Traverse the list
            for (int i = 0; i < middle - 1; i++) {
  
                // Update temp
                temp = temp->next;
            }
  
            // Stores value of next node
            int result = temp->next->value;
  
            temp->next->next->previous = temp;
            temp->next = temp->next->next;
  
            // Update capacity
            capacity--;
  
            return result;
        }
        return -1;
    }
  
    // Function to remove element
    // from the front of queue
    int pop__back()
    {
  
        // If count of elements in
        // queue greater than 0
        if (capacity > 0) {
  
            // Stores previous data
            // value of last node
            int result = last->previous->value;
            last->previous->previous->next = last;
            last->previous = last->previous->previous;
  
            // Update capacity
            capacity--;
            return result;
        }
        return -1;
    }
};
  
// Driver Code
int main()
{
    Queue q;
    q.push__front(1);
    q.push__back(2);
    q.push__middle(3);
    cout << q.pop__middle() << " ";
    cout << q.pop__back() << " ";
    cout << q.pop__front() << " ";
    return 0;
}


输出:

3 2 1

时间复杂度分析:

push__front(x) pop__front() push__back(x) pop__back() push__middle(x) pop__middle()
O(1) O(1) O(1) O(1) O(1) O(1)

基于列表的方法:按照以下步骤解决问题:

  • push__front(x):使用 push_front() 在列表的前面插入一个元素x。
  • push__back(x):使用 push_back() 在第二个列表的末尾插入一个元素x
  • push__middle(x):使用advance()遍历列表,然后使用insert()在列表的中间位置插入元素
  • pop__front():如果列表的大小大于0,则使用 pop_front()删除列表的前面元素,否则返回 -1
  • pop__back():如果列表的大小大于 0,则使用 pop_back() 删除列表的最后一个元素,否则返回-1
  • pop__middle():如果列表的大小大于0 ,则使用 Advance() 迭代到列表的中间元素,然后使用 erase() 擦除该位置的元素。否则,返回-1

下面是上述方法的实现:

C++

// C++ program to implement
// the above approach
  
#include 
using namespace std;
  
// Create structure of queue
class Queue {
  
    list l;
  
public:
    // Function to push element
    // at front of the queue
    void push__front(int val)
    {
        l.push_front(val);
    }
  
    // Function to push element
    // at middle of the queue
    void push__middle(int val)
    {
  
        auto itr = l.begin();
  
        // Traverse the list
        advance(itr, l.size() / 2);
  
        // Insert element into
        // middle of the list
        l.insert(itr, val);
    }
  
    // Function to insert element
    // at the back of the queue
    void push__back(int val)
    {
        l.push_back(val);
    }
  
    // Function to pop element from
    // front of the queue
    int pop__front()
    {
  
        // Stores front element
        // of queue
        int val = -1;
        if (l.size()) {
            val = l.front();
            l.pop_front();
        }
        return val;
    }
  
    // Function to pop middle element
    // of the queue
    int pop__middle()
    {
        int val = -1;
        if (l.size()) {
            auto itr = l.begin();
  
            // Traverse the list
            advance(itr, (l.size() - 1) / 2);
            val = *itr;
  
            // Remove mid element
            // from queue
            l.erase(itr);
        }
        return val;
    }
  
    // Function to pop end
    // element of the queue
    int pop__back()
    {
  
        // Stores back element
        // of the queue
        int val = -1;
  
        if (l.size()) {
            val = l.back();
            l.pop_back();
        }
        return val;
    }
};
  
// Drivers code
int main()
{
    Queue q;
    q.push__front(1);
    q.push__back(2);
    q.push__middle(3);
    cout << q.pop__middle() << " ";
    cout << q.pop__back() << " ";
    cout << q.pop__front() << " ";
    return 0;
}
输出:
3 2 1 

时间复杂度分析:

push__front(x) pop__front() push__back(x) pop__back() push__middle(x) pop__middle()
O(1) O(1) O(1) O(1) O(N) O(N)

基于双链表的方法:这个问题也可以使用双链表来解决,而不使用 STL,通过存储节点和最后节点的地址。请按照以下步骤解决问题:

  • push__front(x):
    • 分配存储数据值x的空间,并将地址存储在当前节点指针中
    • 通过在头节点和头节点- >下一个节点之间链接当前节点来插入元素x
    • 将容量增加一
  • push__back(x):
    • 分配存储数据值x的空间,并将地址存储在当前节点指针中
    • 通过在最后一个节点最后一个->前一个节点之间链接当前节点来插入元素x
    • 将容量增加一
  • push__middle(x):
    • 分配存储数据值x的空间,并将地址存储在当前节点指针中
    • 初始化节点类型的临时指针
    • 通过执行temp=temp->next half of current capacity 时间到达双向链表的中间元素
    • 现在通过重新链接节点在temptemp->next之间插入元素x
    • 容量增加一
  • pop__front()
    • 如果size 的容量小于 1,则返回 -1
    • 否则,通过重新链接节点删除headhead->next节点之间的第一个节点
    • 容量减一
    • 被删除元素的返回值
  • pop__back():
    • 如果容量小于1,则返回-1
    • 否则,通过重新链接节点删除最后一个最后一个->前一个节点之间的结束节点
    • 容量
    • 被删除元素的返回值
  • pop__middle():
    • 初始化节点类型的临时指针
    • 通过执行 temp=temp->nex t 当前容量时间的一半来到达双向链表的中间元素
    • 现在通过重新链接节点删除 temp->previoustemp->next节点之间的临时节点
    • 容量减一
    • 被删除元素的返回值

    下面是上述方法的实现:

    C++

    // C++ program to implement
    // the above approach
      
    #include 
    using namespace std;
      
    // Structure of Queue class
    class Queue {
    public:
        // Create node structure
        struct node {
      
            // Stores data value
            // of a node
            int value;
      
            // Stores pointer to
            // next node
            node* next;
      
            // Stores pointer to
            // previous node
            node* previous;
      
            // Constructor
            node(int value)
                : value(value), next(NULL), previous(NULL)
            {
            }
        };
      
        typedef struct node node;
      
        // Sizeof the queue
        int capacity = 0;
      
        // Stores address of
        // head node
        node* head;
      
        // Stores address of
        // last node
        node* last;
      
        // Constructor
        Queue()
        {
            head = new node(-1);
            last = new node(-1);
            head->next = last;
            head->previous = NULL;
            last->previous = head;
            last->next = NULL;
        }
      
        // Function to insert element
        // at front of queue
        void push__front(int val)
        {
      
            // Stores address of current node
            node* current = new node(val);
      
            // Stores address of next node
            current->next = head->next;
            head->next->previous = current;
      
            // Update next node of head node
            head->next = current;
      
            // Update previous node
            // of current node
            current->previous = head;
      
            // Update capacity
            capacity++;
        }
      
        // Function to insert element
        // at middle of queue
        void push__middle(int val)
        {
      
            // Stores half of total
            // count of elements
            int middle = capacity / 2;
      
            // Stores head node
            node* temp = head;
      
            // Traverse the list
            for (int i = 0; i < middle; i++) {
      
                // Update temp
                temp = temp->next;
            }
      
            // Initialize a node
            node* current = new node(val);
      
            // Update next node
            // of current node
            current->next = temp->next;
      
            // Update previous node
            // of current node
            current->previous = temp;
            temp->next->previous = current;
            temp->next = current;
      
            // Update capacity
            capacity++;
        }
      
        // Function to insert element at
        // the back of queue
        void push__back(int val)
        {
      
            // Initialize a new node
            node* current = new node(val);
      
            // Update next node of
            // current node
            current->next = last;
      
            // Update previous node of
            // current node
            current->previous = last->previous;
            last->previous->next = current;
            last->previous = current;
      
            // Update capacity
            capacity++;
        }
      
        // Function to pop element
        // from front of queue
        int pop__front()
        {
            if (capacity > 0) {
      
                // Stores data value
                // of next node
                int result
                    = head->next->value;
      
                head->next->next->previous
                    = head;
      
                // Update next node head node
                head->next = head->next->next;
      
                // Update capacity
                capacity--;
                return result;
            }
            return -1;
        }
      
        // Function to pop middle
        // element of queue
        int pop__middle()
        {
      
            // If count of elements
            // greater than 0
            if (capacity > 0) {
      
                // Stores half of total count
                // of elements of queue
                int middle = (capacity + 1) / 2;
      
                // Stores head node
                node* temp = head;
      
                // Traverse the list
                for (int i = 0; i < middle - 1; i++) {
      
                    // Update temp
                    temp = temp->next;
                }
      
                // Stores value of next node
                int result = temp->next->value;
      
                temp->next->next->previous = temp;
                temp->next = temp->next->next;
      
                // Update capacity
                capacity--;
      
                return result;
            }
            return -1;
        }
      
        // Function to remove element
        // from the front of queue
        int pop__back()
        {
      
            // If count of elements in
            // queue greater than 0
            if (capacity > 0) {
      
                // Stores previous data
                // value of last node
                int result = last->previous->value;
                last->previous->previous->next = last;
                last->previous = last->previous->previous;
      
                // Update capacity
                capacity--;
                return result;
            }
            return -1;
        }
    };
      
    // Driver Code
    int main()
    {
        Queue q;
        q.push__front(1);
        q.push__back(2);
        q.push__middle(3);
        cout << q.pop__middle() << " ";
        cout << q.pop__back() << " ";
        cout << q.pop__front() << " ";
        return 0;
    }
    
    输出:
    3 2 1
    

    时间复杂度分析:

    push__front(x) pop__front() push__back(x) pop__back() push__middle(x) pop__middle()
    O(1) O(1) O(1) O(1) O(N) O(N)

    如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live