অনেক সময় আমাদের অনেক বড় সাইজের অ্যারে প্রয়োজন হয়, কিন্তু বলে দেওয়া হয় না ঠিক কত সাইজের অ্যারে রানটাইমে লাগতে পারে। অথবা হয়তো একই প্রবলেমের বিভিন্ন কেসে বিভিন্ন সাইজের অ্যারে লাগে। এক্ষেত্রে আমরা যা করি গ্লোবাল স্পেসে ১০০০০০ সাইজের অ্যারে ডিক্লেয়ার করে দি।

আবার অনেকক্ষেত্রে বলে দেওয়া হয় যে, 2D অ্যারে লাগবে। Row, Column এর সর্বোচ্চ মান হতে পারে 100000, কিন্তু একইসাথে বলা থাকে যে সর্বমোট উপাদানের সংখ্যা কখনো 100000-এর চেয়ে বড় হবে না। যেমন, ৫০০০০ row-এর প্রতিটাতে ২ টা করে কলাম থাকতে পারে। আবার ২ টা রো-এর প্রতিটাতে ৫০০০০টা কলাম থাকতে পারে। এখন এইসব ক্ষেত্রে আমরা [100000][100000] সাইজের অ্যারে ডিক্লেয়ার করতে পারি না, কাজ করতে হয় ডাইনামিক মেমরি অ্যালোকেট করে। এই কাজ যথেষ্ট ঝামেলার। তার উপর প্রতিবার কাজ শেষে মেমরি ক্লিয়ার করে দিতে হয়।

এত ঝামেলা থেকে মুক্তি দেওয়া জন্যই সি++ নিয়ে এসেছে ভেক্টর! ভেক্টর এক ধরণের কন্টেইনার, এবং এর কাজ-কারবার মোটামুটিভাবে অ্যারের মতই।

প্রথমেই আমরা দেখে নি ভেক্টর কীভাবে ডিক্লেয়ার করে।

ভেক্টর ডিক্লারেশনের সিনট্যাক্স হলঃ vector <type> name;

অর্থাৎ, ধরি আমরা ভেক্টরের নাম দিব myVector.

আমরা integer  টাইপের ভেক্টর চাইলে লিখবো vector <int> myVector;

একইভাবে vector <char> myVector;

কিংবা vector <double> myVector;

এখন দেখবো আমরা কীভাবে আমাদের এই ভেক্টরটিতে ভ্যারিয়েবল রাখবো। 

ভেক্টর সংক্রান্ত জিনিসপত্র আছে <vector> হেডারফাইলে। তো আমরা প্রথমেই হেডারফাইলটা ইনক্লুড করে দিব, সাথে লাগবে std namespace.

#include <iostream>
#include <vector>
using namespace std;
int main() {
    vector <int> myVector;
    return 0;
}

এখন ধর আমরা এখানে একশ’ টা ভ্যারিয়েবল রাখতে চাই। ভেক্টরে আমরা অ্যারের মত সরাসরি myVector(i) = 1; লিখে কাজ করতে পারি না। এজন্য আমাদের ইউজ করতে হয় push_back().

কোড লিখেই দেখা যাক।

#include <iostream>
#include <vector>
using namespace std;
int main() {
    vector <int> myVector;
    int i;
    for (i=0; i<100; i++) {
        myVector.push_back(i);
    }
    return 0;
}

এই কোডটা যা করবে, তা হল i-এর মানগুলো ভেক্টরে পুশ করে দিবে। অর্থাৎ, ভেক্টরটি হবে নিচের মতঃ

0 1 2 3 4 5 6 … … … … … … 99

এখন আমরা যদি i-এর মান না রেখে ১০০ টা ইনপুট নিয়ে রাখতে চাইতাম, তাহলে আমাদেরকে আলাদা একটা ভ্যারিয়েবলে ইনপুটটা নিতে হত। এরপর সেটা ভেক্টরে পুশ করতে হত।

#include <iostream>
#include <vector>
using namespace std;
int main() {
    vector <int> myVector;
    int i, input;
    for (i=0; i<100; i++) {
        cin >> input;
        myVector.push_back(input);
    }
    return 0;
}

