Binary Search Tree
Binary search tree adalah suatu data struktur yang menyerupai
pohon. Dari kata binary, kita bisa menyimpulkan bahwa pohon tersebut hanya memiliki
maksimal 2 cabang.
Oleh karena itu, ia bukan merupakan tree karena tree bisa memiliki
lebih dari dua cabang. Ia pun juga berbeda dari binary tree biasa, yang kita
bisa lihat dari struktur kode insertion dan deletion yang nanti kita
aplikasikan.
Binary search tree ini harus kita kuasai terlebih dahulu sebelum
kita mengenal varian binary tree yang lebih banyak lagi, seperti AVL tree, Red Black Tree, dan
kawan-kawannya.
Gambar binary search tree:
Binary search tree memiliki struktur umum sebagai berikut:
struct Node{
int
value;
struct
Node* right;
struct
Node* left;
} typedef Node;
Node* head;
Ciri khas yang bisa kita lihat dari gambar di atas
adalah:
- Cabang kiri memiliki value yang lebih kecil daripada parentnya
- Cabang kanan memiliki value yang lebih besar daripada parentnya
Kita bisa melakukan operasi-operasi ini di dalam binary
tree:
- Insertion
- Deletion
- Searching
Perlu diingat, semua proses ini dilakukan dengan melakukan
recursion, karena hal tersebut akan sulit dilakukan jika kita memakai teknik pengulangan
biasa (for, while, do while).
Insertion di dalam binary search tree ini memiliki ciri khas
sebagai berikut:
- Jika value yang ingin kita insert lebih besar daripada parentnya, maka kita akan melangkah ke cabang kanan
- Jika value yang ingin kita insert lebih kecil daripada parentnya, maka kita akan melangkah ke cabang kiri
- Hal ini terus kita ulang hingga ketemu dengan node null.
Cara searching binary search tree dibagi menjadi 3:
=======================================
Semua teknik searching ini…
- Dimulai dari node paling atas terlebih dahulu
- Proses rekursif terus berjalan hingga ketemu null
- Dinamakan Depth-First-Search
=======================================
Inorder traversal:
- Kita Melangkah dari node parent ke cabang kiri
- print value dari node tersebut
- Lanjut melangkah ke cabang kanan
Preorder traversal:
- print value dari node tersebut
- Kita Melangkah ke cabang kiri
- Lanjut melangkah ke cabang kanan
Postorder traversal:
- Kita Melangkah ke cabang kiri
- Lanjut melangkah ke cabang kanan
- Terakhir, print value dari node tersebut
Deletion di dalam binary search tree ini memiliki ciri khas
sebagai berikut:
--- Proses awal sama seperti insertion---
- Jika value yang ingin kita insert lebih besar daripada parentnya, maka kita akan melangkah ke cabang kanan
- Jika value yang ingin kita insert lebih kecil daripada parentnya, maka kita akan melangkah ke cabang kiri
- Hal ini terus kita ulang hingga ketemu dengan value yang sama atau value yang kita cari tidak ada alias null.
--- Proses kedua dan jika valuenya ada---
- Tidak punya anak sama sekali: Tinggal hapus saja node tersebut.
- Dengan kondisi 1 anak saja: Kita copy value dari anak kiri atau kanan lalu menghapusnya.
- Dengan kondisi 2 anak:
- Langkah ke kiri sekali terlebih dahulu dan terus melangkah ke kanan sampai ketemu node null
- Langkah ke kanan sekali terlebih dahulu dan terus melangkah ke kiri sampai ketemu node null
- Setelah itu, kita tinggal copy value dari node tersebut, lalu kita menghapus node tersebut
Berikut adalah contoh implementasi binary search tree dalam bentuk
aplikasi sederhana:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Node{
char
name[100];
int age;
unsigned
long long int nameInASCII;
struct
Node* right;
struct
Node* left;
} typedef Node;
Node* head = NULL;
Node* temp = NULL;
unsigned long long int giveASCIILength(char nameNew[]){
int
index = 0;
unsigned
long long int asciiLength = 0;
for
(index; nameNew[index] != '\0'; index++){
asciiLength
+= nameNew[index];
}
return
asciiLength;
}
Node* oneNode(int ageNew, char nameNew[100]){
temp =
(Node*) malloc(sizeof(Node));
temp->age
= ageNew;
strcpy(temp->name,
nameNew);
temp->nameInASCII
= giveASCIILength(nameNew);
temp->left
= NULL;
temp->right
= NULL;
return
temp;
}
int tempNumber = 0;
unsigned long long int tempLongNumber = 0;
char tempSentence[100] = {};
int length = 0;
int age = 0;
char tempName[100] = {};
void printLine(char message[]){
printf("%s\n",
message);
}
int giveRangedNumber(int min, int max, char message[]){
do{
printf("%s
", message);
scanf("%i",
&tempNumber);
getchar();
}while(tempNumber
< min || tempNumber > max);
return
tempNumber;
}
char* giveRangedSentenceLength(int min, int max, char
message[]){
do{
printf("%s
", message);
scanf("%[^\n]",
tempSentence);
getchar();
length
= strlen(tempSentence);
}while(length
< min || length > max);
return
tempSentence;
}
void printContents(Node* node){
printLine("=========================");
printf("Name:
%s\n", node->name);
printf("ASCII
value: %llu\n", node->nameInASCII);
printf("Age:
%i\n", node->age);
printLine("=========================");
printLine("");
}
void inorderTraversal(Node* current){
if
(current != NULL){
inorderTraversal(current->left);
printContents(current);
inorderTraversal(current->right);
}
}
void preorderTraversal(Node* current){
if
(current != NULL){
printContents(current);
inorderTraversal(current->left);
inorderTraversal(current->right);
}
}
void postorderTraversal(Node* current){
if
(current != NULL){
inorderTraversal(current->left);
inorderTraversal(current->right);
printContents(current);
}
}
void searchOperations(){
int
choice = 0;
do{
system("cls");
printLine("Search
operation:");
printLine("1.
Inorder Traversal");
printLine("2.
Preorder Traversal");
printLine("3.
Postorder Traversal");
printLine("4.
Back");
printLine("If
there are no data to be displayed, it means that your content is still
empty!");
choice
= giveRangedNumber(1, 4, "Choose:");
if
(choice == 1){
inorderTraversal(head);
printLine("Done
searching!");
getchar();
}
else
if (choice == 2){
preorderTraversal(head);
printLine("Done
searching!");
getchar();
}
else
if (choice == 3){
postorderTraversal(head);
printLine("Done
searching!");
getchar();
}
}while(choice
!= 4);
}
Node* insertBST(Node* newNode, Node* curr){
if (head
== NULL){
head
= newNode;
return
head;
}
else if
(curr != NULL){
if
(newNode->nameInASCII < curr->nameInASCII){
curr->left
= insertBST(newNode, curr->left);
}
else
if (newNode->nameInASCII > curr->nameInASCII){
curr->right
= insertBST(newNode, curr->right);
}
else{
printLine("A
data has the same ASCII value. Cannot be inserted!");
}
}
else{
curr
= newNode;
}
return
curr;
}
Node* deleteData(Node* current, unsigned long long int
asciiValue){
if (head
== NULL){
printLine("We
cannot delete the data because the name does not exist!");
getchar();
return
NULL;
}
else if
(current == NULL){
printLine("We
could not find the data you requested! Try rechecking your spelling and type
again!");
getchar();
}
else if
(asciiValue < current->nameInASCII){
current->left
= deleteData(current->left, asciiValue);
}
else if
(asciiValue > current->nameInASCII){
current->right
= deleteData(current->right, asciiValue);
}
else{
//
Found the data!
if
(current->left == NULL && current->right == NULL){
//
No children at all
free(current);
return
NULL;
}
else
if (current->left == NULL){
//
if we want to traverse left-right but there is no value on the left
strcpy(current->name,
current->right->name);
current->nameInASCII
= current->right->nameInASCII;
current->age
= current->right->age;
free(current->right);
current->right
= NULL;
}
else{
temp
= current->left;
while(temp->right->right
!= NULL){
printf("Reached
here!");
temp
= temp->right;
}
strcpy(current->name,
temp->right->name);
current->nameInASCII
= temp->right->nameInASCII;
current->age
= temp->right->age;
free(temp->right);
temp->right
= NULL;
}
}
return
current;
}
void mainMenu(){
int
choice = 0;
do{
system("cls");
printLine("Welcome
to Binary Search Tree program!");
printLine("Please
choose what to do:");
printLine("1.
Insert data");
printLine("2.
Delete data");
printLine("3.
Search");
printLine("4.
Exit");
choice
= giveRangedNumber(1, 5, "Choose: ");
if
(choice == 1){
printLine("====This
will sort the data by ASCII values====");
age
= giveRangedNumber(1, 99, "Please enter the age[1-99]:");
strcpy(tempName,
giveRangedSentenceLength(10, 100, "Please enter the name
[10-100]:"));
head
= insertBST(oneNode(age, tempName), head);
printLine("Your
data has been inserted!");
getchar();
}
else
if (choice == 2){
strcpy(tempName,
giveRangedSentenceLength(10, 100, "Please enter the name to be
deleted[10-100]:"));
tempLongNumber
= giveASCIILength(tempName);
head
= deleteData(head, tempLongNumber);
}
else
if (choice == 3){
searchOperations();
}
else
if (choice == 4){
printLine("Thank
you for using my app! :) :) :)");
}
}while(choice
!= 4);
}
int main(){
mainMenu();
return
0;
}
Tips: jika anda ingin mengetahui benarnya program Anda berjalan, Anda bisa menggunakan opsi inorder traversal. Jika benar, Anda bisa lihat bahwa data ASCII value yang ditampilkan mulai dari paling rendah ke paling besar.
Worst case time complexity untuk binary search tree bisa mencapai jumlah height / ketinggiannya jika kondisi cabangnya menumpuk ke kiri atau ke kanan. Oleh
karena itu, kita akan membahas AVL tree agar kita bisa bermain dengan ketinggian
di tree agar mencapai time complexity minimal dalam blog mendatang.
Happy Coding!
Comments
Post a Comment