Vector in C++

আসসালামুআলাইকুম। আমি আজকে ভেক্টর নিয়ে কিছু লিখছি। এটা আশা করি অনেকেই ব্যবহার করতে পার। যারা যারা পারনা তাদের জন্যই মূলত এই লেখা।
ভেক্টর C++ এর STL (Standard Template Library) এর একটা কন্টেইনার। STL কন্টেইনারের মধ্যে আরো আছে ম্যাপ, সেট, কিউ, ডি-কিউ, স্ট্যাক ইত্যাদি। সেগুলো নিয়ে পরে আলোচনা করবো। C/C++ এ অ্যারে আমরা সবাই ব্যবহার করেছি। ভেক্টর হচ্ছে অ্যারেরই স্পেশালাইজড রুপ যা প্রায় অ্যারের মতই, কিন্তু এতে অনেক সুবিধা আছে যা অ্যারেতে নাই। প্রথমত, এটার সাইজ অ্যারের মত ফিক্সড রাখা লাগেনা। চাইলে ইচ্ছামত এক্সটেন্ড করা যায়। তাই যদি তোমার মনে হয় যে এমন একটা অ্যারে নিবা যেটার সাইজ আগে থেকে ডিফাইন না করে আস্তে আস্তে এটায় একটা একটা করে সংখ্যা রাখবা তখন ভেক্টর ব্যাবহার করতে পার। আবার চাইলে আগে থেকে অ্যারের মত ভেক্টরের সাইজ ও ডিফাইন করে আসতে পারো। প্রবলেম নাই। ভেক্টরের ম্যানিপুলেশন অ্যারের তুলনায় অনেক সহজ, যা তোমাকে প্রবলেম সল্ভিং এর সময় দ্রুত ও নির্ভুল ভাবে ইমপ্লিমেন্টেশন করতে সাহায্য করবে।
এখানে ভেক্টরের কিছু বহুল ব্যবহৃত ফাংশনের কাজ দেখাচ্ছি।
নোটঃ আমি long long এর স্থলে ll ব্যাবহার করেছি।
1D Vector:
মনে কর একটা v নামের কোন ভেক্টরে তুমি ৫টা সংখ্যা রাখতে চাও (যেকোন নামই হতে পারে)। সেটা করার নরমাল উপায় হচ্ছে এমনঃ

vector<ll> v(5); //v={0,0,0,0,0} for(i=0;i<5;i++) cin>>v[i];
গুরুত্বপূর্ন একটা ব্যাপার হচ্ছে, কোন নির্দিষ্ট সাইজের ভেক্টর ডিক্লেয়ার করলে তার সমস্ত ভ্যালু প্রথমে শূন্য দিয়ে ইনিশিয়ালাইজ করা থাকে। চাইলে তুমি শূন্যের বদলে অন্য কোন ভ্যালু দিয়েও ভেক্টরকে ইনিশিয়ালাইজ করতে পার। নিচের মত করলে ৫ সাইজের একটা v ভেক্টরের সমস্ত ভ্যালু -১ দ্বারা ইনিশিয়ালাইজ হবে।
vector<ll> v(5,-1); //v={-1,-1,-1,-1,-1}
আবার চাইলে তুমি এভাবে ভেক্টরের সাইজ ডিক্লেয়ার না করেও ভেক্টরে সংখ্যা গুলো নিতে পার। মনে কর তুমি একটা বিরাট খালি বালতি নিয়েছ। আর .push_back() ফাংশন এর মাধ্যমে একটা একটা করে সংখ্যা নিয়ে নিয়ে বালতিতে জমা করছ। মেমরিতে যতক্ষন ধরে ততক্ষন তুমি সংখ্যা নিতে পারবা, সমস্যা নাই।
vector<ll> v; //v={} for(i=0;i<n;i++) { ll p; cin>>p; v.push_back(p); }
প্রশ্ন করতে পার যে, এভাবে নেয়ার প্রয়োজন কি। অনেক সময় আমরা জানিনা আমাদের কতগুলো সংখ্যা নিতে হবে। সেক্ষেত্রে বড় সাইজের অ্যারে ডিক্লেয়ার করার চেয়ে ডায়নামিকালি ভেক্টর দিয়ে ইনপুট নেয়াই শ্রেয়। তখন মেমোরিও কম লাগবে, ঝামেলাও কম হবে। আর কোন ভেক্টরে এই মুহুর্তে কতগুলো ইলিমেন্ট আছে বের করার জন্য .size() ফাংশনটি ব্যাবহার করা যায়। যেমনঃ
ll s=v.size(); //v.size() will return the size of vector v.
চাইলে কোন ভেক্টরকে অন্য ভেক্টরে কপিও করে ফেলতে পার এভাবে।
vector<ll> a(n); for(i=0;i<n;i++) cin>>a[i]; vector<ll> b; b=a;
আবার চাইলে ভেক্টরকে রিভার্সও করে ফেলতে পার।
reverse(v.begin(),v.end());
.push_back() এর মত .pop_back() ফাংশন ব্যাবহার করে ভেক্টরে শেষের ভ্যালুটা মুছে ফেলা যায়। আর যদি চাও ভেক্টরকে ইনক্রিজিং অর্ডারে সর্ট করতে তবে এভাবে করতে পার।
sort(v.begin(),v.end());
আর যদি চাও ভেক্টরের প্রথম ভ্যালুটা জানতে তবে ব্যাবহার করতে পার .front() আবার একদম শেষের ভ্যালুটা জানতে ব্যাবহার করতে পার .back() ফাংশন।
এছাড়া,
.insert() ফাংশন দিয়ে কোন নির্দিষ্ট পজিশনে সংখ্যা ইনসার্ট করা যায়।
.clear() ফাংশন দিয়ে পুরো ভেক্টর ক্লিয়ার করে খালি করে ফেলা যায়।
.erase() ফাংশন দিয়ে কোন নির্দিষ্ট পজিশন থেকে নির্দিষ্ট পজিশন পর্যন্ত ইলিমেন্ট মুছে ফেলা যায়।