ভেক্টরের এই জিনিসটা খুবই কাজের। যখন চাই, তখন একটা ভ্যারিয়েবল এখানে পুশ করে দেওয়া যায়। আবার যদি চাই, সেটা খুব সহজেই বের করে দেওয়া যায়!

ভেক্টরে কয়টি উপাদান আছে, সেটা বের করা যায় খুব সহজেই

এজন্য আমাদেরকে ব্যবহার করতে হবে size()

#include <iostream>
#include <vector>
using namespace std;
int main() {
    vector <int> myVector;
    int i, input;
    for (i=0; i<100; i++) {
        cin >> input;
        myVector.push_back(input);
    }
    cout << myVector.size() << endl;
    return 0;
}

এই কোডটা রান করে দেখ। দেখবা আউটপুট আসবে ১০০। কারণ ভেক্টরটিতে ১০০ টা উপাদান আছে।

ভেক্টর থেকে একটা উপাদান সরিয়ে দেওয়ার জন্য যা করতে হবে

আমরা ভেক্টরটির শেষে একটি উপাদান পুশ করেছিলাম push_back() ব্যবহার করে। একইভাবে শেষ থেকে একটি উপাদান সরিয়ে নিব pop_back() এর সাহায্যে! যেমন আমরা যদি, আমাদের প্রথম ভেক্টরটি থেকে শেষ উপাদান (99) মুছে ফেলতে চাই, তাহলে আমরা লিখবোঃ

#include <iostream>
#include <vector>
using namespace std;
int main() {
    vector <int> myVector;
    int i;
    for (i=0; i<100; i++) {
        myVector.push_back(i);
    }
    myVector.pop_back();
    return 0;
}

এখন আমাদের ভেক্টরটির চূড়ান্ত চেহারা দাঁড়াবে এমনঃ

0 1 2 3 4 … … … … …96 97 98

আমরা চাইলে পুরো ভেক্টরটি মুছে দিতে পারি

এজন্য আমাদেরকে ইউজ করতে হবে clear()

#include <iostream>
#include <vector>
using namespace std;
int main() {
    vector <int> myVector;
    int i;
    for (i=0; i<100; i++) {
        myVector.push_back(i);
    }
    cout << "Before: " <<  myVector.size() << endl;
    myVector.clear();
    cout << "After: " << myVector.size() << endl ;
    return 0;
}

কোডটা রান করলে আউটপুট হবে নিচের মত। অর্থাৎ ক্লিয়ার করার আগে ভেক্টরটিতে ১০০ টা উপাদান ছিল। পরে একটিও নেই।
Snap 2015-06-05 at 15.27.54

হ্যা এতটাই সোজা! 😀

ভেক্টরের প্রতিটা উপাদান অ্যারের মতই ইউজ করা যায়।

যেমন আমরা যদি চাই ভেক্টরটিতে কয়টি জোড় সংখ্যা আছে, তাহলে নিচের কোড লিখলেই হয়ে যাবে।

#include <iostream>
#include <vector>
using namespace std;
int main() {
    vector <int> myVector;
    int i;
    for (i=0; i<100; i++) {
        myVector.push_back(i);
    }
    int even = 0;
    for (i=0; i<100; i++ ) {
        if (myVector[i] % 2 == 0) even++;
    }
    cout << "Number of evens: " << even << endl;
    return 0;
}

কিংবা যদি চাই জোড় সংখ্যাগুলোকে শূন্য করে দিতে, তাহলে লিখতে পারিঃ

#include <iostream>
#include <vector>
using namespace std;
int main() {
    vector <int> myVector;
    int i;
    for (i=0; i<100; i++) {
        myVector.push_back(i);
    }
    
    for (i=0; i<100; i++ ) {
        if (myVector[i] % 2 == 0) myVector[i] = 0;
    }
    
    return 0;
}

উপাদান পুশ করা ছাড়া বাকি সব কাজই এভাবে অ্যারের মতই করে ফেলা যায়।

খুব সহজেই একটা ভেক্টরের কপি তৈরি করে ফেলা যায়।

আমরা যদি একটা অ্যারের কপি করতে চাই, তাহলে বসে বসে প্রতিটা উপাদান দ্বিতীয় অ্যারেতে বসাতে হয়। কিন্তু ভেক্টরে একটা = অপারেটর দিয়েই কাজটা হয়ে যায়! আমরা লিখবোঃ

