Двоично дърво в структурата на данните (ПРИМЕР)
Какво е бинарно дърво?
Думата двоичен означава две. В дървовидната структура на данните „Двоично дърво“ означава дърво, където всеки възел може да има максимум два дъщерни възела (ляв и десен възел). Това е просто двоично дърво.
Има обаче друго двоично дърво, което се използва най-често и има няколко случая на употреба. Нарича се Двоично дърво за търсене (BST). Това дърво може да направи алгоритъма за търсене много по-бърз, точно log(n) времева сложност. В структурата на данните n означава броя на възлите в двоичното дърво.
Какви са разликите между двоично дърво и двоично дърво за търсене?
Разликата между BST и обикновеното двоично дърво е в това, че BST левият възел има по-малка стойност от основния възел, а десният възел има по-голяма стойност от основния възел. Така че лявото поддърво винаги ще съдържа по-малка стойност от корена, а дясното поддърво винаги ще съдържа по-голяма стойност от корена.
Пример за двоични дървета за търсене
Нека имаме следния пример за демонстриране на концепциите на ��воичното дърво за търсене.
Тук можете всички възли да следват дадената дисциплина. Има формула за максималния брой възли в двоичното дърво за търсене. Ако наблюдаваме горното дърво, можем да видим, че всеки възел има две деца, с изключение на всички листови възли. И височината (h) на даденото двоично дърво е 4. Формулата е 2h - 1. И така, дава 15.
Даденото по-горе изображение не е пълно двоично дърво или балансирано двоично дърво, нарича се пълно двоично дърво или балансирано двоично дърво. Има друга структура от данни, наречена AVL (друг тип двоично дърво), която оптимизира височината на двоичното дърво и извършва търсене по-бързо за BST, както е показано на фиг. 3.
Опитайте се да изчислите обхождането по ред на двоичното дърво, дадено по-горе. Ще откриете, че ще даде ненамаляващ сортиран масив, а алгоритмите за обхождане ще бъдат същите като при двоичното дърво.
Видове двоично дърво
Ето някои важни типове двоично дърво:
- Пълно двоично дърво: Всеки възел може да има 0 или 2 дъщерни възела в това двоично дърво. Само един дъщерен възел не е разрешен в този тип двоично дърво. Така че, с изключение на листовия възел, всички възли ще имат 2 деца.
- Пълно двоично дърво: Всеки възел може да има 0 или 2 възела. Изглежда като пълното двоично дърво, но всички листни елементи са наклонени към лявото поддърво, докато в пълното двоично дърво възелът може да бъде в дясното или лявото поддърво.
- Перфектно двоично дърво: Всички възли трябва да имат 0 или 2 възли и всички листови възли трябва да са на едно и също ниво или височина. Горният пример за пълна двоична дървовидна структура не е перфектно двоично дърво, тъй като възел 6 и възел 1,2,3 не са на една и съща височина. Но примерът на пълното двоично дърво е перфектно двоично дърво.
- Изродено двоично дърво: Всеки възел може да има само едно дете. Всички операции като търсене, вмъкване и изтриване отнемат O(N) време.
- Балансирано двоично дърво: Ето това двоично дърво, разликата във височината на лявото и дясното поддърво е най-много 1. Така че, докато добавяме или изтриваме възел, трябва отново да балансираме височината на дървото. Този тип самобалансирано двоично дърво се нарича AVL дърво.
Има три основни операции на BST. Те са обсъдени подробно по-долу.
Внедряване на двоично дърво в C и C++
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
struct Node
{
int value;
struct Node *left, *right;
}
struct Node *getEmptynode(int val)
{
struct Node *tempNode = (struct Node *)malloc(sizeof(struct Node));
tempNode->value = val;
tempNode->left = NULL;
tempNode->right = NULL;
return tempNode;
}
struct Node *successor(struct Node *node)
{
struct Node *present = node;
// going to the left most node
while (present != NULL && present->left != NULL)
{
present = present->left;
}
return present;
}
struct Node *insert(struct Node *node, int value)
{
if (node == NULL)
{
return getEmptynode(value);
}
if (value < node->value)
{
node->left = insert(node->left, value);
}
else
{
node->right = insert(node->right, value);
}
return node;
}
int searchInBST(struct Node *node, int value)
{
struct Node *current = node;
while (current->value != value)
{
if (current->value > value)
{
current = current->left;
}
else
{
current = current->right;
}
if (current == NULL)
{
return 0;
}
}
return 1;
}
void inorder(struct Node *root)
{
if (root != NULL)
{
inorder(root->left);
cout << root->value << " ";
inorder(root->right);
}
}
struct Node *deleteNode(struct Node *node, int value)
{
if (node == NULL)
{
return node;
}
if (value < node->value)
{
node->left = deleteNode(node->left, value);
}
else if (value > node->value)
{
node->right = deleteNode(node->right, value);
}
else
{
if (node->left == NULL)
{
struct Node *temp = node->right;
free(node);
return temp;
}
else if (node->right == NULL)
{
struct Node *temp = node->left;
free(node);
return temp;
}
struct Node *temp = successor(node->right);
node->value = temp->value;
node->right = deleteNode(node->right, temp->value);
}
return node;
}
int main()
{
struct Node *root = NULL;
root = insert(root, 8);
root = insert(root, 4);
root = insert(root, 12);
root = insert(root, 2);
root = insert(root, 6);
root = insert(root, 10);
root = insert(root, 14);
root = insert(root, 1);
root = insert(root, 3);
root = insert(root, 5);
root = insert(root, 7);
root = insert(root, 9);
root = insert(root, 11);
root = insert(root, 13);
root = insert(root, 15);
cout << "InOrder Traversal after inserting all nodes: " << endl;
inorder(root);
root = insert(root, -10);
cout << "\nInOrder Traversal after inserting -10 : " << endl;
inorder(root);
cout << "\nSearching -5 in the BST: " << searchInBST(root, -5) << endl;
cout << "Searching -10 in the BST: " << searchInBST(root, -10) << endl;
root = deleteNode(root,8);
cout<<"After deleting node 8, inorder traversal: "<<endl;
inorder(root);
root = deleteNode(root,-10);
cout<<"\nAfter deleting node -10, inorder traversal: "<<endl;
inorder(root);
}
Изход:
InOrder Traversal after inserting all nodes: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 InOrder Traversal after inserting -10 : 10 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Searching -5 in the BST: 0 Searching -10 in the BST: 1 After deleting node 8, inorder traversal: -10 1 2 3 4 5 6 7 9 10 11 12 13 14 15 After deleting node -10, inorder traversal: 1 2 3 4 5 6 7 9 10 11 12 13 14 15
Внедряване на двоично дърво в Python
class Node:
def __init__(self,value):
self.left = None
self.right = None
self.value = value
def insert(root,value):
if root == None:
return Node(value)
if value< root.value:
root.left = insert(root.left,value)
else:
root.right = insert(root.right,value)
return root
def searchInBST(root,value):
current = root
while current.value != value:
if current.value > value:
current = current.left
else:
current = current.right
if current == None:
return "Not found"
return "Found"
def inorder(root):
if root != None:
inorder(root.left)
print(root.value,end=" ")
inorder(root.right)
def successor(root):
present = root
while present != None and present.left != None:
present = present.left
return present
def deleteNode(root,value):
if root == None:
return root
if value < root.value:
root.left = deleteNode(root.left, value)
elif value>root.value:
root.right = deleteNode(root.right, value)
else:
if root.left == None:
temp = root.right
root = None
return temp
elif root.right == None:
temp = root.left
root = None
return temp
temp = successor(root.right)
root.value = temp.value
root.right = deleteNode(root.right, temp.value)
return root
root = Node(8)
root = insert(root, 4)
root = insert(root, 12)
root = insert(root, 2)
root = insert(root, 6)
root = insert(root, 10)
root = insert(root, 14)
root = insert(root, 1)
root = insert(root, 3)
root = insert(root, 5)
root = insert(root, 7)
root = insert(root, 9)
root = insert(root, 11)
root = insert(root, 13)
root = insert(root, 15)
print("InOrder Traversal after inserting all nodes: ")
inorder(root)
root = insert(root, -10)
print("\nInOrder Traversal after inserting -10 : ")
inorder(root)
print("\nSearching -5 in the BST: ",searchInBST(root, -5))
print("Searching -5 in the BST: ",searchInBST(root, -10))
root = deleteNode(root,8)
print("After deleting node 8, inorder traversal:")
inorder(root)
root = deleteNode(root,-10)
print("\nAfter deleting node -10, inorder traversal:")
inorder(root)
Изход:
InOrder Traversal after inserting all nodes 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 InOrder Traversal after inserting -10 : -10 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Searching -5 in the BST: Not found Searching -5 in the BST: Found After deleting node 8, inorder traversal: -10 1 2 3 4 5 6 7 9 10 11 12 13 14 15 After deleting node -10, inorder traversal: 1 2 3 4 5 6 7 9 10 11 12 13 14 15
Приложение на двоично дърво
Ето някои често срещани приложения на Binary Tree:
- Организиране на данни за възли в сортиран ред
- Използва се в обекти на карта и набор от възли в библиотеки на езици за програмиране.
- Търсене на елементи в структурите от данни
» Научете следващия ни урок за Алгоритъм за комбиниране