2D Vector:
উল্লেখ্য যে, চাইলে মাল্টি ডাইমেনশনাল ভেক্টরও ব্যাবহার করা যায়। যেমন, ৫০*৫০ সাইজের 2D ভেক্টর ডিক্লেয়ার করে ফেলতে পার এভাবে।
vector<vector<ll>> v(50,vector<ll> (50));
1D এর মতই সব ভ্যালু প্রথমে শূন্য থাকবে। নির্দিষ্ট ভ্যালু (যেমনঃ -১) দিয়ে ভেক্টরকে ইনিশিয়ালাইজ করতে পারো এভাবেঃ
vector<vector<ll>> v(50,vector<ll> (50,-1));
কিন্তু মনে কর তোমার রো এর সংখ্যা নির্দিষ্ট (যেমনঃ ৩) কিন্তু প্রতি কলামে আগে থেকে ফিক্সড না করে যত খুশি সংখ্যা নিতে চাও। তখন এভাবে ভেক্টর এভাবে ডিক্লেয়ার করতে পার।
vector<vector<ll>> v(3);
বা এভাবেও করা যায়ঃ
vector<ll> v[3];
এখন তুমি প্রথম কলামে ১,২ দ্বিতীয় কলামে ৩,৪,৫ এবং তৃতীয় কলামে ৬ রাখতে চাও। সেটা এভাবে করা যায়ঃ
v[0].push_back(1); v[0].push_back(2); v[1].push_back(3); v[1].push_back(4); v[1].push_back(5); v[2].push_back(6);
তখন আমাদের 2D ভেক্টরটার চেহারা হবে এমনঃ
v={{1,2},{3,4,5},{6}};
সবগুলো ভ্যালুকে ট্রাভার্স করা যাবে এভাবেঃ
for(i=0;i<v.size();i++) //v.size()==3 { for(j=0;j<v[i].size();j++) //v[0].size()==2, v[0].size()==3, v[0].size()==1 { cout<<v[i][j]<<" "; } cout<<endl; } // Output: // 1 2 // 3 4 5 // 6
এই 2D ভেক্টর জিনিষটা সবচেয়ে বেশি কাজে লাগবে গ্রাফের প্রবলেম সলভ করার সময়। মেমরি অপটিমাইজেশনের জন্য এটি অ্যারের চেয়ে বেশি প্রেফারড। কারন এখানে দরকার ছাড়া আমরা আগে থেকে কলামে যায়গা নিচ্ছিনা। প্রয়োজন মাফিক ১টা ১টা করে সংখ্যা নিচ্ছি। শুধু শুধু এক্সট্রা জায়গা অপচয়ের তো মানে নেই, তাইনা?
আরেকটা জিনিষ, মনে কর তুমি কোন একটা ভেক্টর আরেকটা ফাংশনের প্যারামিটারে আর্গুমেন্ট হিসেবে পাঠাতে চাচ্ছ। সেটা করতে পার এভাবেঃ
#include<bits/stdc++.h> using namespace std; #define ll long long ll fun(vector<ll> v) //রেফারেন্স পাঠাতে চাইলে এভাবে দিবাঃ ll fun(vector<ll> &v) { return v[0]+v[1]; } int main() { vector<ll> v(2); v[0]=1,v[1]=2; ll sum=fun(v); cout<<sum<<endl; }
এতটুকুই থাক। প্রবলেম সলভিং এর সময় বেসিকালি উপরে উল্লেখিত ফাংশন গুলোই বেশি ব্যবহৃত হয় ভেক্টরে। এছাড়া আরো বেশ কিছু ফাংশন আছে ভেক্টরে। জানতে হলে দেখতে পারো এখানেঃ
ধন্যবাদ। :)
This content was originally written by:

Mohammad Hafiz-Al-Masud,
Department of ICT (4th Batch),
Comilla University.

(20/08/2018)

Comments

Popular posts from this blog

Using SortedDictionary in C#

Modular Inverse in Bigmod