Queries to search an element in an array and move it to front after every query


Introduction

In this tutorial, the task is to use queries to search for an element in an array. It is to push to the front after every query in C++. To implement this task, it takes an array A with elements from 1 to 5 and a query array Q for finding the element in A and moving it to the front of the array. The output is the index number of the searched elements. We use two methods for moving array elements to the front as per the query array.

  • Naive Approach − Iterate through the array of elements as per indices while using a hashtable for searching those elements.

  • Using Fenwick Tree for searching and updating the new array − Fenwick tree or Binary Index Tree is an efficient data structure for frequently updating arrays and queries.

Demonstration

Input = Q[] = {3, 2, 2, 3} A = 5
Output = The indices after moving query element to the front are 2 2 0 1

Explanation

The array in the above demonstration is [1, 2, 3, 4,5]. Using the query array [3, 2, 2, 3] find the indices of that array element. Calculate the updated array in the following manner −

Query 1 − Find 3, the index of this element in array A is 2. Move the resulting element to the front of the updated array.

After searching for 3 at index 2 and moving elements to the front. The updated array is {3, 1, 2, 4, 5}.

Query 2 − Find 2, the index of this element in array A is 2. Move the resulting element to the front of the updated array.

After searching 2 at index 2 and moving elements to the front. The updated array is {2, 3, 1, 4, 5}.

Query 3 − Find 2, the index of this element in array A is 0. Move the resulting element to the front of the updated array.

After searching 2 at index 2 and moving elements to the front. The updated array is {2, 3, 1, 4, 5}.

Query 4 − Find 3, the index of this element in array A is 1. Move the resulting element to the front of the updated array.

After searching for 3 at index 1 and moving elements to the front. Updated array is {3, 2, 1, 4, 5}. The result is 2 2 0 1.

C++ Library Functions

  • sizeof() − It is a standard C++ library function. It calculates the size of an array, variable or data type at the compile time.

sizeof(variable);
  • Vector − It is a dynamic array in C++. It is defined in the <vector> header file. It provides faster and effective updation and deletion of the array elements.

vector<data_type> vector_name;
  • swap() − It is a predefined C++ library function. It swap or interchange position of two elements. It takes two parameters for swapping.

swap(value1, value2);
  • push_back() − It is a predefined function of vector class and is defined in the <vector> header file. It pushes or inserts an element to the back of the vector array.

vector_name.push_back(value);
  • unordered_map() − It is a container class in C++ that stores data in mapped value and key value pairs. It enhances the processing of array functions like update, delete, insert.

unordered_map<data_type> unordered_map_name;

Algorithm

  • Initialize the query array and take the value of another array 5.

  • The queries represent indices of the array.

  • Search for the array element as per the query using a hashtable.

  • Update the new array while moving the searched element to the front via swapping.

  • Print the result.

Example 1

Here we implement the problem statement in C++. We use a basic approach that includes a hashtable for searching the elements as per the indices of the Query array. After searching the element move it to the front of the array while updating array A.

#include <bits/stdc++.h>
using namespace std;
 
// user-defined function for query processing
vector<int> processingQueries(int Q[], int a, int s){
   int f[a + 1], p[a + 1];
 
   for (int x = 1; x <= a; x++){
      f[x - 1] = x;
      p[x] = x - 1;
   }
 
   vector<int> result;
 
   // iterating array for query
   for (int x = 0; x < s; x++){
      int qa = Q[x];
      
      int ps = p[qa];
 
      result.push_back(ps);
 
      for (int x = ps; x > 0; x--){
 
         // swapping element positions
         swap(f[x], f[x - 1]);
 
         p[f[x]] = x;
      }
 
      p[f[0]] = 0;
   }
 
   // returning result
   return result;
}
 
// code controller
int main(){
   // query array
   int Q[] = { 4, 1, 2, 1 };
   int s = sizeof(Q) / sizeof(Q[0]);
 
   int a = 5;
 
   vector<int> result;
 
   // calling function
   result = processingQueries(Q, a, s);
 
   // Printing the output after queries 
   cout<< "Updated array after searching the elements is: ";
   for (int x = 0; x < result.size(); x++)
      cout << result[x] << " ";
 
   return 0;
}

Output

Updated array after searching the elements is: 3 1 2 1 

Example 2

We implement the problem statement in C++ using the Fenwick tree which is a binary index tree. Initialize an array for queries and use the Fenwick tree for searching for the query element in the array 'a'. Instead of assigning an index value of 0 to the array, assign a -1 index value to query 1, -2 to query 2, and so on.

#include <bits/stdc++.h>
using namespace std;

// Function for updating the fenwick tree
void updateArray(vector<int>& Fentree, int x, int v){
   while (x < Fentree.size()) {
      Fentree[x] += v;
      x += (x & (-x));  
   } 
}

int calSum(vector<int>& Fentree, int x)  {
   int sum = 0;
   while (x > 0) {
      sum += Fentree[x];
      x -= (x & (-x));  
   }
   return sum; 
}
    
// function to process the queries
vector<int> processingQueries(vector<int>& q, int m) {
   vector<int> r, Fentree((2 * m) + 1, 0);
   unordered_map<int, int> hm;
   for (int x = 1; x <= m; ++x) {
      hm[x] = x + m;
      updateArray(Fentree, x + m, 1);  
   }
   for (int que : q){
      r.push_back(calSum(Fentree, hm[que]) - 1);  //pushing element to the front
      updateArray(Fentree, hm[que], -1);
      updateArray(Fentree, m, 1);
      hm[que] = m;
      m--;
   }
   return r;
}  
 
int main(){
   vector<int> Q = { 4, 2, 2, 4};   // initializing Query array
   int m = 5;
   vector<int> result;
   result = processingQueries(Q, m);
   cout << "The indices after moving query element to the front are ";
   for (int x = 0;x < result.size(); x++)
      cout << result[x] << " ";
   return 0;
}

Output

The indices after moving query element to the front are 3 2 0 1

Conclusion

We have reached the end of this tutorial on applying range queries to search for an element and push it to the front of the array. We used two approaches for implementing the task: naive and Fenwick tree for searching. Elaborated on the task with some examples to understand the problem statement requirement. Used different C++ library functions to implement the problem statement.

Updated on: 03-Oct-2023

52 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements