A queue is a linear data structure that follows the principle of First In First Out (FIFO). The first element added to the queue will be the first element to be removed from the queue. The queue is a list in which all additions to the list are made at one end, and all deletions from the list are made at the other end. The element which is first pushed into the order, the delete operation is first performed on that.
Which Queue ensures the uniqueness of the elements?
A data structure called a SetQueue includes the attributes of both sets and queues. It keeps a queue of the same components in the order they were introduced to the queue as well as a collection of unique elements
Features of SetQueue:
- When we need to keep track of a collection of distinct items and process them in the order they were added, a SetQueue comes in handy.
- In web crawling or web scraping, when we must keep track of a list of specific URLs to visit and visit those URLs in the order in which they were found, SetQueues is frequently used.
- Using a SetQueue over a standard queue or set has the main benefit of ensuring element uniqueness while also maintaining the sequence of insertion. As a result, processing pieces in the order they were added while eliminating duplications is made simple.
- Depending on the underlying data structures used to maintain the set and the queue, different SetQueue implementations may be utilized. A set is used to retain the unique elements in the sample implementation and a deque is used to keep the order of insertion. However, other data structures can also be employed, such as linked lists or hash tables.
- In general, SetQueues is a helpful data structure for keeping track of a collection of distinct elements while simultaneously maintaining the order of insertion. They are frequently employed in web crawling, web scraping, and other processes where distinct items must be handled in a particular order.
The SetQueue class has three methods:
- By constructing two data structures: a set to keep track of the unique components and a deque to keep track of the order of insertion— the __init__ method initializes the SetQueue.
def __init__( self ):
# create a set to maintain the unique elements
# create a deque to maintain the order of insertion
self . set = set ()
self .queue = deque()
|
- The SetQueue receives an element through the enqueue method. This method first checks if the value is already in the set. If it is not in the set, it adds the value to the set and also appends the value to the deque.
def enqueue( self , value):
# check if the value is not in the set
if value not in self . set :
# add the value to the set
self . set .add(value)
# append the value to the queue
self .queue.append(value)
|
- The dequeue method removes the first element from the SetQueue.This method first checks if the deque is not empty. If it is not empty, it removes and returns the first element from the deque. It also removes the same element from the set.
def dequeue( self ):
# check if the queue is not empty
if len ( self .queue) > 0 :
# remove and return the first element from the queue
value = self .queue.popleft()
# remove the same element from the set
self . set .remove(value)
return value
|
Below is the clear implementation of the above functions:
#include <iostream> #include <unordered_set> #include <queue> // SetQueue data structure template < typename T>
class SetQueue {
private :
std::unordered_set<T> set;
std::queue<T> queue;
public :
// Constructor
SetQueue() {
}
// Enqueue function
void enqueue(T value) {
if (set.find(value) == set.end()) {
set.insert(value);
queue.push(value);
}
}
// Dequeue function
T dequeue() {
if (!queue.empty()) {
T value = queue.front();
queue.pop();
set.erase(value);
return value;
}
return T();
}
// Get the length of the SetQueue
int size() const {
return queue.size();
}
}; // Main function int main() {
// Create a new SetQueue
SetQueue< int > sq;
// Enqueue some elements
sq.enqueue(1);
sq.enqueue(2);
sq.enqueue(3);
sq.enqueue(2);
// Dequeue some elements
std::cout << sq.dequeue() << std::endl;
std::cout << sq.dequeue() << std::endl;
// Enqueue some more elements
sq.enqueue(4);
sq.enqueue(3);
// Dequeue the remaining elements
std::cout << sq.dequeue() << std::endl;
std::cout << sq.dequeue() << std::endl;
// Check the length of the SetQueue
std::cout << sq.size() << std::endl;
return 0;
} |
import java.util.ArrayDeque;
import java.util.HashSet;
import java.util.Queue;
import java.util.Set;
// SetQueue data structure class SetQueue<T> {
private Set<T> set;
private Queue<T> queue;
// Constructor
public SetQueue() {
this .set = new HashSet<>();
this .queue = new ArrayDeque<>();
}
// Enqueue function
public void enqueue(T value) {
if (!set.contains(value)) {
set.add(value);
queue.offer(value);
}
}
// Dequeue function
public T dequeue() {
T value = queue.poll();
if (value != null ) {
set.remove(value);
}
return value;
}
// Get the length of the SetQueue
public int size() {
return queue.size();
}
} // Main class public class Main {
public static void main(String[] args) {
// Create a new SetQueue
SetQueue<Integer> sq = new SetQueue<>();
// Enqueue some elements
sq.enqueue( 1 );
sq.enqueue( 2 );
sq.enqueue( 3 );
sq.enqueue( 2 );
// Dequeue some elements
System.out.println(sq.dequeue());
System.out.println(sq.dequeue());
// Enqueue some more elements
sq.enqueue( 4 );
sq.enqueue( 3 );
// Dequeue the remaining elements
System.out.println(sq.dequeue());
System.out.println(sq.dequeue());
// Check the length of the SetQueue
System.out.println(sq.size());
}
} |
# Python Implementation from collections import deque
# SetQueue data structure class SetQueue:
def __init__( self ):
self . set = set ()
self .queue = deque()
# Enque Function
def enqueue( self , value):
if value not in self . set :
self . set .add(value)
self .queue.append(value)
# Deque Function
def dequeue( self ):
if len ( self .queue) > 0 :
value = self .queue.popleft()
self . set .remove(value)
return value
def __len__( self ):
return len ( self .queue)
# Create a new SetQueue sq = SetQueue()
# Enqueue some elements sq.enqueue( 1 )
sq.enqueue( 2 )
sq.enqueue( 3 )
sq.enqueue( 2 )
# Dequeue some elements print (sq.dequeue())
print (sq.dequeue())
# Enqueue some more elements sq.enqueue( 4 )
sq.enqueue( 3 )
# Dequeue the remaining elements print (sq.dequeue())
print (sq.dequeue())
# Check the length of the SetQueue print ( len (sq))
|
using System;
using System.Collections.Generic;
// SetQueue data structure class SetQueue<T>
{ private HashSet<T> set = new HashSet<T>();
private Queue<T> queue = new Queue<T>();
// Constructor
public SetQueue()
{
}
// Enqueue function
public void Enqueue(T value)
{
if (! set .Contains(value))
{
set .Add(value);
queue.Enqueue(value);
}
}
// Dequeue function
public T Dequeue()
{
if (queue.Count > 0)
{
T value = queue.Dequeue();
set .Remove(value);
return value;
}
return default (T);
}
// Get the length of the SetQueue
public int Size()
{
return queue.Count;
}
} // Main function class Program
{ static void Main()
{
// Create a new SetQueue
SetQueue< int > sq = new SetQueue< int >();
// Enqueue some elements
sq.Enqueue(1);
sq.Enqueue(2);
sq.Enqueue(3);
sq.Enqueue(2);
// Dequeue some elements
Console.WriteLine(sq.Dequeue());
Console.WriteLine(sq.Dequeue());
// Enqueue some more elements
sq.Enqueue(4);
sq.Enqueue(3);
// Dequeue the remaining elements
Console.WriteLine(sq.Dequeue());
Console.WriteLine(sq.Dequeue());
// Check the length of the SetQueue
Console.WriteLine(sq.Size());
}
} |
class GFG { constructor() {
this .set = new Set();
this .queue = [];
}
// Enqueue function
enqueue(value) {
if (! this .set.has(value)) {
this .set.add(value);
this .queue.push(value);
}
}
// Dequeue function
dequeue() {
if ( this .queue.length > 0) {
const value = this .queue.shift();
this .set. delete (value);
return value;
}
return null ;
}
// Get the length of the
// GFG
size() {
return this .queue.length;
}
} // Main function function main() {
// Create a new GFG
const sq = new GFG();
// Enqueue some elements
sq.enqueue(1);
sq.enqueue(2);
sq.enqueue(3);
sq.enqueue(2);
// Dequeue some elements
console.log(sq.dequeue());
console.log(sq.dequeue());
// Enqueue some more elements
sq.enqueue(4);
sq.enqueue(3);
// Dequeue the remaining elements
console.log(sq.dequeue());
console.log(sq.dequeue());
// Check the length of
// the GFG
console.log(sq.size());
} // main function main(); |
1 2 3 4 0
Time Complexity: O(1)
Auxiliary Space: O(n)
Advantages of SetQueue:
- It ensures that no duplicates are added.
- Enqueuing and dequeuing operations both have a time complexity of O(1) on average, which is very efficient.
- SetQueue can be used in situations where maintaining a set of unique elements in the order they were added is important.
Disadvantages of SetQueue:
- It requires more memory than using just one data structure.
- It does not preserve the order of elements that were enqueued if they were dequeued in a different order.
- SetQueue can be less efficient than a regular deque if the elements being added are always unique.