#include <iostream>
#include <vector>
using namespace std;
int main() {
    vector <int> myVector, clone;
    int i;
    for (i=0; i<100; i++) {
        myVector.push_back(i);
    }
    clone = myVector;

    return 0;
}

ব্যস, কাজ শেষ! ২ টা ভেক্টরেই এখন একই উপাদান আছে। বিশ্বাস না হলে প্রিন্ট করে দেখতে পার! 😉

মাল্টি ডাইমেনশনাল ভেক্টর

1D ভেক্টর নিয়ে অনেক কথা হল। এবার দেখা যাক মাল্টি ডাইমেনশনাল ভেক্টর নিয়ে। মাল্টি ডাইমেনশনাল ভেক্টর ডিক্লেয়ার করা যায় দু’ভাবেঃ

vector <int> myVector[1000];

এই ডিক্লারেশন দ্বারা বুঝায়, তুমি এমন একটা ভেক্টর ডিক্লেয়ার করছো, যার row আছে ১০০০ টা। আর এই ১০০০ টা row-তে তুমি যা খুশি পুশ করতে পারবা। অর্থাৎ কলামের সংখ্যা তোমার বলে দিতে হচ্ছে না। এবং একেক row-তে কলামের সংখ্যা একেক রকম হলেও কোনো সমস্যা নাই।

মজার ব্যাপার হল, তুমি যদি এখানে সেকেন্ড ব্র্যাকেট না দিয়ে প্যারানথেসিস (ফার্স্ট ব্র্যাকেট) দিতা, তাহলে এটার মানে হত যে, তুমি একটা 1000 উপাদান বিশিষ্ট 1D ভেক্টর ডিক্লেয়ার করছো।

vector <int> myVector(1000); // 1D Vector

vector <int> myVector[1000]; // 2D Vector

প্রায়ই অনেকে এই দুইটার মধ্যে মিলিয়ে ফেলে ঝামেলায় পড়ে। তাই শুরুতেই সাবধান থাকা ভাল!

ডিক্লারেশনের আরেকটা উপায় হল নিচের মতঃ

vector< vector< int > > v;

একই ভাবে 3D ভেক্টরের জন্যঃ vector< vector< vector< int > > > v;

এখানে দুইটা “>”-এর মধ্যে ইচ্ছে করেই স্পেস রেখেছি, সেফ থাকার জন্য। স্পেস না দিলে অনেক কম্পাইলার এখানে ভুল দেখায় এটাকে >> অপারেটর মনে করে!

মাল্টি ডাইমেনশনাল ভেক্টরগুলোর কাজও 1D-এর মতই। এগুলো নিয়ে কাজ করতে শিখবে তুমি নিজে কোড করতে করতে। এছাড়াও আরও বেশ কিছু ফাংশন আছে, যেগুলো খুব বেশি কাজে লাগে না। যেমনঃ

(১) myVector.empty()

এটা বুলিয়ান ভ্যালু রিটার্ন করে। যদি এম্পটি হয়, রিটার্ন করবে 1, না হলে ০।

(২) myVector.begin()

এটা ভেক্টরের শুরুর অ্যাড্রেস রিটার্ন করবে।

(৩) myVector.end()

এটা ভেক্টর কোথায় শেষ হয়, সেটা রিটার্ন করবে।

(৪) myVector.erase(myVector.begin() + 7)

এটা দিয়ে ৮ নাম্বার উপাদানটা মুছে দেওয়া যায়!

(৫) myVector.swap(secondVector)

এটা দিয়ে দুইটা ভেক্টরের উপাদান অদলবদল হয়ে যাবে।

আরও বেশ কিছু আছে। তবে সেগুলো সচরাচর কাজে আসে না। তাই এগুলো লিখে লেখাটা আর লম্বা করছি না। পরের পর্বে আমরা স্ট্রিং নিয়ে দেখবো। ততদিন পর্যন্ত বিদায়। 🙂

Muntasir Wahed

Muntasir Wahed

System Administrator at স্বশিক্ষা.com
Jack of all trades, master of none.
Muntasir Wahed
Muntasir Wahed