JavaScript ma'lumotlar tuzilmalarining kuchini oching. Ushbu keng qamrovli qo'llanma o'rnatilgan Map va Set, hamda maxsus tuzilmalar yaratish strategiyalarini o'rganadi va global dasturchilarni samarali ma'lumotlar boshqaruvi bilan ta'minlaydi.
JavaScript ma'lumotlar tuzilmalari: Global dasturchilar uchun Map, Set va maxsus tuzilmalarni o'zlashtirish
Dasturiy ta'minotni ishlab chiqishning dinamik dunyosida ma'lumotlar tuzilmalarini o'zlashtirish juda muhimdir. Ular samarali algoritmlar va yaxshi tashkil etilgan kodning asosini tashkil etib, ilovaning ishlashi va kengayishiga bevosita ta'sir qiladi. Global dasturchilar uchun ushbu tushunchalarni bilish turli xil foydalanuvchilar bazasiga xizmat ko'rsatadigan va har xil ma'lumotlar yuklamalarini qayta ishlaydigan mustahkam ilovalar yaratish uchun juda zarur. Ushbu keng qamrovli qo'llanma JavaScript'ning kuchli o'rnatilgan ma'lumotlar tuzilmalari — Map va Setga chuqur kirib boradi, so'ngra o'zingizning maxsus ma'lumotlar tuzilmalaringizni yaratishning ishonchli sabablari va usullarini o'rganadi.
Biz amaliy misollar, real hayotiy keyslar va amaliy tavsiyalar orqali o'tamiz, bu esa barcha sohadagi dasturchilarning ushbu vositalardan to'liq foydalanishini ta'minlaydi. Berlindagi startapda, Tokiodagi yirik korxonada yoki San-Pauludagi mijoz uchun frilans loyihada ishlayotgan bo'lsangiz ham, bu yerda muhokama qilingan tamoyillar universal qo'llaniladi.
JavaScript'da ma'lumotlar tuzilmalarining ahamiyati
JavaScript'ning aniq implementatsiyalariga sho'ng'ishdan oldin, ma'lumotlar tuzilmalari nima uchun bunchalik fundamental ekanligiga qisqacha to'xtalib o'taylik. Ma'lumotlar tuzilmalari ma'lumotlarni tashkil etish, qayta ishlash, olish va saqlash uchun maxsus formatlardir. Ma'lumotlar tuzilmasini tanlash qo'shish, o'chirish, qidirish va saralash kabi operatsiyalarning samaradorligiga sezilarli darajada ta'sir qiladi.
JavaScript'da, o'zining moslashuvchanligi va front-end, back-end (Node.js) va mobil dasturlashda keng qo'llanilishi bilan mashhur bo'lgan tilda, ma'lumotlarni samarali boshqarish juda muhimdir. Noto'g'ri tanlangan ma'lumotlar tuzilmalari quyidagilarga olib kelishi mumkin:
- Ishlashdagi muammolar: Sekin yuklanish vaqtlari, javob bermaydigan foydalanuvchi interfeyslari va samarasiz server tomonidagi qayta ishlash.
- Xotiraning ortiqcha sarflanishi: Tizim resurslaridan keraksiz foydalanish, bu esa operatsion xarajatlarning oshishiga va potensial ishdan chiqishlarga olib keladi.
- Kodning murakkabligi: Chalkash ma'lumotlarni boshqarish mantig'i tufayli kodni saqlash va tuzatishdagi qiyinchiliklar.
JavaScript kuchli abstraksiyalarni taklif qilsa-da, dasturchilarga yuqori darajada optimallashtirilgan yechimlarni amalga oshirish uchun vositalarni ham taqdim etadi. Uning o'rnatilgan tuzilmalarini va maxsus tuzilmalar uchun andozalarni tushunish malakali global dasturchi bo'lishning kalitidir.
JavaScript'ning o'rnatilgan kuchli vositalari: Map va Set
Uzoq vaqt davomida JavaScript dasturchilari ma'lumotlar to'plamlarini boshqarish uchun asosan oddiy JavaScript obyektlariga (lug'atlar yoki xesh-xaritalarga o'xshash) va massivlarga tayanishgan. Ular ko'p qirrali bo'lishiga qaramay, cheklovlarga ega edi. ECMAScript 2015 (ES6) da Map va Setning joriy etilishi JavaScript'ning ma'lumotlarni boshqarish imkoniyatlarini sezilarli darajada oshirdi va ko'proq ixtisoslashgan va ko'pincha samaraliroq yechimlarni taklif qildi.
1. JavaScript Map'lari
Map — bu kalitlar har qanday ma'lumot turida, jumladan, obyektlar, funksiyalar va primitivlar bo'lishi mumkin bo'lgan kalit-qiymat juftliklari to'plamidir. Bu kalitlar yashirin ravishda satrlarga yoki Symbollarga o'zgartiriladigan an'anaviy JavaScript obyektlaridan sezilarli darajada farq qiladi.
Map'larning asosiy xususiyatlari:
- Har qanday turdagi kalit: Oddiy obyektlardan farqli o'laroq, ularda kalitlar odatda satrlar yoki Symbollar bo'ladi, Map kalitlari har qanday qiymat (obyektlar, primitivlar va hokazo) bo'lishi mumkin. Bu yanada murakkab va nozik ma'lumotlar aloqalarini yaratish imkonini beradi.
- Tartiblangan iteratsiya: Map elementlari qo'shilish tartibida takrorlanadi. Bu bashorat qilish imkoniyati ko'plab ilovalar uchun bebahodir.
- Size xususiyati: Map'lar elementlar sonini to'g'ridan-to'g'ri qaytaradigan `size` xususiyatiga ega, bu ularni sanash uchun kalitlar yoki qiymatlar bo'yicha takrorlashdan ko'ra samaraliroqdir.
- Ishlash samaradorligi: Kalit-qiymat juftliklarini tez-tez qo'shish va o'chirish uchun Map'lar odatda oddiy obyektlarga qaraganda yaxshiroq ishlashni taklif qiladi, ayniqsa ko'p sonli yozuvlar bilan ishlaganda.
Map bilan ishlashning keng tarqalgan operatsiyalari:
Map bilan ishlashning asosiy metodlarini ko'rib chiqaylik:
- `new Map([iterable])`: Yangi Map yaratadi. Map'ni boshlang'ich qiymatlar bilan to'ldirish uchun ixtiyoriy kalit-qiymat juftliklaridan iborat takrorlanuvchi obyekt berilishi mumkin.
- `map.set(key, value)`: Belgilangan kalit va qiymatga ega elementni qo'shadi yoki yangilaydi. Map obyektini qaytaradi.
- `map.get(key)`: Belgilangan kalit bilan bog'liq qiymatni yoki kalit topilmasa, `undefined` ni qaytaradi.
- `map.has(key)`: Belgilangan kalitga ega element Map'da mavjudligini ko'rsatuvchi mantiqiy qiymat qaytaradi.
- `map.delete(key)`: Belgilangan kalitga ega elementni Map'dan o'chiradi. Agar element muvaffaqiyatli o'chirilsa, `true`, aks holda `false` qaytaradi.
- `map.clear()`: Map'dagi barcha elementlarni o'chiradi.
- `map.size`: Map'dagi elementlar sonini qaytaradi.
Map bilan iteratsiya:
Map'lar takrorlanuvchandir, ya'ni ularning tarkibini aylanib chiqish uchun `for...of` sikllari va spread sintaksisi (`...`) kabi konstruksiyalardan foydalanishingiz mumkin.
- `map.keys()`: Kalitlar uchun iterator qaytaradi.
- `map.values()`: Qiymatlar uchun iterator qaytaradi.
- `map.entries()`: Kalit-qiymat juftliklari uchun iterator qaytaradi (`[key, value]` massivlari sifatida).
- `map.forEach((value, key, map) => {})`: Har bir kalit-qiymat juftligi uchun berilgan funksiyani bir marta bajaradi.
Map'dan amaliy foydalanish holatlari:
Map'lar juda ko'p qirrali. Mana bir nechta misollar:
- Keshlashtirish: Tez-tez murojaat qilinadigan ma'lumotlarni (masalan, API javoblari, hisoblangan qiymatlar) ularning tegishli kalitlari bilan saqlash.
- Ma'lumotlarni obyektlar bilan bog'lash: Obyektlar bilan metadata yoki qo'shimcha xususiyatlarni bog'lash uchun obyektlarning o'zini kalit sifatida ishlatish.
- Qidiruvlarni amalga oshirish: ID'larni foydalanuvchi obyektlari, mahsulot tafsilotlari yoki konfiguratsiya sozlamalariga samarali bog'lash.
- Takrorlanishlar sonini hisoblash: Ro'yxatdagi elementlarning takrorlanish sonini hisoblash, bu yerda element kalit, uning soni esa qiymatdir.
Misol: API javoblarini keshlashtirish (Global nuqtai nazar)
Tasavvur qiling, siz global elektron tijorat platformasini yaratmoqdasiz. Siz turli mintaqaviy API'lardan mahsulot tafsilotlarini olishingiz mumkin. Bu javoblarni keshlashtirish ishlash samaradorligini keskin oshirishi mumkin. Map yordamida bu juda oddiy:
const apiCache = new Map();
async function getProductDetails(productId, region) {
const cacheKey = `${productId}-${region}`;
if (apiCache.has(cacheKey)) {
console.log(`Keshdan topildi ${cacheKey} uchun`);
return apiCache.get(cacheKey);
}
console.log(`Keshda topilmadi ${cacheKey}. API'dan olinmoqda...`);
// Mintaqaviy API'dan ma'lumot olishni simulyatsiya qilish
const response = await fetch(`https://api.example.com/${region}/products/${productId}`);
const productData = await response.json();
// Kelajakda foydalanish uchun keshda saqlash
apiCache.set(cacheKey, productData);
return productData;
}
// Turli mintaqalarda foydalanish misoli:
getProductDetails('XYZ789', 'us-east-1'); // Ma'lumot oladi va keshlaydi
getProductDetails('XYZ789', 'eu-west-2'); // Alohida oladi va keshlaydi
getProductDetails('XYZ789', 'us-east-1'); // Keshdan topildi!
2. JavaScript Set'lari
Set — bu noyob qiymatlar to'plamidir. U sizga alohida elementlarni saqlash imkonini beradi va dublikatlarni avtomatik ravishda boshqaradi. Map kabi, Set elementlari ham har qanday ma'lumot turida bo'lishi mumkin.
Set'larning asosiy xususiyatlari:
- Noyob qiymatlar: Set'ning eng muhim xususiyati shundaki, u faqat noyob qiymatlarni saqlaydi. Agar siz allaqachon mavjud bo'lgan qiymatni qo'shishga harakat qilsangiz, u e'tiborga olinmaydi.
- Tartiblangan iteratsiya: Set elementlari qo'shilish tartibida takrorlanadi.
- Size xususiyati: Map'larga o'xshab, Set'lar ham elementlar sonini olish uchun `size` xususiyatiga ega.
- Ishlash samaradorligi: Elementning mavjudligini tekshirish (`has`) va elementlarni qo'shish/o'chirish Set'larda odatda juda samarali operatsiyalar bo'lib, ko'pincha o'rtacha O(1) vaqt murakkabligiga ega.
Set bilan ishlashning keng tarqalgan operatsiyalari:
- `new Set([iterable])`: Yangi Set yaratadi. Set'ni elementlar bilan boshlang'ich to'ldirish uchun ixtiyoriy takrorlanuvchi obyekt berilishi mumkin.
- `set.add(value)`: Set'ga yangi element qo'shadi. Set obyektini qaytaradi.
- `set.has(value)`: Belgilangan qiymatga ega element Set'da mavjudligini ko'rsatuvchi mantiqiy qiymat qaytaradi.
- `set.delete(value)`: Belgilangan qiymatga ega elementni Set'dan o'chiradi. Agar element muvaffaqiyatli o'chirilsa, `true`, aks holda `false` qaytaradi.
- `set.clear()`: Set'dagi barcha elementlarni o'chiradi.
- `set.size`: Set'dagi elementlar sonini qaytaradi.
Set bilan iteratsiya:
Set'lar ham takrorlanuvchandir:
- `set.keys()`: Qiymatlar uchun iterator qaytaradi (chunki Set'da kalitlar va qiymatlar bir xil).
- `set.values()`: Qiymatlar uchun iterator qaytaradi.
- `set.entries()`: Qiymatlar uchun `[value, value]` ko'rinishidagi iterator qaytaradi.
- `set.forEach((value, key, set) => {})`: Har bir element uchun berilgan funksiyani bir marta bajaradi.
Set'dan amaliy foydalanish holatlari:
- Dublikatlarni olib tashlash: Massivdan noyob elementlar ro'yxatini olishning tez va samarali usuli.
- A'zolikni tekshirish: Elementning to'plamda mavjudligini juda tez tekshirish.
- Noyob hodisalarni kuzatish: Muayyan hodisaning faqat bir marta qayd etilishi yoki qayta ishlanishini ta'minlash.
- To'plam operatsiyalari: To'plamlar ustida birlashma, kesishma va farq operatsiyalarini bajarish.
Misol: Global hodisalar jurnalida noyob foydalanuvchilarni topish
Foydalanuvchi faolligini kuzatuvchi global veb-ilovasini ko'rib chiqing. Sizda turli serverlar yoki xizmatlardan olingan jurnallar bo'lishi mumkin, ularda bir xil foydalanuvchi harakati uchun dublikat yozuvlar bo'lishi ehtimoli bor. Set ishtirok etgan barcha noyob foydalanuvchilarni topish uchun juda mos keladi:
const userActivityLogs = [
{ userId: 'user123', action: 'login', timestamp: '2023-10-27T10:00:00Z', region: 'Asia' },
{ userId: 'user456', action: 'view', timestamp: '2023-10-27T10:05:00Z', region: 'Europe' },
{ userId: 'user123', action: 'click', timestamp: '2023-10-27T10:06:00Z', region: 'Asia' },
{ userId: 'user789', action: 'login', timestamp: '2023-10-27T10:08:00Z', region: 'North America' },
{ userId: 'user456', action: 'logout', timestamp: '2023-10-27T10:10:00Z', region: 'Europe' },
{ userId: 'user123', action: 'view', timestamp: '2023-10-27T10:12:00Z', region: 'Asia' } // user123 harakatining dublikati
];
const uniqueUserIds = new Set();
userActivityLogs.forEach(log => {
uniqueUserIds.add(log.userId);
});
console.log('Noyob foydalanuvchi ID\'lari:', Array.from(uniqueUserIds)); // Ko'rsatish uchun Set'ni massivga qaytarish uchun Array.from'dan foydalanish
// Natija: Noyob foydalanuvchi ID'lari: [ 'user123', 'user456', 'user789' ]
// Yana bir misol: Mahsulot ID'lari ro'yxatidan dublikatlarni olib tashlash
const productIds = ['A101', 'B202', 'A101', 'C303', 'B202', 'D404'];
const uniqueProductIds = new Set(productIds);
console.log('Noyob mahsulot ID\'lari:', [...uniqueProductIds]); // Spread sintaksisidan foydalanish
// Natija: Noyob mahsulot ID'lari: [ 'A101', 'B202', 'C303', 'D404' ]
O'rnatilgan tuzilmalar yetarli bo'lmaganda: Maxsus ma'lumotlar tuzilmalari
Map va Set kuchli bo'lishiga qaramay, ular umumiy maqsadli vositalardir. Ba'zi holatlarda, ayniqsa murakkab algoritmlar, yuqori darajada ixtisoslashgan ma'lumotlar talablari yoki ishlashi muhim bo'lgan ilovalar uchun o'zingizning maxsus ma'lumotlar tuzilmalaringizni amalga oshirishingiz kerak bo'lishi mumkin. Bu yerda algoritmlar va hisoblash murakkabligini chuqurroq tushunish muhim ahamiyat kasb etadi.
Nima uchun maxsus ma'lumotlar tuzilmalarini yaratish kerak?
- Ishlash samaradorligini optimallashtirish: Tuzilmani muayyan muammoga moslashtirish umumiy yechimlarga qaraganda sezilarli ishlash afzalliklarini berishi mumkin. Masalan, ixtisoslashtirilgan daraxt tuzilmasi ma'lum qidiruv so'rovlari uchun Map'dan tezroq bo'lishi mumkin.
- Xotira samaradorligi: Maxsus tuzilmalar xotiradan aniqroq foydalanish uchun ishlab chiqilishi mumkin, bu esa umumiy maqsadli tuzilmalar bilan bog'liq ortiqcha yuklardan qochish imkonini beradi.
- Maxsus funksionallik: O'rnatilgan tuzilmalar qo'llab-quvvatlamaydigan noyob xatti-harakatlar yoki cheklovlarni amalga oshirish (masalan, ma'lum tartiblash qoidalariga ega ustuvorlik navbati, yo'naltirilgan qirralarga ega graf).
- O'quv maqsadlari: Fundamental ma'lumotlar tuzilmalarining (stek, navbat, bog'langan ro'yxatlar, daraxtlar kabi) qanday ishlashini ularni noldan amalga oshirish orqali tushunish.
- Algoritmlarni amalga oshirish: Ko'plab ilg'or algoritmlar ma'lum ma'lumotlar tuzilmalari bilan uzviy bog'liqdir (masalan, Deykstra algoritmi ko'pincha min-ustuvorlik navbatidan foydalanadi).
JavaScript'da amalga oshiriladigan keng tarqalgan maxsus ma'lumotlar tuzilmalari:
1. Bog'langan ro'yxatlar
Bog'langan ro'yxat — bu chiziqli ma'lumotlar tuzilmasi bo'lib, unda elementlar ketma-ket xotira joylarida saqlanmaydi. Buning o'rniga, har bir element (tugun) ma'lumotni va ketma-ketlikdagi keyingi tugunga havolani (yoki bog'lanishni) o'z ichiga oladi.
- Turlari: Bir tomonlama bog'langan ro'yxatlar, Ikki tomonlama bog'langan ro'yxatlar, Aylanma bog'langan ro'yxatlar.
- Qo'llanilish sohalari: Stek va navbatlarni amalga oshirish, dinamik xotirani boshqarish, bekor qilish/qaytarish funksionalligi.
- Murakkabligi: Boshiga/oxiriga qo'shish/o'chirish O(1) bo'lishi mumkin, ammo qidirish O(n) dir.
Eskiz: Bir tomonlama bog'langan ro'yxat
Biz JavaScript'da keng tarqalgan oddiy sinfga asoslangan yondashuvdan foydalanamiz.
class Node {
constructor(data) {
this.data = data;
this.next = null;
}
}
class LinkedList {
constructor() {
this.head = null;
this.size = 0;
}
// Tugunni oxiriga qo'shish
add(data) {
const newNode = new Node(data);
if (!this.head) {
this.head = newNode;
} else {
let current = this.head;
while (current.next) {
current = current.next;
}
current.next = newNode;
}
this.size++;
}
// Tugunni qiymati bo'yicha o'chirish
remove(data) {
if (!this.head) return false;
if (this.head.data === data) {
this.head = this.head.next;
this.size--;
return true;
}
let current = this.head;
while (current.next) {
if (current.next.data === data) {
current.next = current.next.next;
this.size--;
return true;
}
current = current.next;
}
return false;
}
// Tugunni qiymati bo'yicha topish
find(data) {
let current = this.head;
while (current) {
if (current.data === data) {
return current;
}
current = current.next;
}
return null;
}
// Ro'yxatni chiqarish
print() {
let current = this.head;
let list = '';
while (current) {
list += current.data + ' -> ';
current = current.next;
}
console.log(list + 'null');
}
}
// Foydalanish:
const myList = new LinkedList();
myList.add('Apple');
myList.add('Banana');
myList.add('Cherry');
myList.print(); // Apple -> Banana -> Cherry -> null
myList.remove('Banana');
myList.print(); // Apple -> Cherry -> null
console.log(myList.find('Apple')); // Node { data: 'Apple', next: Node { data: 'Cherry', next: null } }
console.log('Hajmi:', myList.size); // Hajmi: 2
2. Steklar
Stek — bu "Oxirgi kirgan, birinchi chiqadi" (LIFO) tamoyiliga amal qiladigan chiziqli ma'lumotlar tuzilmasi. Likopchalar to'plamini tasavvur qiling: siz yangi likopchani tepaga qo'yasiz va tepadan likopchani olasiz.
- Operatsiyalar: `push` (tepaga qo'shish), `pop` (tepadan olib tashlash), `peek` (tepadagi elementni ko'rish), `isEmpty`.
- Qo'llanilish sohalari: Funksiya chaqiruvlari steklari, ifodalarni baholash, backtracking algoritmlari.
- Murakkabligi: Barcha asosiy operatsiyalar odatda O(1) dir.
Eskiz: Massiv yordamida stek
JavaScript massivi stekni osonlikcha taqlid qilishi mumkin.
class Stack {
constructor() {
this.items = [];
}
// Elementni tepaga qo'shish
push(element) {
this.items.push(element);
}
// Tepadagi elementni olib tashlash va qaytarish
pop() {
if (this.isEmpty()) {
return "Underflow"; // Yoki xatolik chiqarish
}
return this.items.pop();
}
// Tepadagi elementni olib tashlamasdan ko'rish
peek() {
if (this.isEmpty()) {
return "Stekda elementlar yo'q";
}
return this.items[this.items.length - 1];
}
// Stekning bo'shligini tekshirish
isEmpty() {
return this.items.length === 0;
}
// Hajmini olish
size() {
return this.items.length;
}
// Stekni chiqarish (tepadan pastga)
print() {
let str = "";
for (let i = this.items.length - 1; i >= 0; i--) {
str += this.items[i] + " ";
}
console.log(str.trim());
}
}
// Foydalanish:
const myStack = new Stack();
myStack.push(10);
myStack.push(20);
myStack.push(30);
myStack.print(); // 30 20 10
console.log('Peek:', myStack.peek()); // Peek: 30
console.log('Pop:', myStack.pop()); // Pop: 30
myStack.print(); // 20 10
console.log('Bo\'shmi:', myStack.isEmpty()); // Bo'shmi: false
3. Navbatlar
Navbat — bu "Birinchi kirgan, birinchi chiqadi" (FIFO) tamoyiliga amal qiladigan chiziqli ma'lumotlar tuzilmasi. Bilet kassasida navbatda turgan odamlarni tasavvur qiling: navbatdagi birinchi odam birinchi bo'lib xizmat ko'rsatiladi.
- Operatsiyalar: `enqueue` (oxiriga qo'shish), `dequeue` (boshidan olib tashlash), `front` (boshidagi elementni ko'rish), `isEmpty`.
- Qo'llanilish sohalari: Vazifalarni rejalashtirish, so'rovlarni boshqarish (masalan, chop etish navbatlari, veb-server so'rovlari navbatlari), graflarda kenglik bo'yicha qidirish (BFS).
- Murakkabligi: Standart massiv bilan `dequeue` qayta indekslash tufayli O(n) bo'lishi mumkin. Yaxshiroq optimallashtirilgan implementatsiya (masalan, bog'langan ro'yxat yoki ikkita stek yordamida) O(1) ga erishadi.
Eskiz: Massiv yordamida navbat (ishlash samaradorligini hisobga olgan holda)
Massivdagi `shift()` O(n) bo'lsa-da, bu asosiy misol uchun eng oddiy usul. Ishlab chiqarish uchun bog'langan ro'yxat yoki massivga asoslangan rivojlangan navbatni ko'rib chiqing.
class Queue {
constructor() {
this.items = [];
}
// Elementni oxiriga qo'shish
enqueue(element) {
this.items.push(element);
}
// Boshidagi elementni olib tashlash va qaytarish
dequeue() {
if (this.isEmpty()) {
return "Underflow";
}
return this.items.shift(); // Standart massivlarda O(n) operatsiya
}
// Boshidagi elementni olib tashlamasdan ko'rish
front() {
if (this.isEmpty()) {
return "Navbatda elementlar yo'q";
}
return this.items[0];
}
// Navbatning bo'shligini tekshirish
isEmpty() {
return this.items.length === 0;
}
// Hajmini olish
size() {
return this.items.length;
}
// Navbatni chiqarish (boshidan oxiriga)
print() {
let str = "";
for (let i = 0; i < this.items.length; i++) {
str += this.items[i] + " ";
}
console.log(str.trim());
}
}
// Foydalanish:
const myQueue = new Queue();
myQueue.enqueue('A');
myQueue.enqueue('B');
myQueue.enqueue('C');
myQueue.print(); // A B C
console.log('Oldindagi:', myQueue.front()); // Oldindagi: A
console.log('Dequeue:', myQueue.dequeue()); // Dequeue: A
myQueue.print(); // B C
console.log('Bo\'shmi:', myQueue.isEmpty()); // Bo'shmi: false
4. Daraxtlar (Binar qidiruv daraxtlari - BST)
Daraxtlar ierarxik ma'lumotlar tuzilmalaridir. Binar qidiruv daraxti (BST) — har bir tugunning ko'pi bilan ikkita farzandi bo'lgan daraxt turidir, ular chap farzand va o'ng farzand deb ataladi. Har qanday berilgan tugun uchun uning chap quyi daraxtidagi barcha qiymatlar tugun qiymatidan kichik, o'ng quyi daraxtidagi barcha qiymatlar esa kattaroq bo'ladi.
- Operatsiyalar: Qo'shish, o'chirish, qidirish, aylanib chiqish (in-order, pre-order, post-order).
- Qo'llanilish sohalari: Samarali qidirish va saralash (muvozanatli daraxtlar uchun ko'pincha O(n) dan yaxshiroq), belgilar jadvallarini amalga oshirish, ma'lumotlar bazasini indekslash.
- Murakkabligi: Muvozanatli BST uchun qidirish, qo'shish va o'chirish O(log n) dir. Qiyshaygan daraxt uchun esa ular O(n) ga tushishi mumkin.
Eskiz: Binar qidiruv daraxti
Ushbu implementatsiya asosiy qo'shish va qidirishga qaratilgan.
class TreeNode {
constructor(value) {
this.value = value;
this.left = null;
this.right = null;
}
}
class BinarySearchTree {
constructor() {
this.root = null;
}
// BST'ga qiymat qo'shish
insert(value) {
const newNode = new TreeNode(value);
if (!this.root) {
this.root = newNode;
return this;
}
let current = this.root;
while (true) {
if (value === current.value) return undefined; // Yoki dublikatlarni kerak bo'lganda qayta ishlash
if (value < current.value) {
if (!current.left) {
current.left = newNode;
return this;
}
current = current.left;
} else {
if (!current.right) {
current.right = newNode;
return this;
}
current = current.right;
}
}
}
// BST'da qiymat qidirish
search(value) {
if (!this.root) return null;
let current = this.root;
while (current) {
if (value === current.value) return current;
if (value < current.value) {
current = current.left;
} else {
current = current.right;
}
}
return null; // Topilmadi
}
// In-order aylanib chiqish (saralangan ro'yxatni qaytaradi)
inOrderTraversal(node = this.root, result = []) {
if (node) {
this.inOrderTraversal(node.left, result);
result.push(node.value);
this.inOrderTraversal(node.right, result);
}
return result;
}
}
// Foydalanish:
const bst = new BinarySearchTree();
bst.insert(10);
bst.insert(5);
bst.insert(15);
bst.insert(2);
bst.insert(7);
bst.insert(12);
bst.insert(18);
console.log('In-order aylanib chiqish:', bst.inOrderTraversal()); // [ 2, 5, 7, 10, 12, 15, 18 ]
console.log('7 ni qidirish:', bst.search(7)); // TreeNode { value: 7, left: null, right: null }
console.log('100 ni qidirish:', bst.search(100)); // null
5. Graflar
Graflar — bu obyektlar to'plamini (uchlar yoki tugunlar) ifodalovchi ko'p qirrali ma'lumotlar tuzilmasi bo'lib, unda har bir juft uch o'zaro aloqa (qirra) bilan bog'langan bo'lishi mumkin. Ular tarmoqlarni modellashtirish uchun ishlatiladi.
- Turlari: Yo'naltirilgan va yo'naltirilmagan, vaznli va vaznsiz.
- Tasvirlash usullari: Qo'shnilik ro'yxati (JS'da eng keng tarqalgan), Qo'shnilik matritsasi.
- Operatsiyalar: Uchlar/qirralarni qo'shish/o'chirish, aylanib chiqish (DFS, BFS), eng qisqa yo'lni topish.
- Qo'llanilish sohalari: Ijtimoiy tarmoqlar, xaritalash/navigatsiya tizimlari, tavsiya tizimlari, tarmoq topologiyasi.
- Murakkabligi: Tasvirlash usuli va operatsiyaga qarab juda katta farq qiladi.
Eskiz: Qo'shnilik ro'yxati bilan graf
Qo'shnilik ro'yxati Map (yoki oddiy obyekt) dan foydalanadi, bu yerda kalitlar uchlar, qiymatlar esa ularning qo'shni uchlari massivlaridir.
class Graph {
constructor() {
this.adjacencyList = new Map(); // Kalitlarni yaxshiroq boshqarish uchun Map'dan foydalanish
}
// Uch qo'shish
addVertex(vertex) {
if (!this.adjacencyList.has(vertex)) {
this.adjacencyList.set(vertex, []);
}
}
// Qirra qo'shish (yo'naltirilmagan graf uchun)
addEdge(vertex1, vertex2) {
if (!this.adjacencyList.has(vertex1) || !this.adjacencyList.has(vertex2)) {
throw new Error("Bir yoki ikkala uch mavjud emas.");
}
this.adjacencyList.get(vertex1).push(vertex2);
this.adjacencyList.get(vertex2).push(vertex1); // Yo'naltirilmagan graf uchun
}
// Qirra o'chirish
removeEdge(vertex1, vertex2) {
if (!this.adjacencyList.has(vertex1) || !this.adjacencyList.has(vertex2)) {
return false;
}
this.adjacencyList.set(vertex1, this.adjacencyList.get(vertex1).filter(v => v !== vertex2));
this.adjacencyList.set(vertex2, this.adjacencyList.get(vertex2).filter(v => v !== vertex1));
return true;
}
// Uchni va uning barcha qirralarini o'chirish
removeVertex(vertex) {
if (!this.adjacencyList.has(vertex)) {
return false;
}
while (this.adjacencyList.get(vertex).length) {
const adjacentVertex = this.adjacencyList.get(vertex).pop();
this.removeEdge(vertex, adjacentVertex);
}
this.adjacencyList.delete(vertex);
return true;
}
// Asosiy chuqurlik bo'yicha qidirish (DFS) aylanib chiqish
dfs(startVertex, visited = new Set(), result = []) {
if (!this.adjacencyList.has(startVertex)) return null;
visited.add(startVertex);
result.push(startVertex);
this.adjacencyList.get(startVertex).forEach(neighbor => {
if (!visited.has(neighbor)) {
this.dfs(neighbor, visited, result);
}
});
return result;
}
}
// Foydalanish (masalan, global shaharlar o'rtasidagi parvoz yo'nalishlarini ifodalash):
const flightNetwork = new Graph();
flightNetwork.addVertex('New York');
flightNetwork.addVertex('London');
flightNetwork.addVertex('Tokyo');
flightNetwork.addVertex('Sydney');
flightNetwork.addVertex('Rio de Janeiro');
flightNetwork.addEdge('New York', 'London');
flightNetwork.addEdge('New York', 'Tokyo');
flightNetwork.addEdge('London', 'Tokyo');
flightNetwork.addEdge('London', 'Rio de Janeiro');
flightNetwork.addEdge('Tokyo', 'Sydney');
console.log('Nyu-Yorkdan parvozlar tarmog\'i DFS:', flightNetwork.dfs('New York'));
// Misol natijasi: [ 'New York', 'London', 'Tokyo', 'Sydney', 'Rio de Janeiro' ] (tartib Set iteratsiyasiga qarab o'zgarishi mumkin)
// flightNetwork.removeEdge('New York', 'London');
// flightNetwork.removeVertex('Tokyo');
To'g'ri yondashuvni tanlash
O'rnatilgan Map/Set'dan foydalanish yoki maxsus tuzilmani amalga oshirish to'g'risida qaror qabul qilayotganda, quyidagilarni hisobga oling:
- Muammoning murakkabligi: Oddiy to'plamlar va qidiruvlar uchun Map va Set odatda yetarli va ko'pincha mahalliy optimallashtirishlar tufayli samaraliroqdir.
- Ishlash samaradorligi talablari: Agar ilovangiz ma'lum operatsiyalar uchun juda yuqori ishlashni talab qilsa (masalan, doimiy vaqtda qo'shish va o'chirish, logarifmik qidiruv), maxsus tuzilma zarur bo'lishi mumkin.
- O'rganish darajasi: Maxsus tuzilmalarni amalga oshirish algoritmlar va ma'lumotlar tuzilmalari tamoyillarini mustahkam tushunishni talab qiladi. Ko'pchilik umumiy vazifalar uchun o'rnatilgan xususiyatlardan foydalanish samaraliroqdir.
- Qo'llab-quvvatlanuvchanlik: Yaxshi hujjatlashtirilgan va sinovdan o'tgan maxsus tuzilmalarni qo'llab-quvvatlash mumkin, ammo murakkablari sezilarli qo'llab-quvvatlash xarajatlarini keltirib chiqarishi mumkin.
Global dasturlashda e'tiborga olinadigan jihatlar
Global miqyosda ishlaydigan dasturchilar sifatida ma'lumotlar tuzilmalari bilan bog'liq bir nechta omillarni e'tiborga olish kerak:
- Kengayuvchanlik: Ma'lumotlar hajmi eksponensial ravishda o'sganda siz tanlagan ma'lumotlar tuzilmasi qanday ishlaydi? Bu butun dunyo bo'ylab millionlab foydalanuvchilarga xizmat ko'rsatadigan ilovalar uchun juda muhim. Map va Set kabi o'rnatilgan tuzilmalar odatda kengayuvchanlik uchun yaxshi optimallashtirilgan, ammo maxsus tuzilmalar buni hisobga olgan holda loyihalashtirilishi kerak.
- Internatsionalizatsiya (i18n) va Lokalizatsiya (l10n): Ma'lumotlar turli lingvistik va madaniy muhitlardan kelishi mumkin. Ma'lumotlar tuzilmalaringiz turli belgilar to'plamlari, saralash qoidalari va ma'lumotlar formatlarini qanday qayta ishlashini o'ylab ko'ring. Masalan, foydalanuvchi nomlarini saqlashda oddiy satrli kalitlardan ko'ra obyektlarni kalit sifatida ishlatadigan Map'lardan foydalanish ishonchliroq bo'lishi mumkin.
- Vaqt mintaqalari va sana/vaqtni boshqarish: Turli vaqt mintaqalarida vaqtga sezgir ma'lumotlarni saqlash va so'rash ehtiyotkorlikni talab qiladi. Bu to'g'ridan-to'g'ri ma'lumotlar tuzilmasi muammosi bo'lmasa-da, sana obyektlarini samarali olish va boshqarish ko'pincha ularning qanday saqlanishiga bog'liq (masalan, vaqt belgilari yoki UTC qiymatlari bilan indekslangan Map'larda).
- Mintaqalar bo'yicha ishlash samaradorligi: Tarmoq kechikishi va server joylashuvi seziladigan ishlashga ta'sir qilishi mumkin. Serverda (tegishli tuzilmalardan foydalangan holda) va mijoz tomonida ma'lumotlarni samarali olish va qayta ishlash ushbu muammolarni yumshatishi mumkin.
- Jamoaviy hamkorlik: Turli, taqsimlangan jamoalarda ishlaganda, aniq hujjatlashtirish va foydalanilgan ma'lumotlar tuzilmalarini umumiy tushunish juda muhim. Map va Set kabi standart tuzilmalarni amalga oshirish yangi xodimlarni o'rgatishni va hamkorlikni osonlashtiradi.
Xulosa
JavaScript'ning Map va Setlari ko'plab umumiy ma'lumotlarni boshqarish vazifalari uchun kuchli, samarali va oqilona yechimlarni taqdim etadi. Ular eski usullarga nisbatan yaxshilangan imkoniyatlarni taklif qiladi va har qanday zamonaviy JavaScript dasturchisi uchun muhim vositalardir.
Biroq, ma'lumotlar tuzilmalari dunyosi bu o'rnatilgan turlardan ancha kengroqdir. Murakkab muammolar, ishlashdagi qiyinchiliklar yoki maxsus talablar uchun Bog'langan ro'yxatlar, Steklar, Navbatlar, Daraxtlar va Graflar kabi maxsus ma'lumotlar tuzilmalarini amalga oshirish foydali va ko'pincha zarur bo'lgan ishdir. Bu sizning hisoblash samaradorligi va muammolarni hal qilish bo'yicha tushunchangizni chuqurlashtiradi.
Global dasturchilar sifatida ushbu vositalarni qabul qilish va ularning kengayuvchanlik, ishlash samaradorligi va xalqarolashtirishga ta'sirini tushunish sizga jahon sahnasida rivojlana oladigan murakkab, mustahkam va yuqori samarali ilovalarni yaratish imkonini beradi. O'rganishda, amalga oshirishda va optimallashtirishda davom eting!