C++ তে কনটেইনার হলো এমন ডেটা স্ট্রাকচার যা ডেটা সংরক্ষণ এবং পরিচালনা করতে ব্যবহৃত হয়। C++ স্ট্যান্ডার্ড লাইব্রেরি (STL) কনটেইনারের মাধ্যমে প্রোগ্রামারদের জন্য বিভিন্ন ডেটা স্ট্রাকচার উপলব্ধ করা হয়, যেমন অ্যারে, লিস্ট, সেট, ম্যাপ, এবং অন্যান্য ডেটা স্ট্রাকচার যা অ্যালগরিদম এবং ইটরেটর দ্বারা পরিচালিত হয়।
C++ এ কনটেইনারগুলোকে মূলত তিনটি শ্রেণিতে ভাগ করা হয়:
- সিকোয়েন্স কনটেইনার (Sequence Containers)
- অ্যাসোসিয়েটিভ কনটেইনার (Associative Containers)
- আনঅর্ডারড কনটেইনার (Unordered Containers)
১. সিকোয়েন্স কনটেইনার (Sequence Containers)
এই কনটেইনারগুলো ডেটা উপাদানগুলোকে সিকোয়েন্স আকারে সংরক্ষণ করে, অর্থাৎ ডেটাগুলো একটি নির্দিষ্ট অর্ডারে থাকে। সিকোয়েন্স কনটেইনারগুলোর মধ্যে রয়েছে:
- std::vector
এটি একটি ডাইনামিক অ্যারে, যা ডেটা ম্যানিপুলেশনের জন্য সবচেয়ে বেশি ব্যবহৃত হয়। এটি প্রোগ্রামারকে অ্যারে আকারের পরিবর্তন করার সুবিধা দেয়।
উদাহরণ:
#include <iostream>
#include <vector>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
// ভেক্টরের মধ্যে নতুন উপাদান যোগ করা
vec.push_back(6);
// ভেক্টরের উপাদানগুলো প্রদর্শন
for (int val : vec) {
std::cout << val << " ";
}
return 0;
}- std::list
এটি একটি ডাবল লিংকড লিস্ট, যা দ্রুত উপাদান যোগ বা অপসারণের জন্য ব্যবহৃত হয়। তবে, এটি অ্যাক্সেস করতে একটু ধীরগতির হতে পারে।
উদাহরণ:
#include <iostream>
#include <list>
int main() {
std::list<int> lst = {1, 2, 3, 4, 5};
// লিস্টে নতুন উপাদান যোগ করা
lst.push_back(6);
// লিস্টের উপাদানগুলো প্রদর্শন
for (int val : lst) {
std::cout << val << " ";
}
return 0;
}- std::deque
এটি একটি ডবল-এন্ডেড কিউ (double-ended queue), যার মাধ্যমে উভয় প্রান্ত থেকে উপাদান যোগ এবং অপসারণ করা যায়।
উদাহরণ:
#include <iostream>
#include <deque>
int main() {
std::deque<int> dq = {1, 2, 3, 4, 5};
// ডিকিউ এর প্রথমে নতুন উপাদান যোগ করা
dq.push_front(0);
// ডিকিউ এর শেষে নতুন উপাদান যোগ করা
dq.push_back(6);
// ডিকিউ এর উপাদানগুলো প্রদর্শন
for (int val : dq) {
std::cout << val << " ";
}
return 0;
}২. অ্যাসোসিয়েটিভ কনটেইনার (Associative Containers)
এই কনটেইনারগুলো কী-ভ্যালু জোড়া হিসেবে ডেটা সংরক্ষণ করে এবং ডেটার অ্যাক্সেস খুব দ্রুত হয়, কারণ এগুলি সাধারণত একটি সাজানো অর্ডারে থাকে।
- std::set
এটি একটি অ্যাসোসিয়েটিভ কনটেইনার, যা ইউনিক উপাদান সংরক্ষণ করে এবং তা সাজানো থাকে। set ডুপ্লিকেট মান গ্রহণ করে না।
উদাহরণ:
#include <iostream>
#include <set>
int main() {
std::set<int> s = {1, 2, 3, 4, 5};
// নতুন উপাদান যোগ করা
s.insert(6);
// সেটের উপাদানগুলো প্রদর্শন
for (int val : s) {
std::cout << val << " ";
}
return 0;
}- std::map
এটি কী-ভ্যালু জোড়া আকারে ডেটা সংরক্ষণ করে এবং প্রতিটি কী ইউনিক থাকে। map একটি সাজানো স্ট্রাকচার থাকে।
উদাহরণ:
#include <iostream>
#include <map>
int main() {
std::map<int, std::string> m;
// কী-ভ্যালু জোড়া ইনসার্ট করা
m[1] = "One";
m[2] = "Two";
m[3] = "Three";
// ম্যাপের উপাদানগুলো প্রদর্শন
for (auto &pair : m) {
std::cout << pair.first << ": " << pair.second << std::endl;
}
return 0;
}- std::multiset এবং std::multimap
এগুলো set এবং map এর মতো, তবে এখানে একাধিক ডুপ্লিকেট মান গ্রহণ করতে পারে।
৩. আনঅর্ডারড কনটেইনার (Unordered Containers)
এই কনটেইনারগুলো হ্যাশ টেবিলের মাধ্যমে কাজ করে, এবং এগুলো সাধারণত দ্রুত অ্যাক্সেস প্রদান করে। এগুলোতে উপাদানগুলি সাজানো থাকে না।
- std::unordered_set
এটি set এর মতো, তবে উপাদানগুলো সাজানো থাকে না। এটি হ্যাশ টেবিল ব্যবহার করে, ফলে দ্রুত অ্যাক্সেস পাওয়া যায়।
উদাহরণ:
#include <iostream>
#include <unordered_set>
int main() {
std::unordered_set<int> us = {1, 2, 3, 4, 5};
// নতুন উপাদান যোগ করা
us.insert(6);
// unordered_set এর উপাদানগুলো প্রদর্শন
for (int val : us) {
std::cout << val << " ";
}
return 0;
}- std::unordered_map
এটি map এর মতো, তবে এটি হ্যাশ টেবিল ব্যবহার করে। এর ফলে, এটির ডেটা অ্যাক্সেস দ্রুত হয়, তবে উপাদানগুলো সাজানো থাকে না।
উদাহরণ:
#include <iostream>
#include <unordered_map>
int main() {
std::unordered_map<int, std::string> um;
// কী-ভ্যালু জোড়া ইনসার্ট করা
um[1] = "One";
um[2] = "Two";
um[3] = "Three";
// unordered_map এর উপাদানগুলো প্রদর্শন
for (auto &pair : um) {
std::cout << pair.first << ": " << pair.second << std::endl;
}
return 0;
}৪. Stack এবং Queue
সি++ এ স্ট্যাক এবং কিউ কনটেইনারের জন্য বিশেষভাবে প্রস্তুত std::stack এবং std::queue কনটেইনার রয়েছে, যা প্রায়ই লিনিয়ার স্ট্রাকচারের জন্য ব্যবহৃত হয়।
- std::stack
এটি একটি স্ট্যাক কনটেইনার, যা LIFO (Last In First Out) প্রিন্সিপাল অনুসরণ করে।
- std::queue
এটি একটি কিউ কনটেইনার, যা FIFO (First In First Out) প্রিন্সিপাল অনুসরণ করে।
উপসংহার
C++ তে কনটেইনারগুলো ডেটা সংরক্ষণ এবং পরিচালনা করার জন্য গুরুত্বপূর্ণ টুলস সরবরাহ করে। সিকোয়েন্স কনটেইনার (যেমন vector, list, deque) ডেটা সংরক্ষণ করে সিকোয়েন্স আকারে, অ্যাসোসিয়েটিভ কনটেইনার (যেমন set, map) ডেটাকে কী-ভ্যালু জোড়ায় সংরক্ষণ করে, এবং আনঅর্ডারড কনটেইনারগুলো (যেমন unordered_set, unordered_map) দ্রুত অ্যাক্সেস নিশ্চিত করে। C++ এর STL কনটেইনারগুলো প্রোগ্রামারদের জন্য খুবই শক্তিশালী এবং কার্যকরী।
সি++ স্ট্যান্ডার্ড লাইব্রেরির Sequence Containers হলো এমন কিছু কনটেইনার, যা ডেটা সিকোয়েন্স আকারে সংরক্ষণ করে। এর মধ্যে std::vector, std::deque, এবং std::list হলো সবচেয়ে ব্যবহৃত ও জনপ্রিয় সিকোয়েন্স কনটেইনার। প্রতিটি কনটেইনারের নিজস্ব বৈশিষ্ট্য ও ব্যবহার আছে, যা নির্দিষ্ট পরিস্থিতিতে ব্যবহার করা সুবিধাজনক। নিচে এই কনটেইনারগুলো নিয়ে বিস্তারিত আলোচনা করা হলো:
১. std::vector
std::vector হলো ডাইনামিক অ্যারে যা প্রয়োজন অনুযায়ী আকার পরিবর্তন করতে সক্ষম। এটি সাধারণ অ্যারের মতোই কাজ করে, তবে এর আকার ডায়নামিকালি বাড়ানো বা ছোট করা যায়। std::vector সাধারণত যখন এলিমেন্টগুলো লিনিয়ার অ্যাক্সেস প্রয়োজন এবং অ্যারের আকার পরিবর্তনযোগ্য হতে হবে তখন ব্যবহৃত হয়।
বৈশিষ্ট্য:
- এলিমেন্টগুলো ধারাবাহিকভাবে (contiguous memory) সংরক্ষিত থাকে।
- এলিমেন্ট অ্যাক্সেস করার জন্য
O(1)সময় লাগে, যা খুবই দ্রুত। - শেষ প্রান্তে এলিমেন্ট যোগ বা মুছে ফেলা
O(1)সময়ে সম্ভব।
উদাহরণ:
#include <iostream>
#include <vector>
int main() {
std::vector<int> vec = {1, 2, 3, 4};
vec.push_back(5); // নতুন এলিমেন্ট যোগ করা
vec.pop_back(); // শেষ এলিমেন্ট মুছে ফেলা
// ভেক্টরের সব এলিমেন্ট প্রদর্শন
for (int val : vec) {
std::cout << val << " ";
}
return 0;
}কখন ব্যবহার করবেন:
- যখন এলিমেন্টগুলো ধারাবাহিক মেমোরিতে সংরক্ষণ করতে চান।
- যখন কনটেইনারের শেষ প্রান্তে এলিমেন্ট যোগ বা মুছে ফেলতে হবে।
- যখন এলিমেন্টগুলোতে এলোমেলোভাবে (random access) অ্যাক্সেস প্রয়োজন।
২. std::deque
std::deque বা "Double Ended Queue" হলো এমন একটি কনটেইনার যা উভয় প্রান্তে এলিমেন্ট যোগ ও মুছে ফেলার সুবিধা দেয়। এটি অ্যারের মতোই কাজ করে, তবে প্রয়োজন অনুযায়ী উভয় প্রান্তে ডাটা সংরক্ষণ করতে পারে।
বৈশিষ্ট্য:
- এলিমেন্ট যোগ বা মুছে ফেলা উভয় প্রান্ত থেকে করা যায়।
- এলিমেন্ট অ্যাক্সেসের সময় সাধারণত
O(1)লাগে। std::dequeডায়নামিক মেমরি ব্যবহার করে, তাই প্রয়োজনমতো আকার বাড়ানো বা কমানো যায়।
উদাহরণ:
#include <iostream>
#include <deque>
int main() {
std::deque<int> deq = {1, 2, 3};
deq.push_front(0); // সামনে নতুন এলিমেন্ট যোগ করা
deq.push_back(4); // শেষে নতুন এলিমেন্ট যোগ করা
// ডেক-এর সব এলিমেন্ট প্রদর্শন
for (int val : deq) {
std::cout << val << " ";
}
return 0;
}কখন ব্যবহার করবেন:
- যখন উভয় প্রান্ত থেকে ডেটা অ্যাক্সেস বা সংশোধনের প্রয়োজন।
- যখন এলিমেন্টগুলোতে এলোমেলোভাবে অ্যাক্সেস প্রয়োজন।
- যখন শেষ এবং শুরু থেকে দ্রুত অ্যাক্সেস দরকার, তবে মধ্যবর্তী স্থান থেকে অ্যাক্সেসের প্রয়োজন নেই।
৩. std::list
std::list হলো ডাবল লিংকড লিস্ট, যেখানে প্রতিটি নোড আগের এবং পরের নোডের সাথে লিঙ্ক থাকে। এটি সিকোয়েন্সের মাঝখানে দ্রুত ডেটা যোগ বা মুছে ফেলার জন্য অত্যন্ত কার্যকর।
বৈশিষ্ট্য:
- ডাবল লিংকড লিস্ট হিসেবে কাজ করে।
- মাঝখানে ডেটা যোগ বা মুছে ফেলা
O(1)সময়ে সম্ভব, যদি ইটরেটর দিয়ে নির্দিষ্ট অবস্থানে পৌঁছানো যায়। - এলিমেন্টগুলো ধারাবাহিক মেমোরিতে থাকে না, তাই এলোমেলো অ্যাক্সেস
O(n)সময়ে হয়।
উদাহরণ:
#include <iostream>
#include <list>
int main() {
std::list<int> lst = {1, 2, 3, 4};
lst.push_front(0); // সামনে নতুন এলিমেন্ট যোগ করা
lst.push_back(5); // শেষে নতুন এলিমেন্ট যোগ করা
lst.pop_front(); // সামনে থেকে এলিমেন্ট মুছে ফেলা
// লিস্টের সব এলিমেন্ট প্রদর্শন
for (int val : lst) {
std::cout << val << " ";
}
return 0;
}কখন ব্যবহার করবেন:
- যখন মাঝখানে এলিমেন্ট দ্রুত যোগ বা মুছে ফেলার প্রয়োজন।
- যখন কনটেইনারের আকার পরিবর্তন করতে হবে।
- যখন এলোমেলো অ্যাক্সেসের প্রয়োজন নেই এবং শুধুমাত্র ধারাবাহিকভাবে ডেটা অ্যাক্সেস করতে হবে।
সংক্ষেপে তুলনা
| বৈশিষ্ট্য | std::vector | std::deque | std::list |
|---|---|---|---|
| মেমরি অ্যারেঞ্জমেন্ট | ধারাবাহিক (contiguous) মেমরি | ডায়নামিক, ধারাবাহিক নয় | ডাবল লিংকড লিস্ট |
| এলোমেলো অ্যাক্সেস | O(1) (দ্রুত) | O(1) (দ্রুত) | O(n) (ধীর) |
| প্রান্তে অপারেশন | শেষ প্রান্তে দ্রুত | উভয় প্রান্তে দ্রুত | উভয় প্রান্তে দ্রুত |
| মাঝখানে অপারেশন | ধীর | ধীর | দ্রুত (O(1) ইটরেটরের সাথে) |
এই তিনটি সিকোয়েন্স কনটেইনার প্রতিটি নির্দিষ্ট ব্যবহারের জন্য উপযোগী। std::vector সাধারণত যখন এলোমেলো অ্যাক্সেস দরকার হয় তখন ব্যবহার করা হয়, std::deque যখন উভয় প্রান্ত থেকে অ্যাক্সেস বা পরিবর্তনের প্রয়োজন হয়, এবং std::list যখন মাঝখানে দ্রুত ডেটা পরিবর্তনের প্রয়োজন হয়।
C++ এর স্ট্যান্ডার্ড লাইব্রেরি বিভিন্ন Associative Containers সরবরাহ করে যা ডেটাকে একটি নির্দিষ্ট অর্ডারে বা নির্দিষ্ট কীগুলির সাথে যুক্ত করে সংরক্ষণ করে। এই কনটেইনারগুলোতে ডেটা অনুসন্ধান এবং সংশোধন দ্রুত হয় কারণ এগুলো সাধারণত সঞ্চিত ডেটাকে স্বয়ংক্রিয়ভাবে সাজানো রাখে (সাধারণত একটি বৈদ্যুতিন সার্চ ট্রি বা লাল-কালো ট্রি দ্বারা)।
নিচে C++ এর কিছু সাধারণ Associative Containers: std::set, std::map, std::multiset, এবং std::multimap এর ব্যবহার এবং পার্থক্য আলোচনা করা হয়েছে:
১. std::set
std::set একটি কনটেইনার যা ইউনিক (অদ্বিতীয়) উপাদানসমূহ সংরক্ষণ করে এবং এগুলো স্বয়ংক্রিয়ভাবে সাজানো থাকে। এটি সিএট (Tree) ডেটা স্ট্রাকচার ব্যবহার করে, তাই ডেটা খুব দ্রুত খুঁজে পাওয়া যায় এবং সন্নিবেশ করা যায়।
- পার্থক্য: কোন মানের ডুপ্লিকেট অনুমতি দেয় না।
- গঠন: কীগুলোর উপর ভিত্তি করে সাজানো থাকে।
উদাহরণ (std::set):
#include <iostream>
#include <set>
int main() {
std::set<int> numbers;
// সেটে উপাদান যোগ করা
numbers.insert(5);
numbers.insert(2);
numbers.insert(8);
numbers.insert(3);
numbers.insert(5); // ডুপ্লিকেট, তাই যোগ হবে না
// সেটের উপাদান প্রিন্ট করা
for (int num : numbers) {
std::cout << num << " ";
}
return 0;
}আউটপুট:
2 3 5 8এখানে, 5 ডুপ্লিকেট হওয়ায় সেটে একবারই থাকবে, এবং উপাদানগুলো সাজানো অবস্থায় থাকবে।
২. std::map
std::map একটি অ্যাসোসিয়েটিভ কনটেইনার যা কী-ভ্যালু জোড়া সংরক্ষণ করে। এখানে প্রতিটি কী অবশ্যই ইউনিক হতে হবে, এবং কী-এর উপর ভিত্তি করে মান (ভ্যালু) সংরক্ষিত হয়। এটি সাধারণত সাজানো থাকে এবং দ্রুত অনুসন্ধান (log(n) সময়) সমর্থন করে।
- পার্থক্য: প্রতিটি কীয়ের জন্য একটি মান সংযুক্ত থাকে, কীগুলো অবশ্যই ইউনিক (অদ্বিতীয়)।
- গঠন: কী এর মাধ্যমে ভ্যালু সংরক্ষণ করা হয় এবং কীগুলোর উপর ভিত্তি করে সাজানো থাকে।
উদাহরণ (std::map):
#include <iostream>
#include <map>
int main() {
std::map<std::string, int> ages;
// মান যোগ করা
ages["John"] = 25;
ages["Alice"] = 30;
ages["Bob"] = 22;
// মান অ্যাক্সেস করা
std::cout << "Alice's age: " << ages["Alice"] << std::endl;
// কী-ভ্যালু জোড়া প্রিন্ট করা
for (const auto& pair : ages) {
std::cout << pair.first << ": " << pair.second << std::endl;
}
return 0;
}আউটপুট:
Alice's age: 30
Alice: 30
Bob: 22
John: 25এখানে, std::map কীগুলোর উপর ভিত্তি করে সাজানো হয়েছে এবং প্রতিটি কী একটি মানের সাথে সংযুক্ত।
৩. std::multiset
std::multiset হল একটি অ্যাসোসিয়েটিভ কনটেইনার যা অদ্বিতীয় নয় এমন উপাদান সংরক্ষণ করতে দেয়। এটি ডুপ্লিকেট মান অনুমোদন করে এবং উপাদানগুলো স্বয়ংক্রিয়ভাবে সাজানো থাকে। std::set এর মতোই, তবে এতে ডুপ্লিকেট উপাদান থাকতে পারে।
- পার্থক্য: ডুপ্লিকেট উপাদানসমূহ অনুমোদন করে, তবে উপাদানগুলো সাজানো থাকে।
- গঠন: কীগুলোর উপর ভিত্তি করে সাজানো থাকে এবং মানের ডুপ্লিকেট থাকতে পারে।
উদাহরণ (std::multiset):
#include <iostream>
#include <set>
int main() {
std::multiset<int> numbers;
// সেটে উপাদান যোগ করা
numbers.insert(5);
numbers.insert(2);
numbers.insert(5);
numbers.insert(8);
numbers.insert(3);
// সেটের উপাদান প্রিন্ট করা
for (int num : numbers) {
std::cout << num << " ";
}
return 0;
}আউটপুট:
2 3 5 5 8এখানে, 5 দুটি বার ইনসার্ট হওয়ার পরেও সেটে দুইবার উপস্থিত রয়েছে, কারণ std::multiset ডুপ্লিকেট মান গ্রহণ করে।
৪. std::multimap
std::multimap হল একটি অ্যাসোসিয়েটিভ কনটেইনার যা কী-ভ্যালু জোড়া সংরক্ষণ করে, এবং এটি ডুপ্লিকেট কী অনুমোদন করে। এটি মূলত std::map এর মতো, তবে এতে একই কী এর জন্য একাধিক মান থাকতে পারে।
- পার্থক্য: একই কী এর জন্য একাধিক মান থাকতে পারে।
- গঠন: কী-ভ্যালু জোড়া সাজানো থাকে এবং কী এর জন্য একাধিক মান থাকতে পারে।
উদাহরণ (std::multimap):
#include <iostream>
#include <map>
int main() {
std::multimap<std::string, int> grades;
// মান যোগ করা
grades.insert({"John", 85});
grades.insert({"Alice", 90});
grades.insert({"John", 88});
grades.insert({"Bob", 92});
grades.insert({"Alice", 95});
// কী-ভ্যালু জোড়া প্রিন্ট করা
for (const auto& pair : grades) {
std::cout << pair.first << ": " << pair.second << std::endl;
}
return 0;
}আউটপুট:
Alice: 90
Alice: 95
Bob: 92
John: 85
John: 88এখানে, John এবং Alice এর জন্য একাধিক গ্রেড রয়েছে, কারণ std::multimap ডুপ্লিকেট কী অনুমোদন করে।
পার্থক্য সারণী
| Container | Key | Duplicates | Order |
|---|---|---|---|
std::set | Single | No | Sorted (ascending by default) |
std::map | Single | No | Sorted by key |
std::multiset | Single | Yes | Sorted (ascending by default) |
std::multimap | Single | Yes | Sorted by key |
উপসংহার
std::set: ইউনিক উপাদান সংরক্ষণ করে এবং উপাদানগুলো সাজানো থাকে।std::map: ইউনিক কী-ভ্যালু জোড়া সংরক্ষণ করে, এবং কীগুলোর উপর ভিত্তি করে সাজানো থাকে।std::multiset: ডুপ্লিকেট উপাদান অনুমোদন করে এবং উপাদানগুলো সাজানো থাকে।std::multimap: ডুপ্লিকেট কী অনুমোদন করে এবং কীগুলোর উপর ভিত্তি করে সাজানো থাকে।
এই কনটেইনারগুলো বিভিন্ন ক্ষেত্রে ব্যবহার করা যায় যেখানে ডেটা সঞ্চয় ও অনুসন্ধানের প্রয়োজন এবং ডেটাকে সাজানো রাখতে হবে।
C++-এ std::unordered_set এবং std::unordered_map হলো স্ট্যান্ডার্ড লাইব্রেরির দুটি অর্ডারহীন কনটেইনার যা হ্যাশ টেবিল ব্যবহার করে কাজ করে। এগুলি সাধারণত std::set এবং std::map এর বিকল্প, তবে তারা উপাদানগুলিকে কোনো নির্দিষ্ট অর্ডারে রাখে না এবং খোঁজার গতি দ্রুত হয়, বিশেষত বড় ডেটাসেটের জন্য।
১. std::unordered_set
std::unordered_set একটি কনটেইনার যা একক মান সংরক্ষণ করে এবং এই মানগুলোকে অর্ডারহীনভাবে (unordered) রাখে। এটি হ্যাশ টেবিল ব্যবহার করে, যার ফলে অনুসন্ধান (search), যোগ (insert), এবং অপসারণ (erase) অপারেশনগুলি গড়ে O(1) সময়ে সম্পন্ন হয়, যদি হ্যাশ ফাংশন ভালভাবে কাজ করে।
বৈশিষ্ট্য:
- দ্বৈত উপাদান নিষিদ্ধ: সেটে একাধিক একি উপাদান থাকতে পারে না (যেমন,
std::setএর মতো)। - অর্ডারহীন: উপাদানগুলো একটি নির্দিষ্ট অর্ডারে রাখা হয় না।
- দ্রুত খোঁজা: উপাদান খোঁজা দ্রুত হয়, বিশেষ করে বড় ডেটাসেটের জন্য।
উদাহরণ:
#include <iostream>
#include <unordered_set>
int main() {
// unordered_set তৈরি করা
std::unordered_set<int> mySet = {10, 20, 30, 40};
// উপাদান যোগ করা
mySet.insert(50);
mySet.insert(60);
// উপাদান চেক করা
if (mySet.find(30) != mySet.end()) {
std::cout << "30 is found in the set" << std::endl;
}
// উপাদান প্রিন্ট করা
std::cout << "Elements in unordered_set: ";
for (const int& num : mySet) {
std::cout << num << " ";
}
return 0;
}আউটপুট (অর্ডার পরিবর্তিত হতে পারে):
30 is found in the set
Elements in unordered_set: 10 20 30 40 50 60২. std::unordered_map
std::unordered_map একটি কনটেইনার যা কী-ভ্যালু জোড়া (key-value pairs) সংরক্ষণ করে এবং এই জোড়াগুলোকে অর্ডারহীনভাবে (unordered) রাখে। এটি একটি হ্যাশ টেবিলের মত কাজ করে এবং গড় O(1) সময়ে কী-ভ্যালু পেয়ারগুলো অ্যাক্সেস করা সম্ভব হয়।
বৈশিষ্ট্য:
- কী-ভ্যালু জোড়া:
std::unordered_mapকনটেইনারটি প্রতিটি উপাদানে একটি কী এবং সেই কী সম্পর্কিত একটি ভ্যালু সংরক্ষণ করে। - অর্ডারহীন: উপাদানগুলো একটি নির্দিষ্ট অর্ডারে রাখা হয় না।
- দ্রুত অনুসন্ধান: কী দিয়ে ভ্যালু খোঁজার গতি দ্রুত।
উদাহরণ:
#include <iostream>
#include <unordered_map>
int main() {
// unordered_map তৈরি করা
std::unordered_map<std::string, int> myMap;
// কী-ভ্যালু যোগ করা
myMap["apple"] = 3;
myMap["banana"] = 5;
myMap["orange"] = 2;
// ভ্যালু খোঁজা
std::cout << "apple count: " << myMap["apple"] << std::endl;
// কী-ভ্যালু জোড়া প্রিন্ট করা
std::cout << "Elements in unordered_map:" << std::endl;
for (const auto& pair : myMap) {
std::cout << pair.first << ": " << pair.second << std::endl;
}
return 0;
}আউটপুট (অর্ডার পরিবর্তিত হতে পারে):
apple count: 3
Elements in unordered_map:
banana: 5
apple: 3
orange: 2std::unordered_set এবং std::unordered_map এর মধ্যে পার্থক্য
| বৈশিষ্ট্য | std::unordered_set | std::unordered_map |
|---|---|---|
| ডেটা স্ট্রাকচার | একক উপাদান (unique elements) | কী-ভ্যালু জোড়া (key-value pairs) |
| কী | উপাদান (ভ্যালু) | কী (key) এবং ভ্যালু (value) |
| অর্ডার | অর্ডারহীন (unordered) | অর্ডারহীন (unordered) |
| হ্যাশ টেবিল | হ্যাশ টেবিল ব্যবহার করে | হ্যাশ টেবিল ব্যবহার করে |
| গতি | গড় O(1) অনুসন্ধান (search), যোগ (insert) এবং অপসারণ (erase) | গড় O(1) অনুসন্ধান (search), যোগ (insert) এবং অপসারণ (erase) |
উপসংহার
std::unordered_set: এটি একটি কনটেইনার যা একক মান (unique values) সংরক্ষণ করে এবং অর্ডারহীনভাবে রাখে। এর ব্যবহার সাধারণত সেটের মধ্যে কোনো বিশেষ অর্ডার না রাখলেও খোঁজার গতি দ্রুত চাইলে হয়।std::unordered_map: এটি একটি কনটেইনার যা কী-ভ্যালু জোড়া সংরক্ষণ করে এবং এই জোড়াগুলোকে অর্ডারহীনভাবে রাখে।std::unordered_mapদ্রুতভাবে কী-ভ্যালু পেয়ার অ্যাক্সেস করতে সাহায্য করে।
এই কনটেইনারগুলো সাধারণত বড় ডেটাসেট এবং দ্রুত অনুসন্ধান ও যোগ/অপসারণ অপারেশন প্রয়োজন এমন পরিস্থিতিতে ব্যবহৃত হয়।
সি++ স্ট্যান্ডার্ড লাইব্রেরিতে কনটেইনার অ্যাডাপ্টার হিসেবে তিনটি গুরুত্বপূর্ণ ক্লাস রয়েছে: std::stack, std::queue, এবং std::priority_queue। এদেরকে কনটেইনার অ্যাডাপ্টার বলা হয় কারণ এরা মূল কনটেইনারের কার্যকারিতা (যেমন vector, deque, বা list) ব্যবহার করে নতুন ধরনের অ্যাক্সেস নিয়ম তৈরি করে। এই কনটেইনার অ্যাডাপ্টারগুলো ডেটা অ্যাক্সেস করার ভিন্ন ধরণ প্রদান করে, যা বিভিন্ন প্রোগ্রামিং সমস্যা সমাধানে সহায়ক।
১. std::stack
std::stack হলো একটি LIFO (Last In, First Out) ডেটা স্ট্রাকচার। এতে সর্বশেষ যোগ করা উপাদানটিই প্রথমে অপসারণ করা যায়। সাধারণত stack কনটেইনার push, pop, top ইত্যাদি অপারেশন সরবরাহ করে।
বৈশিষ্ট্য ও পদ্ধতি:
- push: স্ট্যাকে একটি নতুন উপাদান যোগ করে।
- pop: স্ট্যাকের শীর্ষ উপাদান সরিয়ে দেয়।
- top: স্ট্যাকের শীর্ষ উপাদানটি রেফারেন্স হিসেবে প্রদান করে।
- empty: চেক করে যে স্ট্যাকটি খালি কিনা।
- size: স্ট্যাকের বর্তমান উপাদানের সংখ্যা প্রদান করে।
উদাহরণ:
#include <iostream>
#include <stack>
int main() {
std::stack<int> stk;
stk.push(10);
stk.push(20);
stk.push(30);
while (!stk.empty()) {
std::cout << stk.top() << " "; // শীর্ষ উপাদান প্রদর্শন
stk.pop(); // শীর্ষ উপাদান সরিয়ে নেয়া
}
return 0;
}২. std::queue
std::queue হলো একটি FIFO (First In, First Out) ডেটা স্ট্রাকচার। এতে প্রথমে যোগ করা উপাদানটিই প্রথমে অপসারণ করা যায়। এটি সাধারণত push, pop, front, এবং back অপারেশন সরবরাহ করে।
বৈশিষ্ট্য ও পদ্ধতি:
- push: কিউয়ের শেষ প্রান্তে একটি নতুন উপাদান যোগ করে।
- pop: কিউয়ের সামনের উপাদান সরিয়ে দেয়।
- front: কিউয়ের প্রথম উপাদান রেফারেন্স হিসেবে প্রদান করে।
- back: কিউয়ের শেষ উপাদান রেফারেন্স হিসেবে প্রদান করে।
- empty: চেক করে যে কিউটি খালি কিনা।
- size: কিউয়ের বর্তমান উপাদানের সংখ্যা প্রদান করে।
উদাহরণ:
#include <iostream>
#include <queue>
int main() {
std::queue<int> q;
q.push(10);
q.push(20);
q.push(30);
while (!q.empty()) {
std::cout << q.front() << " "; // প্রথম উপাদান প্রদর্শন
q.pop(); // প্রথম উপাদান সরিয়ে নেয়া
}
return 0;
}৩. std::priority_queue
std::priority_queue হলো একটি বিশেষ ধরনের কিউ যেখানে উপাদানগুলোকে গুরুত্ব অনুযায়ী সাজানো হয়। সাধারণত সর্বোচ্চ (বা সর্বনিম্ন) মান সর্বপ্রথমে বের করা যায়। এটি ডিফল্টভাবে সর্বোচ্চ মানকে সর্বপ্রথমে প্রদর্শন করে। priority_queue সাধারণত push, pop, এবং top অপারেশন সরবরাহ করে।
বৈশিষ্ট্য ও পদ্ধতি:
- push: কিউয়ে একটি নতুন উপাদান যোগ করে এবং উপাদানগুলোকে সাজিয়ে রাখে।
- pop: সর্বোচ্চ (বা সর্বনিম্ন) মান সরিয়ে দেয়।
- top: সর্বোচ্চ (বা সর্বনিম্ন) মান রেফারেন্স হিসেবে প্রদান করে।
- empty: চেক করে যে কিউটি খালি কিনা।
- size: কিউয়ের বর্তমান উপাদানের সংখ্যা প্রদান করে।
উদাহরণ:
#include <iostream>
#include <queue>
int main() {
std::priority_queue<int> pq;
pq.push(10);
pq.push(30);
pq.push(20);
while (!pq.empty()) {
std::cout << pq.top() << " "; // সর্বোচ্চ মান প্রদর্শন
pq.pop(); // সর্বোচ্চ মান সরিয়ে নেয়া
}
return 0;
}নোট: উপরের উদাহরণে সর্বোচ্চ মান প্রথমে প্রিন্ট করা হয় কারণ std::priority_queue ডিফল্টভাবে সর্বোচ্চ মানকে অগ্রাধিকার দেয়। তবে std::greater<int> ব্যবহার করে এটি সর্বনিম্ন মানকে অগ্রাধিকার দিতেও কনফিগার করা যায়।
কনটেইনার অ্যাডাপ্টারের সুবিধাসমূহ
- ডেটা ব্যবস্থাপনার সরলতা:
stack,queue, এবংpriority_queueবিভিন্ন সমস্যা সমাধানের জন্য সরল এবং কার্যকরী উপায়ে ডেটা অ্যাক্সেস ও পরিচালনা করতে সহায়ক। - মেমরি ব্যবহারের দক্ষতা: এই অ্যাডাপ্টারগুলো অন্তর্নিহিত কনটেইনারের উপর ভিত্তি করে কাজ করে, যা মেমরি ব্যবহারের ক্ষেত্রে দক্ষ।
- স্বতন্ত্র কার্যকারিতা: প্রতিটি অ্যাডাপ্টার নির্দিষ্ট কাজের জন্য তৈরি, যেমন
stackLIFO অপারেশন,queueFIFO অপারেশন, এবংpriority_queueডেটা গুরুত্বপূর্ণতার ভিত্তিতে সাজানো রাখে।
এগুলো বিভিন্ন ধরনের ডেটা অ্যাক্সেস প্যাটার্ন বাস্তবায়নের জন্য খুবই সহায়ক, যা প্রোগ্রামিংয়ের বিভিন্ন ক্ষেত্রে অত্যন্ত কার্যকর।
Read more