Hajmlarvao‘lchambilanishlashusullari: empty() – true qaytaradi, agar to‘plam bo‘sh bo‘lsa false, size() - to‘plamdagi elementlar sonini qaytaradi, max_size() – mumkin bo‘lgan elementlar sonini qaytaradi.
Modifikatorlari:clear() – konteynerni tozalaydi, insert() – element qo‘shish, erase() – elemeni o‘chirish, swap() – o‘rin almashtirish, emplace() – joydi elementni yaratish.
Qidirish usullari: set to‘plam bilan ishlaganda qidirish muhim xisoblanadigan aspekt bo‘lib hisoblanadi. Qidirishni samarali tashkil qilish uchun bir nechta o‘zning usullariga ega: count(key), find(key), equal_range(key), lower_bound(key), upper_bound(key)
Taqqoslash va birlashtirish amallari: set to‘plam uchun barcha taqqoslash amallari amal qiladi. ning ketma-ket konteynerlarga amal qilgan barcha amal o‘rinli.
[=] (operator=) operatorni elementlar to‘plamini olish uchun ishlatiladi. Masalan, other to‘plamning nusxasini yangi bir other_one to‘plamga nusxalash uchun ishlatiladi (other_one = other).
Semantik nusxalashni amalga oshirish usuli other to‘plamning nusxasini yangi bir other_one to‘plamga to‘liq nusxalash uchun ishlatiladi va other to‘plami o‘chirilmaydi, ammo uning holatini aniqlab bo‘lmaydi other_one = move(other).
va doir masalalr va dasturlarni keltiramiz.
masala. [10, 50] intervalda N ta ketma- ket sonlar tasofidiy berilgan. {10, 20, 30, 40, 50} berilan sonlardan joriy ketma-ketlikda nechtadan bor.
int main() {
default_random_engine rnd(time(0)); uniform_int_distribution g(10, 50); vector myVektor;
int n, k = 0;
cout << "n = "; cin >> n; for (int i = 0; i < n; i++) {
int d = g(rnd);
myVektor.push_back(d); cout << myVektor[i] << " ";
}
set mySet;
for (int i=1; i<=5; ++i) mySet.insert(i*10); cout << endl;
for (int i = 0; i < n; i++)
if (mySet.count(myVektor[i])) k++; cout << k << " ta element topildi." << endl;
system("pause"); return 0;
}
Oldinroq juda tez-tez elementlarni kiritish va o‘chirish algoritmlarni foydalanish kerak emas deb aytgan. Vektor va to‘plam bilan ishlash samaradorligini taqqoslaylik. To‘plam va vektorning massivlarini tasodifiy sonlar bilan to‘ldiradigan va belgilangan qiymatni qidiradigan dastur yarataylik.
3.3(b) – dastur. Vektor va to‘plam bilan ishlash samaradorligini taqqoslash.
// Created by MBBahodir #include "stdafx.h"
#include #include #include #include #include #include #include using namespace std;
int main() {
int n;
default_random_engine rnd(time(0)); uniform_int_distribution g(1, 10000); cout << "n = "; cin >> n;
const int k = 100; int a = n;
auto start = chrono::system_clock::now(); vector ar1;
while (a--) ar1.push_back(g(rnd));
auto result1 = find(ar1.begin(), ar1.end(), k); auto end = chrono::system_clock::now();
auto elapsed = end - start; cout << "vector => "
<< elapsed.count()
<< endl; a = n;
start = chrono::system_clock::now(); set ar2;
while (a--) ar2.insert(g(rnd)); auto result2 = ar2.find(k);
end = chrono::system_clock::now(); elapsed = end - start;
cout << "set => " << elapsed.count() << endl;
system("pause"); return 0;
}
3.3(b)-dastur. Output
n = 10000
vector => 289989
set => 1160000
To‘plamning ishlashi vektordan sezilarli darajada past bo‘ladi. Shuni yodda tutingki, to‘plamni to‘ldirish amali saralash bilan amalga oshiriladi va bu albatta, qimmatbaho amal. Lekin, faqat qidirish uchun, har ikki konteynerlarni ishlash solishtiradigan bo‘lsa, vaziyat foydasiga o‘zgaradi:
3.3(c)-dastur. Output
n = 10000
vector => 70042
set => 20044
Bundan qanday xulosa chiqarish mumkin? set yordamida (yoki multiset) takrorlanish jarayonlarini dasturlashda ketma ketlikdan elementlarni olish, yoki tez-tez o‘chirish va elementlar kiritish bu noto‘g‘riyondashuv hisoblanadi. Set to‘plam obʻyektini yaratish uchun takrorlanish jarayonlari asosida shakllantirilgan ketmk ketlik foydalanish kerak yoki tayyor to‘plam uchun insert funksiyasidan foydalanish maqsadga muvofiq.
Ammo, dastur tez-tez elementlarni qidirish ishlatilsa, set raqobatga chiqa olmaydi.
pair - yordamchi sinfi. Boshqa assotsiativ konteynerlar bilan ishlashni yanada ko‘rib chiqish uchun pair yordamchi shablon sinfi bilan tanishishimiz kerak. Bu sinf birlik sifatida ikkita obʻyektlarni saqlash imkoniyatini beradi. pair STD ning turli joylarida, xususan minmax() algoritmida, set equal_range() sinfining usulida, shuningdek juft (key, value) bo‘lgan assosiativ konteynerlar elementlari bilan ishlash uchun ishlatiladi.
pair - bir juft obʻyekt yaratish uchun quyidagi konstruktor sintaktiki ishlatiladi:
pair p1;
pair p2(val1, val2); pair p3(p1);
Amalari:
p.first – havola bo‘yicha juftlikning birinchi elementiga murojaat. p.second – havola bo‘yicha juftlikning ikkinchi elementiga murojaat.
p->first – ko‘rsatkich bo‘yicha juftlikning birinchi elementiga murojaat.
p->second – ko‘rsatkich bo‘yicha juftlikning ikkinchi elementiga murojaat.
p = other_p – qiymat qilib berish (C++ qoidasiga asosan oshkormas tip almatirish yordamida).
p.swap(other_p) yoki swap(p, other_p) –p va other_p lar uchun o‘rin almashtirish.
<, <=, >, >=, ==, != – taqqoslash amallari make_pair(val1, val2) – juftlikni beradi.
3.4-dastur. Pair konstruktori va amallarini ishlatish.
Assosiativ konreynerlar uchun map va multimap sinflari. map assotsiativ konteyneri (xarita, lug‘at) o‘z-o‘zini muvozanatlovchi daraxtga (qizil-qora daraxt) asoslangan to‘plamlar bilan bir xil tarzda amalga oshiriladi. To‘plam va lug‘at o‘rtasidagi asosiy farq shundaki, map massivi kalitlardan tashkil topgan elementlar juftlarining tartibli assotsiativ massivi (konteyneri) va ularning mos qiymatlaridan iborat. Lug‘atda kalitlari unikal (takrorlanmaydigan) va multimap bir nechta nusxadagi kalitlari bo‘ladi. Lug‘atlarda kalit va qiymat turlari fundamental tip yoki abstrakt tip bo‘lishi mumkin. Agar kalit tipi abstrakt tip bo‘lsa, uning uchun saralash yo‘nalishini belgilovchi komparator funksiyasi (taqqoslash funksiyasi) aniqlanishi kerak. Kalit doimiy qiymatga ega va kalit qiymatini o‘zgartirish mumkin emas. Juftlikning ikkinchi element qiymatini (asosiy qiymatini) o‘zgartirish mumkin.
Map (yoki multimap) sinflari bilan ishlashni boshlash uchun dastur sarlavhasiga (ikkala sinf bilan birgalikda) quyidagi dastur fragmenti yozildi (bu oldin ham barcha assosiativ konteynerlar uchun aytilgan edi):
#include
Konstruktorlar. Lug‘at obʻyektlari shablon parametrlarini: kalit tipi va kalitning qiymati tipi (key va T), taqqoslash (comp)funksiyasini o‘z ichiga oladi. Agar bunday funksiya bo‘lmasa, u oshkormas less <> funksiya (operation <) tomonidan o‘rnatiladi.
Quyidagi konstruktorlar yordamida map sinf obʻyektlarini yaratiladi:
Oddiy map konreyner konstruktorlari: map ar; yoki map ar(Comp);
Nusxalash uchun konstruktor: map ar(other);
Iteratorlar yordamida qo‘shish uchun konstruktorlar: map ar(first, last); yoki map ar(first, last, Somp);
Ro‘yxat asosida initsializatsiya qilish konstruktorlari: map ar {init}; yoki map ar(init); yoki map ar(init, Comp); Eslatma. Ro‘yxatni initsializatsiya qilishda har bir juftlik alohida figurali qavs ichiga olinishi kerak!
map ar {{"a1", 10}, {"www", 17}, {"j8", 100}};
Bu yerda Comp konteyner kalitlari solishtirish uchun funksiyasi (ixtiyoriy). Bundan tashqari, taqqoslash funksiyaning yonida konstruktor ixtiyoriy Allocator() vazifasini o‘z ichiga oladi (soddaligi uchun yozilmaydi), dasturchi uning allocator vazifasini ham belgilaydi.
Map sinfining destruktori: ar.~map();
Lug‘at usullari. Lug‘at usullari set to‘plam usullari bilan bir xil bo‘lganligi uchun ularni takrorlab keltirmaymiz. Bu usullar qanday ishlashini misol yordamida ko‘rsatamiz. Aytaylik, quyidagicha lug‘at yaratishimiz kerak: kalitga tasodifiy (string), qiymatga tasodifiy (integer) o‘rnatiladi. So‘ngra key1 va key2 orasidagi barcha key = > qiymat juftliklarining chiqishi talab qilinsin. Dastur oxirida key 3 kalit uchun maksimal qiymatni chiqarish talab qilinadi (dasturning o‘zidagi izohlarga qarang).
3.5-dastur. Lug‘at usullaridan foydalanish.
// Created by MBBahodir #include "stdafx.h"
#include #include #include #include #include
using namespace std;
int main() {
map rat; vector lit;
lit.push_back("a1"); lit.push_back("a2"); lit.push_back("a3"); lit.push_back("b1"); lit.push_back("b2"); lit.push_back("b3"); lit.push_back("c1"); lit.push_back("c2"); lit.push_back("c3");
default_random_engine rnd(time(0)); uniform_int_distribution d(-10, 20);
uniform_int_distribution c(0, 8);
//=============================1==============================//
// lugʻatni toʻldirish: tasofidiy kalit tasodifiy olinadi //
//============================================================//
int n;
cout << "Lugʻat elementlari sonini kirit: "; cin >> n;
while (n--) {
string S = lit[c(rnd)]; int D = d(rnd);
pair tpr = make_pair(S, D); rat.insert(tpr);
// emplace uchun juftlik yaratish shartmas:
//rat.emplace(S, D);
}
//=============================2==============================//
// 2 ta har xil amal bilan kalit va qiymat qoshish //
//============================================================//
rat.emplace("d1", 10);
rat.insert(pair("d3", -15)); rat.insert(pair("d3", 6));
//=============================3==============================//
// birinchi va ikkinchi kalit orasidagi elementlarni chiqarish//
//============================================================//
string el_l, el_r;
cout << "kalitlarni kirit:\n"; cout << "1-kalit: "; cin >> el_l; cout << "2-kalit: "; cin >> el_r; auto fst = rat.lower_bound(el_l); auto lst = rat.upper_bound(el_r); while (fst != lst) {
cout << fst -> first
<< " => "
<< fst -> second
<< endl; fst++;
}
//==============================4==============================//
// kalitga mos eng katta elementni aniqlash //
//=============================================================//
string tmp;
cout << "Kalit kirit: "; cin >> tmp;
auto first = rat.equal_range(tmp).first; auto last = rat.equal_range(tmp).second; if (first == last)
cout << 0 << endl;
else
while (first != last) {
auto r = first -> second; if (r >= 10)
cout << r << " "; first++;
}
system("pause");
return 0;
}
Elementlarga murojaat. Lug‘atlarda elementlarga kirishning yana ikkita usuli mavjud (iteratorlar bilan ishlashdan tashqari). Birinchi usul at(key) usulini qo‘llashdir (bilsangiz kerak). Biroq, indeksni argument sifatida qabul qilmaydi, lekin kalitning qiymatini qabul qiladi. Bu usul kalitga ekvivalent bo‘lgan kalit bilan mos elemeni qiymatiga mos yozuvlar qaytaradi. Agar bu element mavjud bo‘lmasa, out_of_range istisno funksiyasining qiymati qaytariladi. Boshqacha aytganda, massivda bunday kalit bor-yo‘qligini tekshiradi. Ikkinchi usul overloaded[] funksiyadan foydalanishga asoslangan. Lekin quyidagi sabablarga ko‘ra ehtiyotkorlik bilan foydalanish zarur. ar(key) mavjud bo‘lmasa, standart konstruktor yordamida kalit bilan yangi element qator qo‘shiladi. Aks holda elementga ko‘rsatkich qaytariladi. Eslattb o‘tamizki, indekslash funksiyasini assotsiativ konteyner sinflarning ikki turga (map va unordered_map) foydalanish mumkin. Ushbu usullarni ishlab chiquvchilar tomonidan qo‘shilishining sabablari aniq: dastur juda qisqa va chiroyli bo‘ladi.
at() funksiyasi istisno qaytargani uchun try - catch funksiyasi bilan quyidagicha boshqarish mumkin:
map rat; try {
rat.at("U");
}
// istesnoni ushlab olish catch (std::out_of_range) {
// uni qayta ishlash
rat["U"] = 15;
}
Dastur fragmentida "U" kalitli juftlik topilmasa, uni yaratib, yangi qiymat beradi.
rat["U"] = 15; (hiyla, ruscha fishka) indekslash amali u faqat asosiy qiymatini olish emas, balki bu qiymatini o‘zgartirish mumkin degan maʻnoni anglatadi, bir qiymatini qaytaradi. Boshqacha qilib aytganda, ushbu dastur fragmenidagi amallarini bajarish mumkin:
map, A = allocator
>> to‘plam pair tipidagi qiymatni saqlaydi. Bunda K kalit, tanlash imkonini beradi va T saqlanadigan qiymat. Shuning uchun iteratordan foydalangannimizda first kalit qiymatni va second saqlangan qiymatni qaytaradi, o‘zgartirish imkonini beradi. Yuqorida aytib o‘tilgandek operator[] asosiy amallardan hisoblanadi (vazifasini bilsangiz kerak). Agar map m bo‘lsa va m[k] = t maʻno jihatidan quyidagi fragmentga teng:
m.insert(make_pair(k, T())).first->second = t
Bu kabi elementlarni qo‘shish samarali hisoblanib, T obʻyektni yaratishga imkon bermaydi (yuqoridagi fragmentda aniq T() konstruktor chaqirilgan).
Agar operator[] noqulay va samarasiz deb hisoblasangiz, yana unga ikkita alternativ variantlar bor. Birinchisi find funksiyasidan foydalanib,kalit bo‘yicha (key, value) juftligiga mos iteratorni olish yoki kalit lug‘atda bo‘lmasa, end() funksiyadan foydalanish mumkin. Ikkinchisi at() funksiyasidan, yaʻni kalit asosida qiymatni qaytaradi. Agar kalit bo‘lmasa, istisno holatga o‘tadi.
Map sinfining umumiy shabloni quyidagicha:
template ,
template class Allocator = allocator>
Map sinfining operatorlari, xususiyatlari, funksiyalari va usullarini qo‘rib chiqamiz.
iterator- ikki tomonlama iterator bo‘lib value_type ishora beradi. Aniq tipi amalga oshirish bilan bog‘liq va Allocator asosila belgilanadi.
const_iterator- doimiy ikki tomonlama iterator bo‘lib const value_type ishora beradi. Aniq tipi amalga oshirish bilan bog‘liq va Allocator asisida belgilanadi. Bunda iterator va const_iterator uchun konstruktor bor, bu kafolatlanadi.
size_type – butun ishorasiz tip. Aniq tipi amalga oshirish bilan bog‘liq va Allocator asisida belgilanadi.
difference_type - butun ishorali tip. Aniq tipi amalga oshirish bilan bog‘liq va Allocator asisida belgilanadi.
Assotsiativ konteynerlar uchun standart usullar to‘plamidan tashqari, lug‘at Allocator::reference operator[](const key_type&) amalini taʻminlaydi. Masalan, m lug‘atda k kalit yuilan m[k] kuyidagi fragment bilan ekvmvalent: