O'zbek

Binar Qidiruv Daraxtlari (BQD) asoslarini o'rganing va ularni JavaScript'da samarali amalga oshirishni bilib oling. Ushbu qo'llanma BQD tuzilishi, amallari va butun dunyodagi dasturchilar uchun amaliy misollarni o'z ichiga oladi.

Binar Qidiruv Daraxtlari: JavaScript'da To'liq Amalga Oshirish Qo'llanmasi

Binar Qidiruv Daraxtlari (BQD) kompyuter fanlarida asosiy ma'lumotlar tuzilmasi bo'lib, ma'lumotlarni samarali qidirish, saralash va olish uchun keng qo'llaniladi. Ularning ierarxik tuzilishi ko'plab amallarda logarifmik vaqt murakkabligini ta'minlaydi, bu ularni katta hajmdagi ma'lumotlar to'plamini boshqarish uchun kuchli vositaga aylantiradi. Ushbu qo'llanma BQD haqida to'liq ma'lumot beradi va ularning JavaScript'da amalga oshirilishini namoyish etadi, bu esa butun dunyodagi dasturchilarga mo'ljallangan.

Binar Qidiruv Daraxtlarini Tushunish

Binar Qidiruv Daraxti Nima?

Binar Qidiruv Daraxti - bu daraxtga asoslangan ma'lumotlar tuzilmasi bo'lib, unda har bir tugun ko'pi bilan ikkita bolaga ega bo'ladi, ular chap bola va o'ng bola deb ataladi. BQD'ning asosiy xususiyati shundaki, har qanday berilgan tugun uchun:

Bu xususiyat BQD'dagi elementlarning har doim tartiblangan bo'lishini ta'minlaydi, bu esa samarali qidirish va olish imkonini beradi.

Asosiy Tushunchalar

Binar Qidiruv Daraxtini JavaScript'da Amalga Oshirish

Node Klassini Aniqlash

Birinchidan, BQD'dagi har bir tugunni ifodalash uchun `Node` klassini aniqlaymiz. Har bir tugun ma'lumotlarni saqlash uchun `key` va o'zining bolalariga `left` va `right` ishoralarini o'z ichiga oladi.


class Node {
  constructor(key) {
    this.key = key;
    this.left = null;
    this.right = null;
  }
}

Binar Qidiruv Daraxti Klassini Aniqlash

Keyin `BinarySearchTree` klassini aniqlaymiz. Bu klass ildiz tugunini va daraxtga element qo'shish, qidirish, o'chirish va aylanib o'tish uchun metodlarni o'z ichiga oladi.


class BinarySearchTree {
  constructor() {
    this.root = null;
  }

  // Metodlar shu yerga qo'shiladi
}

Qo'shish (Insertion)

`insert` metodi BQD'ga berilgan kalit bilan yangi tugunni qo'shadi. Qo'shish jarayoni yangi tugunni mavjud tugunlarga nisbatan tegishli joyga qo'yish orqali BQD xususiyatini saqlab qoladi.


insert(key) {
  const newNode = new Node(key);

  if (this.root === null) {
    this.root = newNode;
  } else {
    this.insertNode(this.root, newNode);
  }
}

insertNode(node, newNode) {
  if (newNode.key < node.key) {
    if (node.left === null) {
      node.left = newNode;
    } else {
      this.insertNode(node.left, newNode);
    }
  } else {
    if (node.right === null) {
      node.right = newNode;
    } else {
      this.insertNode(node.right, newNode);
    }
  }
}

Misol: BQD'ga qiymatlarni qo'shish


const bst = new BinarySearchTree();
bst.insert(11);
bst.insert(7);
bst.insert(15);
bst.insert(5);
bst.insert(3);
bst.insert(9);
bst.insert(8);
bst.insert(10);
bst.insert(13);
bst.insert(12);
bst.insert(14);
bst.insert(20);
bst.insert(18);
bst.insert(25);

Qidirish (Searching)

`search` metodi berilgan kalitli tugun BQD'da mavjudligini tekshiradi. U daraxtni aylanib o'tadi, kalitni joriy tugun kaliti bilan taqqoslaydi va shunga mos ravishda chap yoki o'ng quyi daraxtga o'tadi.


search(key) {
  return this.searchNode(this.root, key);
}

searchNode(node, key) {
  if (node === null) {
    return false;
  }

  if (key < node.key) {
    return this.searchNode(node.left, key);
  } else if (key > node.key) {
    return this.searchNode(node.right, key);
  } else {
    return true;
  }
}

Misol: BQD'dan qiymat qidirish


console.log(bst.search(9));  // Natija: true
console.log(bst.search(2));  // Natija: false

O'chirish (Deletion)

`remove` metodi BQD'dan berilgan kalitli tugunni o'chiradi. Bu eng murakkab operatsiya, chunki tugunni o'chirishda BQD xususiyatini saqlab qolish kerak. Ko'rib chiqilishi kerak bo'lgan uchta holat mavjud:


remove(key) {
  this.root = this.removeNode(this.root, key);
}

removeNode(node, key) {
  if (node === null) {
    return null;
  }

  if (key < node.key) {
    node.left = this.removeNode(node.left, key);
    return node;
  } else if (key > node.key) {
    node.right = this.removeNode(node.right, key);
    return node;
  } else {
    // kalit node.key ga teng

    // 1-holat - barg tugun
    if (node.left === null && node.right === null) {
      node = null;
      return node;
    }

    // 2-holat - tugunning faqat 1 ta bolasi bor
    if (node.left === null) {
      node = node.right;
      return node;
    } else if (node.right === null) {
      node = node.left;
      return node;
    }

    // 3-holat - tugunning 2 ta bolasi bor
    const aux = this.findMinNode(node.right);
    node.key = aux.key;
    node.right = this.removeNode(node.right, aux.key);
    return node;
  }
}

findMinNode(node) {
  let current = node;
  while (current != null && current.left != null) {
    current = current.left;
  }
  return current;
}

Misol: BQD'dan qiymatni o'chirish


bst.remove(7);
console.log(bst.search(7)); // Natija: false

Daraxtni Aylanib O'tish

Daraxtni aylanib o'tish har bir tugunga ma'lum bir tartibda tashrif buyurishni o'z ichiga oladi. Bir nechta keng tarqalgan aylanib o'tish usullari mavjud:


inOrderTraverse(callback) {
  this.inOrderTraverseNode(this.root, callback);
}

inOrderTraverseNode(node, callback) {
  if (node !== null) {
    this.inOrderTraverseNode(node.left, callback);
    callback(node.key);
    this.inOrderTraverseNode(node.right, callback);
  }
}

preOrderTraverse(callback) {
  this.preOrderTraverseNode(this.root, callback);
}

preOrderTraverseNode(node, callback) {
  if (node !== null) {
    callback(node.key);
    this.preOrderTraverseNode(node.left, callback);
    this.preOrderTraverseNode(node.right, callback);
  }
}

postOrderTraverse(callback) {
  this.postOrderTraverseNode(this.root, callback);
}

postOrderTraverseNode(node, callback) {
  if (node !== null) {
    this.postOrderTraverseNode(node.left, callback);
    this.postOrderTraverseNode(node.right, callback);
    callback(node.key);
  }
}

Misol: BQD'ni aylanib o'tish


const printNode = (value) => console.log(value);

bst.inOrderTraverse(printNode);   // Natija: 3 5 8 9 10 11 12 13 14 15 18 20 25
bst.preOrderTraverse(printNode);  // Natija: 11 5 3 9 8 10 15 13 12 14 20 18 25
bst.postOrderTraverse(printNode); // Natija: 3 8 10 9 12 14 13 18 25 20 15 11

Minimal va Maksimal Qiymatlar

BQD'dagi minimal va maksimal qiymatlarni topish uning tartiblangan tabiati tufayli juda oson.


min() {
  return this.minNode(this.root);
}

minNode(node) {
  let current = node;
  while (current !== null && current.left !== null) {
    current = current.left;
  }
  return current;
}

max() {
  return this.maxNode(this.root);
}

maxNode(node) {
  let current = node;
  while (current !== null && current.right !== null) {
    current = current.right;
  }
  return current;
}

Misol: Minimal va maksimal qiymatlarni topish


console.log(bst.min().key); // Natija: 3
console.log(bst.max().key); // Natija: 25

Binar Qidiruv Daraxtlarining Amaliy Qo'llanilishi

Binar Qidiruv Daraxtlari turli xil dasturlarda qo'llaniladi, jumladan:

Ishlash Samaradorligi Masalalari

BQD'ning ishlash samaradorligi uning tuzilishiga bog'liq. Eng yaxshi holatda, muvozanatlangan BQD qo'shish, qidirish va o'chirish amallari uchun logarifmik vaqt murakkabligini ta'minlaydi. Biroq, eng yomon holatda (masalan, qiyshiq daraxt), vaqt murakkabligi chiziqli vaqtga tushishi mumkin.

Muvozanatlangan va Muvozanatlanmagan Daraxtlar

Muvozanatlangan BQD - bu har bir tugunning chap va o'ng quyi daraxtlari balandligi ko'pi bilan birga farq qiladigan daraxtdir. O'z-o'zini muvozanatlovchi algoritmlar, masalan AVL daraxtlari va Qizil-qora daraxtlar, daraxtning muvozanatli bo'lishini ta'minlaydi va barqaror ishlashni kafolatlaydi. Turli mintaqalar serverdagi yuklamaga qarab turli optimallashtirish darajalarini talab qilishi mumkin; muvozanatlash yuqori global foydalanish sharoitida ishlash samaradorligini saqlashga yordam beradi.

Vaqt Murakkabligi

BQD'ning Ilg'or Tushunchalari

O'z-o'zini Muvozanatlovchi Daraxtlar

O'z-o'zini muvozanatlovchi daraxtlar - bu muvozanatni saqlash uchun o'z tuzilishini avtomatik ravishda sozlaydigan BQD'lardir. Bu daraxt balandligining logarifmik bo'lib qolishini ta'minlaydi, bu esa barcha operatsiyalar uchun barqaror ishlashni kafolatlaydi. Keng tarqalgan o'z-o'zini muvozanatlovchi daraxtlarga AVL daraxtlari va Qizil-qora daraxtlar kiradi.

AVL Daraxtlari

AVL daraxtlari har qanday tugunning chap va o'ng quyi daraxtlari orasidagi balandlik farqi ko'pi bilan bir bo'lishini ta'minlash orqali muvozanatni saqlaydi. Bu muvozanat buzilganda, muvozanatni tiklash uchun aylantirishlar amalga oshiriladi.

Qizil-Qora Daraxtlar

Qizil-qora daraxtlar muvozanatni saqlash uchun rang xususiyatlaridan (qizil yoki qora) foydalanadi. Ular AVL daraxtlariga qaraganda murakkabroq, ammo ba'zi holatlarda yaxshiroq ishlash samaradorligini taklif qiladi.

JavaScript Kod Misoli: Binar Qidiruv Daraxtining To'liq Implementatsiyasi


class Node {
  constructor(key) {
    this.key = key;
    this.left = null;
    this.right = null;
  }
}

class BinarySearchTree {
  constructor() {
    this.root = null;
  }

  insert(key) {
    const newNode = new Node(key);

    if (this.root === null) {
      this.root = newNode;
    } else {
      this.insertNode(this.root, newNode);
    }
  }

  insertNode(node, newNode) {
    if (newNode.key < node.key) {
      if (node.left === null) {
        node.left = newNode;
      } else {
        this.insertNode(node.left, newNode);
      }
    } else {
      if (node.right === null) {
        node.right = newNode;
      } else {
        this.insertNode(node.right, newNode);
      }
    }
  }

  search(key) {
    return this.searchNode(this.root, key);
  }

  searchNode(node, key) {
    if (node === null) {
      return false;
    }

    if (key < node.key) {
      return this.searchNode(node.left, key);
    } else if (key > node.key) {
      return this.searchNode(node.right, key);
    } else {
      return true;
    }
  }

  remove(key) {
    this.root = this.removeNode(this.root, key);
  }

  removeNode(node, key) {
    if (node === null) {
      return null;
    }

    if (key < node.key) {
      node.left = this.removeNode(node.left, key);
      return node;
    } else if (key > node.key) {
      node.right = this.removeNode(node.right, key);
      return node;
    } else {
      // kalit node.key ga teng

      // 1-holat - barg tugun
      if (node.left === null && node.right === null) {
        node = null;
        return node;
      }

      // 2-holat - tugunning faqat 1 ta bolasi bor
      if (node.left === null) {
        node = node.right;
        return node;
      } else if (node.right === null) {
        node = node.left;
        return node;
      }

      // 3-holat - tugunning 2 ta bolasi bor
      const aux = this.findMinNode(node.right);
      node.key = aux.key;
      node.right = this.removeNode(node.right, aux.key);
      return node;
    }
  }

  findMinNode(node) {
    let current = node;
    while (current != null && current.left != null) {
      current = current.left;
    }
    return current;
  }

  min() {
    return this.minNode(this.root);
  }

  minNode(node) {
    let current = node;
    while (current !== null && current.left !== null) {
      current = current.left;
    }
    return current;
  }

  max() {
    return this.maxNode(this.root);
  }

  maxNode(node) {
    let current = node;
    while (current !== null && current.right !== null) {
      current = current.right;
    }
    return current;
  }

  inOrderTraverse(callback) {
    this.inOrderTraverseNode(this.root, callback);
  }

  inOrderTraverseNode(node, callback) {
    if (node !== null) {
      this.inOrderTraverseNode(node.left, callback);
      callback(node.key);
      this.inOrderTraverseNode(node.right, callback);
    }
  }

  preOrderTraverse(callback) {
    this.preOrderTraverseNode(this.root, callback);
  }

  preOrderTraverseNode(node, callback) {
    if (node !== null) {
      callback(node.key);
      this.preOrderTraverseNode(node.left, callback);
      this.preOrderTraverseNode(node.right, callback);
    }
  }

  postOrderTraverse(callback) {
    this.postOrderTraverseNode(this.root, callback);
  }

  postOrderTraverseNode(node, callback) {
    if (node !== null) {
      this.postOrderTraverseNode(node.left, callback);
      this.postOrderTraverseNode(node.right, callback);
      callback(node.key);
    }
  }
}

// Foydalanish misoli
const bst = new BinarySearchTree();
bst.insert(11);
bst.insert(7);
bst.insert(15);
bst.insert(5);
bst.insert(3);
bst.insert(9);
bst.insert(8);
bst.insert(10);
bst.insert(13);
bst.insert(12);
bst.insert(14);
bst.insert(20);
bst.insert(18);
bst.insert(25);

const printNode = (value) => console.log(value);

console.log("In-order (tartibli) aylanib o'tish:");
bst.inOrderTraverse(printNode);

console.log("Pre-order (oldindan) aylanib o'tish:");
bst.preOrderTraverse(printNode);

console.log("Post-order (keyin) aylanib o'tish:");
bst.postOrderTraverse(printNode);

console.log("Minimal qiymat:", bst.min().key);
console.log("Maksimal qiymat:", bst.max().key);

console.log("9 ni qidirish:", bst.search(9));
console.log("2 ni qidirish:", bst.search(2));

bst.remove(7);
console.log("7 ni o'chirgandan keyin qidirish:", bst.search(7));

Xulosa

Binar Qidiruv Daraxtlari ko'plab qo'llanilishga ega bo'lgan kuchli va ko'p qirrali ma'lumotlar tuzilmasidir. Ushbu qo'llanma BQD'lar haqida, ularning tuzilishi, operatsiyalari va JavaScript'da amalga oshirilishi haqida to'liq ma'lumot berdi. Ushbu qo'llanmada muhokama qilingan tamoyillar va texnikalarni tushunish orqali butun dunyodagi dasturchilar dasturiy ta'minotni ishlab chiqishda keng ko'lamli muammolarni hal qilish uchun BQD'lardan samarali foydalanishlari mumkin. Global ma'lumotlar bazalarini boshqarishdan tortib, qidiruv algoritmlarini optimallashtirishgacha, BQD haqidagi bilim har qanday dasturchi uchun bebaho boylikdir.

Kompyuter fanlari bo'yicha sayohatingizni davom ettirar ekansiz, o'z-o'zini muvozanatlovchi daraxtlar va ularning turli xil amalga oshirilishlari kabi ilg'or tushunchalarni o'rganish sizning tushunchangiz va imkoniyatlaringizni yanada oshiradi. Binar Qidiruv Daraxtlaridan samarali foydalanish san'atini o'zlashtirish uchun turli stsenariylar bilan amaliyot qilishni va tajriba o'tkazishni davom eting.