设计一个数据结构,有效支持队列中的以下操作:
- 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 时间到达双向链表的中间元素
- 现在通过重新链接节点在temp和temp->next之间插入元素x
- 将容量增加一
- pop__front()
- 如果size 的容量小于 1,则返回 -1
- 否则,通过重新链接节点删除head和head->next节点之间的第一个节点
- 容量减一
- 被删除元素的返回值
- pop__back():
- 如果容量小于1,则返回-1
- 否则,通过重新链接节点删除最后一个和最后一个->前一个节点之间的结束节点
- 容量减一
- 被删除元素的返回值
- pop__middle():
- 初始化节点类型的临时指针
- 通过执行 temp=temp->nex t 当前容量时间的一半来到达双向链表的中间元素
- 现在通过重新链接节点删除 temp->previous和temp->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