BAB 6 Binary Tree (Pohon Biner)
Sturucture FATHER INFO INFO INFO LEFT RIGHT LEFT RIGHT LEFT RIGHT
Sturucture INFO LEFT RIGHT atau typedef struct Node { int INFO; struct Node *LEFT; struct Node *RIGHT; }; typedef struct Node Simpul; typedef struct Node { struct Node *LEFT; int INFO; struct Node *RIGHT; }; typedef struct Node Simpul;
Sturucture INFO atau LEFT RIGHT typedef struct Node { int INFO; struct Node *LEFT; struct Node *RIGHT; }; typedef struct Node Simpul; typedef struct Node { struct Node *LEFT; int INFO; struct Node *RIGHT; }; typedef struct Node Simpul;
INFO FATHER LEFT RIGHT atau typedef struct Node { struct Node *FATHER; int INFO; struct Node *LEFT; struct Node *RIGHT; }; typedef struct Node Simpul; INFO LEFT RIGHT atau typedef struct Node { int INFO; struct Node *FATHER; struct Node *LEFT; struct Node *RIGHT; }; typedef struct Node Simpul;
6.1.1 Beberapa contoh pohon biner dengan kedalaman (depth) d = 3. root level A B C 1 D E F G 2 J K 3 Gambar-6.2 a Stricly Binary Tree
level A 1 2 3 B C D E J K Gambar-6.2 b Stricly Binary Tree
root Gambar-6.2 c Complete Binary Tree level 1 2 3 depth = 3 A B C D E 1 2 3 depth = 3 A B C D E F G H I J K L M N O Gambar-6.2 c Complete Binary Tree
Almost Complete Binary Tree root level A 1 2 3 B C D E F G H I J K L M N Gambar-6.2 d Almost Complete Binary Tree
6.2 Penomoran Simpul Pohon Biner 5 2n 2n+1 10 11
A 1 B C 3 2 1 D E F 2 4 5 7 G H I 3 10 11 14 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 A B C D E F G H I
6.4 Proses (Operasi) Pada Pohon Biner. 1. Insialisasi 2. Pembuatan sebuah simpul. 3. Pembuatan simpul akar 4. Penambahan (insert) simpul kedalam sebuah pohon 5. Penghapusan (delete) simpul dari sebuah pohon 6. Pembacaan / Penelusuran pohon biner
Mendeklarasikan struktur Simpul struct Node { struct Node *Left; char INFO; struct Node *Right; }; typedef struct Node Simpul; Simpul *Root, *P, *Q, *R; char X; INFO Left Right *Root *P *Q *R X Pointer Root digunakan khusus menunjuk simpul akar. Pointer P digunakan khusus menunjuk simpul yang baru dibuat Pointer Q, R digunakan sebagai pointer pembantu Pointer-pointer lain dapat ditambahkan bilamana diperlukan Selain itu dideklarasi juga sebuah variabel X bertipe sama dengan tipe INFO yaitu tipe : char
6.6. Pembuatan Sebuah Simpul Fungsi untuk Pembuatan Sebuah Simpul void BuatSimpul( char X) { P = (Simpul*) malloc(sizeof(Simpul)); if(P != NULL) { P->INFO = X; P->Left = NULL; P->Right = NULL; } else { printf(“Memory Heap Full”); exit(1); A
Instruksi Membuat Sebuah Simpul P = (Simpul*) malloc(sizeof(Simpul)); P
P P->INFO P->RIGHT P->LEFT
Mengisi P->INFO dengan data P->INFO = X; Misal variabel X Berisi nilai Karakter ‘A’ P A
Mengisi P->LEFT dan P->RIGHT Dengan NULL P->Left = NULL; P->Right = NULL; P A
6.7 Menjadikan Sebuah Simpul Sebagai Simpul Akar Suatu Pohon Fungsi untuk Menjadikan Sebuah Simpul Sebagai Simpul Akar void BuatSimpulAkar( ) { if(Root == NUL) { if(P != NULL) { Root = P; Root->Left = NULL; Root->Right = NULL; } else printf(“\n Simpul Belum Dibuat”); printf(“Pohon Sudah Ada”); Root P A
6.8 Menambahkan (Insert) Sebuah Simpul ke Pohon Yang Sudah Ada. 6.8.1 Insert urut nomor simpul atau insert level per level. P Root Root A A B P B
6.8 Menambahkan (Insert) Sebuah Simpul ke Pohon Yang Sudah Ada. 6.8.1 Insert urut nomor simpul atau insert level per level. P Root Root A A B P B Root->LEFT= P;
Root P Root A B P A B
Root P A B Root->RIGHT = P;
6.8.1 Insert urut nomor simpul atau insert level per level.
Root Root Root Root Root A A A A A B B C B C B C a b c D D E d e Root 1 A 1 A 1 A 1 A 1 B 2 B 2 C 3 B 2 C 3 B 2 C 3 a b 4 c D 4 D E 5 d e Root Root Root A 1 A 1 A 1 B 2 C 3 B 2 C 3 B 2 C 3 D 4 E 5 F 6 D 4 E 5 F 6 G 7 D 4 E F 6 G 7 5 f g H 8 h
*Q #include<stdio.h> #include<stdlib.h> int main() #include<conio.h> #include<ctype.h> #include<math.h> #include<malloc.h> struct Node { struct Node *Left; char INFO; struct Node *Right; }; typedef struct Node Simpul; Simpul *P, *Root, *Current; Simpul *Q[129]; int main() { int i, j, Flag; char X; clrscr(); Inisialisasi(); X = getche(); BuatSimpul(X); BuatSimpulAkar(); InsertSimpulUrutNomor(); BacaUrutNomor(); } 128 *Q
inisialisasi
InsertSimpulUrutNomor(); BacaUrutNomor(); } void Inisialisasi () int main() { int i, j, Flag; char X; clrscr(); Inisialisasi(); X = getche(); BuatSimpul(X); BuatSimpulAkar(); InsertSimpulUrutNomor(); BacaUrutNomor(); } void Inisialisasi () { Root = NULL; P = NULL; } Root P
input pertama kali Buat Simpul dan dijadikan Simpul Akar
P A int main() { int i, j, Flag; char X; clrscr(); Inisialisasi(); X = getche(); BuatSimpul(X); BuatSimpulAkar(); InsertSimpulUrutNomor(); BacaUrutNomor(); } void BuatSimpul( char X) { P = (Simpul…………………); P->INFO = X; P->Left = NULL; P->Right = NULL; } P A
P A int main() { int i, j, Flag; char X; clrscr(); Inisialisasi(); X = getche(); BuatSimpul(X); BuatSimpulAkar(); InsertSimpulUrutNomor(); BacaUrutNomor(); } void BuatSimpulAkar( ) { Root = P; Root->Left = NULL; Root->Right = NULL; } Root P A
Insert di Root->Left input data kedua dan Insert di Root->Left
- P A int main() { int i, j, Flag; char X; clrscr(); Inisialisasi(); void InsertUrutNomor() { int i, j, Flag; char X; Flag = 0; i=1; j=1; Q[i] = Root; while(Flag == 0 && j < 127) { X = getche(); i++; } int main() { int i, j, Flag; char X; clrscr(); Inisialisasi(); X = getche(); BuatSimpul(X); BuatSimpulAkar(); InsertSimpulUrutNomor(); BacaUrutNomor(); } - Root P A
- void InsertUrutNomor() { int i, j, Flag; char X; Flag = 0; i=1; j=1; Q[i] = Root; while(Flag == 0 && j < 127) { X = getche(); i++; } { X = getche(); if(X != '0') { BuatSimpul(X); Current = Q[i]; Current->Left = P; j++; Q[j] = P; } else { // data habis Flag = 1; j++; Q[j] = NULL; if(Flag == 0) Current->Right = P; i++; -
Q - i void InsertUrutNomor() { int i, j, Flag; char X; Flag = 0; i=1; j=1; Q[i] = Root; j i 1 2 3 4 5 6 7 while(Flag == 0 && j < 127) { X = getche(); i++; } Q n 2n 2n+1 - Disini berisi alamat simpul Akar (Root) Disini berisi alamat simpul no 5 Root
- void InsertUrutNomor() { int i, j, Flag; char X; Flag = 0; i=1; j=1; Q[i] = Root; while(Flag == 0 && j < 127) { X = getche(); i++; } { X = getche(); if(X != '0') { BuatSimpul(X); Current = Q[i]; Current->Left = P; j++; Q[j] = P; } else { // data habis Flag = 1; j++; Q[j] = NULL; if(Flag == 0) Current->Right = P; i++; -
{ X = getche(); if(X != '0') { BuatSimpul(X); Current = Q[i]; Current->Left = P; j++; Q[j] = P; } else { // data habis Flag = 1; j++; Q[j] = NULL; Input data untuk diinsert di Q->Left if(Flag == 0) { X = getche(); if(X != '0') { BuatSimpul(X); Current = Q[i]; Current->Right = P; j++; Q[j] = P; } else { // data habis Flag = 1; j++; Q[j] = NULL; Input data untuk diinsert di Q->Right i++;
Q A P B Root Current i { X = getche(); if(X != '0') { BuatSimpul(X); Input data ke-dua dan Insert di Current->Left { X = getche(); if(X != '0') { BuatSimpul(X); Current = Q[i]; Current->Left = P; j++; Q[j] = P; } else { // data habis Flag = 1; j++; Q[j] = NULL; Current A 1 P Sekarang Current masih sama dengan Root B 2 i j 1 2 3 4 5 6 7 Q Root P Root Current
Q A P B C Root Current i if(Flag == 0) { X = getche(); if(X != '0') { BuatSimpul(X); Current = Q[i]; Current->Right = P; j++; Q[j] = P; } else { // data habis Flag = 1; j++; Q[j] = NULL; Root Input data ke-tiga dan Insert di Current->Right Current A 1 P Sekarang Current masih sama dengan Root B C 3 2 i j 1 2 3 4 5 6 7 Q Root No.2 P Root Current
Q A P - B C I++ Root Current i void InsertUrutNomor() { int i, j, Flag; char X; Flag = 0; i=1; j=1; Q[i] = Root; while(Flag == 0 && j < 127) { X = getche(); i++; } Root Current A 1 Sudah selesai insert dua simpul P - B C 3 2 i j I++ 1 2 3 4 5 6 7 Q Root No.2 P Root Current
Q A P - B C I++ Root Current i void InsertUrutNomor() { int i, j, Flag; char X; Flag = 0; i=1; j=1; Q[i] = Root; while(Flag == 0 && j < 127) { X = getche(); i++; } Root Current A 1 P - B C 3 2 i j I++ 1 2 3 4 5 6 7 Q Root No.2 P Root Current
Q A B C P C Root Current i { X = getche(); if(X != '0') Input data ke-4 { X = getche(); if(X != '0') { BuatSimpul(X); Current = Q[i]; Current->Left = P; j++; Q[j] = P; } else { // data habis Flag = 1; j++; Q[j] = NULL; Current Pindah Nunjuk Simpul No. 2 A 1 Current kemudian data ke-4 dan Insert di Current-> Left B C 3 2 P C 4 i j 1 2 3 4 5 6 7 Q Root No.2 P
void Inisialisasi () { Root = NULL; P = NULL; } void BuatSimpul(char X) { } void BuatSimpulAkar( ) { lihat contoh sebelumnya void InsertSimpulUrutNomor() void BacaUrutNomor() int main() { int i, j, Flag; char X; clrscr(); Inisialisasi(); X = getche(); BuatSimpul(X); BuatSimpulAkar(); InsertSimpulUrutNomor(); BacaUrutNomor(); }
void BuatSimpul( char X) { P = (Simpul*) malloc(sizeof(Simpul)); if(P != NULL) { P->INFO = X; P->Left = NULL; P->Right = NULL; } else { printf(“Memory Heap Full”); exit(1);
void BacaUrutNomor() { int i,j,n,Counter; i=1; j=1; n=1; Counter=0; printf(“\n”); Q[I] = Root; while(Q[i] != NULL) { Current = Q[i]; printf("%c ", Current->INFO); Counter++; if(Counter == n) { printf(“\n”); Counter=0; n = n*2; } j++; Q[j] = Current->Left; j++; Q[j] = Current->Right; i++;
void BacaUrutNomor() { int i, j, n, Counter; char X; i=1; j=1; n=1; Counter=0; printf(“\n”); while(Q[i] != NULL) { Current = Q[i]; printf("%c ", Current->INFO); Counter++; if(Counter == n) { printf(“\n”); Counter=0; n = n*2; } i++;
E K D I B C G N O A H 1 3 4 5 F M L 6 J P Q 7 2
6.8.2 Insert Simpul Pada Nomor Simpul Tertentu.
Root 1 A 2 B C 3 D E F G 4 5 6 7 8 H I K 12 L M N O 9 P Q S V W X Y Z 16 19 25 a 50
Root F 1 A 6 F = Nilai INFO C 3 6 F L 12 6 = nomor simpul Y 25 a 50
F 6 6 = nomor simpul F = Nilai INFO Root 1 A kanan C 3 kiri 6 F kiri L 12 Q kanan 6 = nomor simpul Y 25 kiri a 50
F 6 6 = nomor simpul F = Nilai INFO Root 1 A 1 C 3 6 F 12 L Q 1 Y 25 6 F 12 L Q 1 6 = nomor simpul Y 25 50 a
Root 4 3 2 1 -1 1 Top 1 A 1 C 3 1 6 F 12 L Q S 1 Y 25 50 a
n = 50; Top = -1; hasil = n; while(hasil > 1) { sisa = n % 2; n = n/2; Top++; S[Top] = sisa; } 4 3 2 1 -1 1 Top 1 S
n = 50; Top = -1; hasil = n; while(hasil > 1) { sisa = n % 2; n = n/2; Top++; S[Top] = sisa; } 4 3 2 1 -1 1 Top 50 / 2 = 25 sisa 0 simpan 0 1 25 / 2 = 12 sisa 1 simpan 1 12 / 2 = 6 sisa 0 simpan 0 S 6 / 2 = 3 sisa 0 simpan 0 3 / 2 = 1 sisa 1 simpan 1 Selesai bila hasil = 1
Q = Root; while(Top > 0 ) { arah = S[Top]; Top--; if(arah = 0 ) Q = Q->Left; else Q = Q->Right; } arah = S[0]; // Top pasti = 0 if(arah == 0 ) Q->Left = P; { printf(“\n Ada kesalahan”); printf(“\n unt.simpul no.50”); printf(“\n harus insert kiri”);
Q = Root; while(Top > 0 && Q != NULL) { arah = S[Top]; Top--; if(arah == 0 ) Q = Q->Left; else Q = Q->Right; } if(Q != NULL) { arah = S[0]; if(arah == 0 ) Q->Left = P; else { printf(“\n Ada kesalahan”); printf(“\n unt.simpul no.50”); printf(“\n harus insert kiri”); } printf( “Simpul Tak Bisa Diinsert” );
E D F B C G A H Root h 1 2 3 4 5 6 7 8 g f e a b c d 204
while(Top > 0 && Q != NULL) { arah = S[Top]; Top--; if(arah == 0 ) Perhatikan langkah-langkah dalam usaha menempatkan pointer Q menunjuk simpul no. 25 (bila ada) 1 Top S 4 3 2 A C F L 6 12 Root Q Keadaan awal. Q menunjuk Root, Top menunjuk S[4] Q = Root; while(Top > 0 && Q != NULL) { arah = S[Top]; Top--; if(arah == 0 ) Q = Q->Left; else Q = Q->Right; } Program-b 1 Top S 4 3 2 A C F L 6 12 Root Q 1 Top S 4 3 2 A C F L 6 12 Root Q Bila simpul no.3 tidak ada, maka Q = NULL, sehingga keluar dari loop, walaupun Top belum menunjuk S[0]. Bila simpul no. 6 tidak ada, maka Q = NULL, sehingga keluar dari loop, walaupun Top belum menunjuk S[0]. 1 Top S 4 3 2 A C F L 6 12 Root Q 25 1 Top S 4 3 2 A C F L 6 12 Root Q Bila simpul no.12 tidak ada, maka Q = NULL, sehingga keluar dari loop, walaupun Top belum menunjuk S[0]. Sampai disini, bila : Simpul no.25 tidak ditemukan Maka : Q = NULL, walaupun Top menunjuk S[0] 210
Contoh-6.8.2.d Berusaha menginsert sebuah simpul baru menjadi Simpul no. 50. Insert dibatalkan bila : Simpul no no.25 atau simpul-simpul sebelum no.25 tidak ada, dan cetak perkataan “Simpul Tak Bisa Diinsert”, “Simpul Superordinatnya Tidak Ada “, atau b. Simpul no.50 sudah ada, dan cetak perkataan “ Simpul no.50 Sudah Ada “. Langkah-1. (Bagian-1) Menentukan langkah untuk menuju simpul no.50 yaitu : 1 – 0 – 0 – 1 - 0 dan simpan ke Stack S. A C F L Y a 1 3 6 12 25 50 Q Root n = 50; Top = -1; hasil = n; while(hasil > 1) { sisa = n % 2; n = n/2; Top++; S[Top] = sisa; } 1 Top S Gambar-6.17 b 4 3 2 Gambar-6.17 a Langkah-2 atau Program Bagian-2. (sambungan Bagian-1). Q = Root; while(Top > 0 && Q != NULL) { arah = S[Top]; Top--; if(arah == 0 ) Q = Q->Left; else Q = Q->Right; } A C F L a 1 3 6 12 25 50 Q Root Gambar-6.19 if(Q == NULL) { printf( “ Simpul Tak Bisa Diinsert “ ); printf( “ Simpul Superordinatnya Tidak Ada” ); } else { //Q pasti != NULL & tentunya Top pasti = 0 arah = S[0]; if(arah == 0 ) { if(Q->Left != NULL) printf(“Simpul no.50 Sudah Ada”); else Q->Left = P; else { printf(“\n Ada kesalahan program”); printf(“\n Untuk Simpul No. 50 “); printf(“\n Seharusnya isi S[0]=0”); 211
6.10 Membaca Pohon Biner. 6.10.1 Membaca Pohon Biner level per level urut nomor simpul. 6.10.2 Membaca atau mencari sebuah simpul dengan nomor tertentu. 6.10.1 Membaca Pohon Biner level per level urut nomor simpul. Perhatikan pohon biner yang diilustrasikan pada empat buah gambar berikut ini : E K D I B C G N O A H 1 2 3 4 5 F M L 6 J P Q 7 Gambar-6.24 a E K D I B C G N A 1 2 3 4 5 J 7 Gambar-6.24 b E K B C G N A 1 2 3 5 F M 6 J 7 Gambar-6.24 c E K B C A 1 2 3 5 J Gambar-6.24 d Pohon –pohon biner diatas, bila dibaca dan dicetak simpul per simpul, dengan pembacaan level per level urut nomor simpul maka : Untuk pohon pada : Gambar-6.24 a Gambar-6.24 b Gambar-6.24 c Gambar-6.24 d Akan tercetak : A B C D E F G H I J K L M N O P Q A B C D E G I J K N A B C E F G J K M N A B C E J K Untuk keperluan algoritma, maka diperlukan sebuah array (biasanya diberi nama Q) bertipe pointer Simpul, untuk mencatat alamat simpul-simpul. Sebagai contoh, untuk pohon biner yang diilustrasikan dengan Gambar-6.24 d, maka alamat simpul-simpulnya tersimpan dalam array pointer seperti yang digambarkan pada Gambar-6.25. Catatan : &A maksudnya alamat simpul A, \0 untuk menyatakan NULL 1 2 3 4 5 6 7 8 9 10 11 12 Q &A &B &C \0 &E \0 \0 \0 \0 &J &K \0 Gambar-6.25 217
#include<stdio.h> #include<malloc.h> #include<conio.h> struct Node { struct Node *Left; char INFO; struct Node *Right; }; typedef struct Node Simpul; Simpul *Q[50]; Simpul *Current, *Akar, *P; int i,j; char X; - disini membuat pohon binernya ( tidak dibahas ). // mencetak isi simpul-simpul pohon biner for(i=0; i<=49; i++) { Q[i] = NULL; } Q[0] = Akar; i=0; j=0; while(Q[i] != NULL) { Current = Q[i]; printf("%c ", Current->INFO); if(Current->Left != NULL) { j++; Q[j] = Current->Left; } if(Current->Right != NULL) Q[j] = Current->Right; i++; Menyiapkan array Q Bertipe Pointer untuk menunjuk Simpul Disini membuat simpul-simpul pohon biner. Bagaimana membuat pohon biner sudah diterangkan sebelumnya. Mengisi seluruh elemen array Q dengan NULL. Untuk pertama kali, alamat simpul akar disimpan di Q[0]. Alamat simpul akar pasti bukan NULL. Apakah simpul subpohon kiri ada ? Menyimpan alamat simpul subpohon kiri (kalau ada) ke dalam array Q Menyimpan alamat simpul subpohon kanan (kalau ada) ke dalam array Q Algoritma mencetak simpul level per level urut nompor simpul 218
//trilvl2.cpp #include<stdio.h> #include<malloc.h> #include<conio.h> struct Node { struct Node *Left; char INFO; struct Node *Right; }; typedef struct Node Simpul; Simpul *Q[50], *Current, *Akar, *P; int i,j; char X; void Inisialisasi() { Akar = NULL; P = NULL; } void BuatSimpul(char X) { P = (Simpul*) malloc(sizeof(Simpul)); if(P !=NULL) { P->INFO = X; P->Left = NULL; P->Right = NULL; else printf("Simpul Tak Bis Dibuat "); void BuatAkar() { if (Akar == NULL) { if(P != NULL) {Akar = P; } { printf("Simpul Belum Ada"); } else { printf("Akar Sudah Ada "); } void main() { Inisialisasi(); BuatSimpul('A'); BuatAkar(); BuatSimpul('B'); Akar->Left = P; BuatSimpul('C'); Akar->Right = P; BuatSimpul('G'); Akar->Right->Right = P; BuatSimpul('E'); Akar->Left->Right = P; BuatSimpul('F'); Akar->Right->Left = P; BuatSimpul('L'); Akar->Right->Left->Left = P; BuatSimpul('M'); Akar->Right->Left->Right = P; for(i=0;i<=49;i++) { Q[i] = NULL; } Q[0] = Akar; i=0; j=0; while(Q[i] != NULL) { Current = Q[i]; printf("%c ", Current->INFO); if(Current->Left != NULL) { j++; Q[j] = Current->Left; } if(Current->Right != NULL) { j++; Q[j] = Current->Right; } i++; Ketik dan RUN program ini untuk melihat hasil pembacaan simpul pohon biner level per level urut nomor simpul. Instruksi-instruksi untuk meng-insert simpul sengaja dibuat secara ‘manual’ hanya untuk memudahkan membuat pohon. Meng-insert simpul secara ‘program’ dapat dilihat pada contoh sebelumnya. Gambar pohon yang dibuat secara ‘manual’ oleh program ini M A C B E L G F Akar Instruksi-instruksi membuat atau menginsert simpul-simpul pohon secara ‘manual’ Cara seperti ini tidak berlaku umum. Digunakan disini hanya untuk memudahkan membuat pohon seperti pada gambar diatas. Program ini akan membuat Pohon sepert diatas, Dan mencetak level per level sehingga tercetak ; A B C E F G L M 219
Membaca Pohon Biner level per level urut nomor pada pohon yang menggunakan pointer link pada level yang sama. Algoritma mencetak simpul level per level sama dengan menginsert simpul level per level sebagai berikut : A Root LastKiri B C D E Current F P G H I J K L Q Gambar-6.24 b LastKiri Q A Root B C D E Current F P G H I J K L Gambar-6.24 a Pertama kali pointer Q dan LastKiri ditempatkan menunjuk simpul Akar (Gambar-6-24 a). Pointer Q akan mengunjungi simpul satu persatu mulai simpul A, B, C, D dan seterusnya dengan instruksi Q = Q->LEFT untuk turun ke level berikutnya, dan kemudian Q= Q->LINK untuk berjalan ke kanan sampai Q->LINK == NULL. Fungsi untuk membaca simpul level per level void BacaPerLevel() { Q = Root; LastKiri = Root; printf("%c ", Q->INFO ); while(Q->Left != NULL) { Q = Q->Left; LastKiri = LastKiri->Left; printf("%c ",Q->INFO); while(Q->Link != NULL) { Q = Q->Link; } Q = LastKiri; void BacaPerLevel() { Q = Root; LastKiri = Root; printf("%c ", Q->INFO ); while(Q->Left != NULL) { printf("\n"); Q = Q->Left; LastKiri = LastKiri->Left; printf("%c ",Q->INFO); while(Q->Link != NULL) { Q = Q->Link; } Q = LastKiri; Program-1 Program-2 Bila pohon seperti Gambar-6.24 a atau Gambar-6.24 b, dicetak : Dengan : Program-1 akan mencetak : A B C D E F G H I J K L Dengan :Program-2 akan mencetak : A B C D E F G H I J K L E J K D F M B C G A H V W Catatan : Program diatas tidak bisa digunakan untuk mencetak pohon yang no. simpulnya tidak urut seperti Gambar-6.25 Gambar-6.25 220
Bentuk Program selengkapnya. Membaca pohon biner level per level Bila Program ini dijalankan, maka akan terbentuk pohon seperti yang diilustrasikan pada Gambar-6.26 //Membuat pohon dengan insert level per level #include<stdio.h> #include<stdlib.h> #include<conio.h> #include<ctype.h> #include<math.h> struct Node { struct Node *Left; char INFO; struct Node *Right; struct Node *Link; }; typedef struct Node Simpul; Simpul *P,*Q, *Root, Simpul *LastCurrent, *Current, *LastKiri ; const kiri = 0, kanan = 1; int i, n, Flag, FlagHabis, Level; char X, A[26] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; void Inisialisasi () { } void BuatSimpul(char X) void BuatSimpulAkar( ) void InsertSimpulPerLevel() void BacaPerLevel() int main() clrscr(); i=0; X=A[i]; Inisialisasi(); BuatSimpul(X); BuatSimpulAkar(X); for(i=1; i<=25; i++) { X=A[i]; InsertSimpulPerLevel(); printf(“\n”); BacaPerLevel(); return(0); Semua variabel, dibuat dan digunakan secara bersifat Global Untuk memudahkan pengetesan program, data yang akan diisikan ke simpul pohon, disiapkan berupa array sehingga tidak perlu diketik setiap kali melakukan pengetesan. Jumlah data dapat ditambah atau dikurangi sesuai keperluan Lengkapi semua fungsi sesuai dengan yang telah diuraikan sebelumnya Kalau program ini dijalankan (setelah melengkapi fungsi-fungsi yang diperlukan), maka dalam memory akan terbentuk pohon biner sebagai berikut : M Z L X Y N F G O C I R S H Q J T U D E K V W B A P Gambar-6.26 Tentu saja pohon ini tidak terlihat atau tergambar di layar, karena pohon adanya di dalam memory komputer, dalam bentuk Linked-List. Setelah dicetak dengan fungsi BacaPerLevel( ), maka yang tercetak dan terlihat dilayar adalah : A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 221
6.10.2 Membaca atau mencari sebuah simpul dengan nomor tertentu. Contoh-1: Sudah ada sebuah pohon biner. Strujtur simpul sama seperti yang dicontohkan dalam bab ini. Jumlah simpul dan kedalaman pohon tidak diketahui. Simpul akar ditunjuk oleh pointer Root. Sudah tersedia pointer P, Q, dan R yang dapat menunjuk alamat sebuah simpul, dapat digunakan bila diperlukan. Susun algoritma untuk : Memeriksa apakah simpul dengan nomor 50 ada terdapat dalam pohon tersebut. Bila ada, cetak perkataan “ADA’”, bila tidak ada, cetak perkataan “TIDAK ADA”. Jawab : Program terdiri dari 2 tahap. A C F L Y a 1 3 6 12 25 50 Q Root Gambar- a Tahap-1 : Menentukan alur pencarian untuk menuju simpul no 50. Alurnya adalah : kanan - kiri – kiri - kanan – kiri (lihat Gambar- a) Bila kanan dinyatakan dengan 1, dan kiri dengan 0, maka alurnya menjadi : 1 – 0 – 0 – 1 – 0 Dan menyimpan nilai tersebut kedalam Stack S. (lihat Gambar b) 1 Top S Gambar- b 4 3 2 Tahap-2 : Berdasarkan nilai yang ada dalam Stack. S, pohon ditelusuri mulai dari simpul akar. Bila simpul no 50 ada, maka cetak perkataan “ADA, sebaliknya cetak perkataan “TIDAK ADA”. // Tahap-1. n = 50; Top = -1; hasil = n; while(hasil > 1) { sisa = n % 2; n = n/2; Top++; S[Top] = sisa; } Bagi terus menerus 50 dengan 2. Sisa pembagian simpan di Stack S. Proses selesai bila hasil sudah = 1. 50 / 2 = 25 sisa = 0 25 / 2 = 12 1 12 / 2 = 6 0 6 / 2 = 3 0 3 / 2 = 1 1 // Tahap-2. Q = Root; while(Top >= 0 && Q != NULL) { arah = S[Top]; Top--; if(arah == 0 ) Q = Q->Left; else Q = Q->Right; } if (Q != NULL) printf(“ADA”); Else printf(“TIDAK ADA”); hasil Keluar dari Loop bila : Top == -1 atau Q == NULL. Bila Q == NULL berarti, simpul no 50, atau no. 25, atau no. 12 , atau no. 6 atau no. 3, atau no. 1 tidak ada. 222
6.11 Penelusuran Pohon Biner. Penelusuran (traverse atau traversal ) pohon biner, maksudnya membaca atau mengunjungi (visit) simpul-simpul pohon biner dengan urutan tertentu. Ada 3 (tiga) macam penelusuran, yang bila ditambah dengan kebalikannya menjadi 6 (enam) macam penelusuran sebagai berikut : 1. Preorder (atau depth-first order) 4. Inverse Preorder 2. Inorder (atau symetric order) 5. Inverse Inorder 3. Postorder 6. Inverse Postorder Untuk memahami istilah Pre, Post, In, order diatas, pandanglah sebuah pohon atau subpohon sebagai berikut : B A + Gambar-6.27 a Pohon pada Gambar-6.27 a Bila ditelusuri secara maka hasil penelusurannya: Preorder + A B (bentuk PREFIX) Inorder A + B (bentuk INFIX) Postorder A B + (bentuk POSTFIX) Pohon pada Gambar-6.27 a diatas, sebenarnya adalah hasil representasi arithmatic statement : A + B ke dalam pohon biner. Dalam arithmetic statement A + B, A dan B disebut operand dan tanda tambah (+) disebut operator. Bentuk A + B ini biasa disebut bentuk INFIX, yang artinya operatornya berada didalam (IN). Selain bentuk INFIX, komputer mengenal bentuk PREFIX seperti + A B, dimana operatornya berada sebelum (PRE) dua buah operand, dan bentuk POSTFIX seperti A B + dimana operatornya berada sesudah (POST) dua buah operand. Tapi sebuah pohon biner belum tentu merupakan representasi arithmetic statement, seperti yang diilustrasikan paga Gambar-6-27 b C B A Gambar-6.27 b Pohon pada Gambar-6.27 b Bila ditelusuri secara maka hasil penelusurannya: Preorder A B C Inorder B A C Postorder B C A Karena bukan merupakan arithmetic statement, jadi tidak diistilahkan dengan bentuk INFIX, PREFIX dan POSTFIX Dari dua ilustrasi diatas, dapat dilihat sebagai berikut: Untuk penelusuran Preorder, urutannya adalah : Ambil Akar, kemudian telusuri secara preorder subpohon kiri, dan setelah selesai penelusuran ke subpohon kiri, kemudian dilanjutkan dengan penelusuran secara preorder ke subpohon kanan. Jadi penelusurannya sendiri bersifat recursive. Dalam buku literatur, untuk penelusursn preorder ditulis : 1. Visit the root. 2. Traverse the left subtree in preorder. 3. Traverse the right subtree in preorder 223
6.11.1 Beberapa contoh pohon biner dan hasil penelusurannya : Untuk penelusuran inorder : Untuk penelusuran Postorder 1. Traverse the left subtree in preorder. 1. Traverse the left subtree in postorder 2. Visit the root. 2. Traverse the right subtree in postorder 3. Traverse the right subtree in preorder 3. Visit the root. Agar mudah diingat, prosesnya ketiganya dapat disingkat sebagai berikut : Untuk Preorder, ---> AKAR, KIRI, KANAN Untuk Inorder, ----> KIRI, AKAR, KANAN Untuk Postorder, --> KIRI, KANAN, AKAR 6.11.1 Beberapa contoh pohon biner dan hasil penelusurannya : C F B E A D Preorder : A Inorder : A Postorder: A Gambar-6.28 a Gambar-6.28 b Gambar-6.28c Preorder : A B Inorder : B A Postorder: B A Preorder : A B C Inorder : B A C Postorder: B C A Pre : A B D E C F In : D B E A F C Post: D E B F C A Gambar-6.28d E J K D F M B C G A H V W E J K D F M B C G A H Gambar-6.28 e Gambar-6.28 f Pre : A B D H E J K C F M G In : H D B J E K A F M C G Post: H D J K E B M F G C A Pre : A B D H E J K V W C F M G In : H D B J E V K W A F M C G Post: H D J V W K E B M F G C A Lihat Gambar-6.28 f Untuk Preorder : Akar, Kiri, Kanan : A Akar Kiri Kanan B D H E J K V W C F M G Sehingga didapat hasil penelusuran preorder : A B D H E J K V W C F M G 224
Untuk Inorder : Kiri, Akar, Kanan : Gambar-6.28 f digambarkan ulang E J K D F M B C G A H V W Gambar-6.28 f Hasil penelusuran Pre : A B D H E J K V W C F M G In : H D B J E V K W A F M C G Post: H D J V W K E B M F G C A Lihat Gambar-6.28f Untuk Inorder : Kiri, Akar, Kanan : A Akar Kiri Kanan B H D E J V K W C F M G Sehingga didapat hasil penelusuran inorder : H D B J E V K W A F M C G Lihat Gambar-6.28 f Untuk Postorder : Kiri, Kanan, Akar : A Akar Kiri Kanan B H D E J V W K C M F G Sehingga didapat hasil penelusuran postorder : H D J V W K E B M F G C A M Z L X Y N F G O C I R S H Q J T U D E K V W B A P Gambar-6.29 Hasil penelusuran untuk pohon Gambar-6.29 Preorder : A B D HPQ IRS E JTU KVW C F LXY MZ GNO Inorder : PHQ D RIS B TJU E VKW A XLY F ZM C NGO Postorder: PQH RSI D TUJ VWK E B XYL ZM F NOG C A 225
6.11.2 Program (Fungsi) Penelusuran Pohon Biner Hanya ada 3 (tiga) macam penelusuran yang akan dibahas, yaitu Preorder, Inorder, dan Postorder. Algoritma penelusuran ditulis dalam sebuah fungsi. Fungsi dapat bersifat recursive atau non recursive. 1) Fungsi yang bersifat recursive a. Fungsi Penelusuran Preorder. Ingat : Akar, Kiri, Kanan void PreOrder(Simpul *T) { if(T != NULL) { printf("%c ", T->INFO); PreOrder(T->Left); PreOrder(T->Right); } Fungsi ini akan dipanggil dari program induk atau fungsi main( ) dengan instruksi : Preorder(Root); b. Fungsi Penelusuran Inorder. Ingat : Kiri, Akar, Kanan void InOrder(Simpul *T) { if(T != NULL) { InOrder(T->Left); printf("%c ", T->INFO); InOrder(T->Right); } Fungsi ini akan dipanggil dari program induk atau fungsi main() dengan instruksi : Inorder(Root); c. Fungsi Penelusuran Postorder. Ingat : Kiri, Kanan, Akar. void PostOrder(Simpul *T) { if(T != NULL) { PostOrder(T->Left); PostOrder(T->Right); printf("%c ", T->INFO); } Fungsi ini akan dipanggil dari program induk atau fungsi main() dengan instruksi : Postorder(Root); Perhatikan : 1. Walaupun diusahakan selalu menggunakan variabel Global, agar mudah dipahami, namun ketiga fungsi diatas, semuanya menggunakan variabel Lokal T. Hal ini tidak dapat dihindari karena fungsi bersifat recursive. 2. Setiap simpul yang dikunjungi, nilai INFOnya selalu dicetak agar terlihat dilayar urutan simpul yang dikunjungi. Gunakan ketiga fungsi diatas, sebagai pengganti fungsi BacaPerLevel( ), pada program yang dicontohkan sebelumnya maka akan terlihat hasil penelusuran pohon Gambar-6.25 sebagai berikut : Preorder : A B D H P Q I R S E J T U K V W C F L X Y M Z G N O Inorder : P H Q D R I S B T J U E V K W A X L Y F Z M C N G O Postorder: P Q H R S I D T U J V W K E B X Y L Z M F N O G C A 226
2) Fungsi yang bersifat non recursive Proses disini menggunakan Stack, untuk menyimpan alamat simpul simpul yang telah dikunjunggi. Alamat ini penting untuk disimpan agar dapat kembali menuju Akar atau simpul yang ada di ‘atas’ nya. Besarnya Stack tergantung kebutuhan yang lebih dikaitkan dengan ketinggian atau kedalaman pohon. Karena digunakan untuk menyimpan alamat, maka tipe Stack adalah tipe pointer (menggunakan bintang (*) ) yakni pointer yang menunjuk suatu Simpul. a. Fungsi untuk Penelusuran Preorder non recursive. void PreOrderNonRec(Simpul *T) { int top, X; Simpul *S[20]; Simpul *P; top = -1; P = T; do { while(P != NULL) { X = P->INFO; printf(“%c “, X); top++; S[top] = P; P = P->Left; } if(top > -1) { P = S[top]; top --; P = P->Right; while((top > -1) || (P != NULL)); Fungsi ini akan dipanggil dari program induk atau fungsi main( ) dengan instruksi : PreOrderNonRec(Root); Perhatikan instruksi : Simpul *S[20] Instruksi ini menyiapkan array satu dimensi bernama S sebanyak 20 elemen bertipe pointer (pakai *) dimana pointer tersebut dapat mencatat alamat obyek berstruktur Simpul. b. Fungsi Penelusuran Inorder non recursive. void InOrderNonRec(Simpul *T) { int top, X; Simpul *S[20]; Simpul *P; top = -1; P = T; do { while(P != NULL) { top++; S[top] = P; P = P->Left; } if(top > -1) { P = S[top]; top --; X = P->INFO; printf(“%c “, X); P = P->Right; while((top > -1) || (P != NULL)); Fungsi ini akan dipanggil dari program induk atau fungsi main( ) dengan instruksi : InOrderNonRec(Root); 227
6.12 Pohon Biner Berbenang (Threaded Binary Tree). Pohon biner berbenang (threaded binary tree) adalah pohon biner dimana semua pointer yang bernilai NULL dibuat menjadi benang (thread). Untuk pohon biner dengan jumlah simpul = n, maka akan terdapat pointer benang sebanyak 2n. Jumlah pointer yang bernilai null ada sebanyak n+1, lebih banyak dari pointer yang bukan null (busur) yang jumlahnya = n-1. Untuk pohon biner, semua simpul daun akan mempunyai dua buah benang, benang-kiri dan benang kanan, sedangkan simpul lain mungkin mempunyai salah satu benang, benang-kiri atau benang-kanan, dan sebagian simpul tidak mempunyai benang. Pointer null dibuat menjadi benang karena memang ada gunanya. Benang digunakan untuk menujuk simpul ‘diatas’nya dalam urutan penelusuran inorder. Perhatikan pohon biner berbenang pada Gambar-6-30 berikut ini, dimana benang digambarkan dengan garis putus-putus tipis. D H I B E J K R S A C F G Head Root Catatan : Pengertian simpul successor menurut urutan Inorder, dapat diterangkan menggunakan Gambar-6.30. Bila berada di simpul R, maka successor inorder adalah simpul I. Bila berada di simpul I, maka successor inorder adalah simpul S. Bila berada di simpul S, maka successor inorder adalah simpul B Gambar-6.30 Perhatikan aturan pembuatan benang setiap simpul. Untuk keperluan pemrograman, maka dibuatkan sebuah simpul Kepala yang ditunjuk oleh pointer Head. Head->Left dibuat menunjuk akar, sedangkan Head->Right menunjuk simpul Kepala itu sendiri.. Ada dua benang yang khusus menuju ke simpul kepala yanitu benang-kiri simpul paling kiri, dan benang-kanan simpul paling kanan. Bila simpul kepala tidak ada, maka kedua benang ini menunjuk ke simpul akar. Pohon biner pada Gambar-6-30 diatas, bila ditelusuri secara INORDER, maka urutannya adalah : H D R I S B J E A K F C G Pandanglah urutan penelusuran Inorder dari H ke D, atau dari R ke I atau dari S ke B, semuanya dapat dilakukan dengan cepat melalui benang-kanan, tanpa harus melakukan proses secara recursive. Jadi kalau hanya untuk keperluan penelusuran inorder, yang diperlukan hanyalah benang-kanan. Atau dengan perkataan lain, setiap simpul yang mempunyai benang-kanan berarti benang tersebut adalah merupakan jalur untuk penelusuran inorder untuk mencapai akar. 228
6.12.1 Struktur Pohon Biner Berbenang Sekarang timbul persoalan, bagaimana membedakan pointer yang keluar dari sebuah simpul, apakah berfungsi sebagai busur penghubung dua buah simpul, atau berfungsi sebagai benang. Untuk itu dibuat dua buah elemen dalam simpul tersebut yang isinya berupa tanda atau yang dalam pemrograman biasa disebut flag. Sebut saja namanya FlagKiri dan FlagKanan. Bila FlagKiri berisi 0 (nol) maka pointer-kiri (Left) berfungsi sebagai busur atau null, tapi bila isinya = 1 (satu) maka pointer-kiri berfungsi sebagai benang. Demikian juga dengan FlagKanan untuk pointer-kanan Dalam bahas C/C++, struktur simpulnya dapat ditulis sebagai berikut : Struktur Simpul Pohon biner berbenang. struct Node { char INFO; int FlagKiri, FlagKanan; struct Node *Right struct Node *Left; }; typedef struct Node Simpul; INFO Flag Kiri Kanan Left Right void BuatSimpul( char X) {P = (Simpul*) malloc (sizeof(Simpul)); if(P != NULL) { P->INFO = X; P->Left = NULL; P->Right = NULL; P->FlagKiri = 0; P->FlagKanan = 0; } else { printf(“Memory Heap Full”); exit(1); } Dan setiap kali pembuatan sebuah simpul baru, Bila simpul baru tersebut ditunjuk oleh pointer P, maka perlu ditambahkan instruksi : P->FlagKiri = 0; P->FlagKanan = 0; Seperti yang dicontohkan diatas. Dengan demikian pohon biner berbenang yang digambarkan pada Gambar 6-30 dapat digambarkan lebih jelas dengan Gambar-6.31 sebagai berikut. A B C F 1 D H I R S Head Root Gambar-6.31 229
6.12.2 Penelusuran INORDER Pohon Biner Berbenang Dengan memanfaatkan benang-kanan untuk kembali ke simpul succesor secara inorder, maka penelusuran secara INORDER non recursive dapat dibuat tanpa menggunakan Stack sebagai berikut : Prosedur Penelusuran INORDER non recursive, pada pohon biner berbenang B D 1 E G H h T = Head C F A void InOrderBenang(Simpul *T) { Simpul *Q, *R; Q = T; do { R = Q->Right; if(Q->FlagKanan == 0) { while(R->FlagKiri == 0) { R = R->Left; } } Q = R; if(Q != T) printf("%c ", Q->INFO); while(Q != T); Gambar-6.32 Procedeure ini dipanggil dari program utama dengan instruksi InOrderBenang(Head); Bila Pohon pada Gambar-6.32 ditelusuri dengan prosedur ini akan menghasilkan cetakan : D B G E H A F C yaitu hasil penelusuran secara Inorder. Pohon Gambar-6.28 adalah pohon yang dibuat secara sembarang, tanpa aturan tertentu. Cara membuatnya hanya dengan instruksi-instruksi dasar sebagai berikut : Penggalan program membuat Pohon Biner Berbenang sembarang seperti Gambar-6.32 BuatSimpul('A'); BuatSimpulAkar(); BuatSimpul('h'); BuatSimpulHead(); BuatSimpul('B'); Akar->Left = P; BuatSimpul('C'); Akar->Right = P; P->Right = Head; P->FlagKanan = 1; BuatSimpul('D'); Akar->Left->Left = P; P->Left = Head; P->FlagKiri = 1; P->Right = Akar->Left; P->FlagKanan = 1; BuatSimpul('E'); Akar->Left->Right = P; Q = P; BuatSimpul('F'); Akar->Right->Left = P; P->Left = Akar; P->Right = Akar->Right; P->FlagKiri = 1; P->FlagKanan = 1; BuatSimpul('G'); Q->Left = P; P->Left = Akar->Left; P->Right = Q; BuatSimpul('H'); Q->Right = P; P->Left = Q; P->Right = Akar; Pembuatan pohon dila-kukan secara ‘manual’ , satu per satu hanya untuk digunakan seba-gai contoh. Tentu saja pembuatan sebenarnya secara terprogram, sa-ma dengan pembuatan pohon level per level dengan menambahkan benang. 230
6.13. Contoh Program 16.13.1 Program membuat pohon biner dengan insert level per level //Membuat dan menelusuri pohon biner dengan insert level per level //atree05.cpp #include<stdio.h> #include<stdlib.h> #include<conio.h> #include<ctype.h> #include<math.h> struct Node { struct Node *Left; char INFO; struct Node *Right; struct Node *Link; }; typedef struct Node Simpul; Simpul *P,*Q, *Akar, *LastCurrent, *Current, *LastKiri ; const int kiri = 0, kanan = 1; int i, n, Flag, FlagHabis, Level; char X, A[35] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ12345678"; void Inisialisasi () { Akar = NULL; } void BuatSimpul(char item) { P = (Simpul*) malloc(sizeof(Simpul)); if(P !=NULL) { P->INFO = item; P->Left = NULL; P->Right = NULL; P->Link = NULL; else { printf("Memory Penuh"); exit(1); void BuatSimpulAkar( ) { if(Akar == NULL) { Akar = P; LastCurrent = Akar; LastKiri = Akar; Flag = kiri; Level = 0; n = 1; FlagHabis = 1; else { printf("Pohon Sudah ada"); exit(1); } 1 kiri kanan INFO Left Right Link P Simpul baru dibuat kiri 1 Flag Level n FlagHabis INFO Left Right Link P Akar LastCurrent LastKiri Simpul yang baru dibuat dijadikan sebagai simpul Akar Program bersambug ke-halam berikutnya Catatan : Flag = kiri, kalau ada insert, akan diinsert di bagian kiri FlagHabis = 1, jumlah simpul pada level tersebut sudah habis, kalau ada insert, dilanjutkan ke level berikutnya, dan kemudian FlagHabis dibuat = 0. n = 1, jumlah simpul , Level = 0 sekarang sedang ada di level 0 231
A P B A P B C 232 void TambahSimpul() {if(Akar != NULL) { n=n+1; if(FlagHabis == 1) { FlagHabis = 0; Current = P; LastCurrent->Left = P; Flag = kanan; Level = Level + 1; } else {if(Flag == kiri) { Flag = kanan; Current->Link = P; {LastCurrent->Right = P; Flag = kiri; if( n == (pow(2,Level+1)- 1)) { FlagHabis = 1; LastCurrent = LastKiri->Left; LastKiri = LastKiri->Left; {Current->Link = P; LastCurrent = LastCurrent->Link; printf(“Pohon Belum Ada "); void PreOrder(Simpul *T) { if(T != NULL) { printf("%c ", T->INFO); PreOrder(T->Left); PreOrder(T->Right); void InOrder(Simpul *T) { InOrder(T->Left); printf("%c ", T->INFO); InOrder(T->Right); 4 5 6 7 2 3 1 Akar 8 9 10 11 12 13 14 15 1 FlagHabis Menginsert simpul paling kiri dalam suatu level, misal simpul no-2, atau no-4, atau no-8 Menginsert simpul sebelah kiri, tapi bukan yang paling kiri, misal simpul no-6, atau no-10, atau no-12, atau no-14 Menginsert simpul sebelah kanan, termasuk yang paling kanan, seperti simpul no-3, atau no-5 atau no-7, atau no-9, atau no-11 dan seterusnya. Bila yang diinsert adalah simpul yang paling kanan dari suatu level, maka : FlagHabis dibuat = 1, dan LastCurrent dibuat menunjuk simpul paling kiri pada level tersebut. A Link Root LastCurrent LastKiri P B Current 1 n = 2 level = 1 FlagHabis = 0 Flag = kanan 2 Keadaan setelah insert Simpul no-2 A Root LastCurrent LastKiri P B Current C n = 3 FlagHabis = 1 Flag = kiri level = 2 1 2 3 Keadaan setelah insert Simpul no-3 232
A B C P D A B C D E P A B C D E P F 233 void PostOrder(Simpul *T) { if(T != NULL) { PostOrder(T->Left); PostOrder(T->Right); printf("%c ", T->INFO); } void BacaPerLevel() { Q = Akar; LastKiri = Akar; printf("%c ", Q->INFO ); while(Q->Left != NULL) { printf("\n"); Q = Q->Left; LastKiri = LastKiri->Left; printf("%c ",Q->INFO); while(Q->Link != NULL) { Q = Q->Link; Q = LastKiri; int main() { clrscr(); i=0; X=A[i]; Inisialisasi(); BuatSimpul(X); BuatSimpulAkar(X); for(i=1; i<=25; i++) { X=A[i]; TambahSimpul(); PreOrder(Akar); printf("\n"); InOrder(Akar); PostOrder(Akar); BacaPerLevel(); getch(); return(0); A Root LastCurrent LastKiri B C P D Current n = 4 FlagHabis = 0 Flag = kanan level = 2 Keadaan setelah insert Simpul no-4 A Root LastCurrent LastKiri B C D E Current P Keadaan setelah insert Simpul no-5 A Root LastCurrent LastKiri B C D E Current P F Keadaan setelah insert Simpul no-7 233
6.13.2 Program membuat pohon biner berbenang //Membuat dan menelusuri pohon biner berbenang //Benang.cpp #include<stdio.h> #include<conio.h> #include<math.h> struct Node { char INFO; int FlagKiri, FlagKanan; struct Node *Right; struct Node *Left; }; typedef struct Node Simpul; Simpul *P,*Q, *Akar, *Head; void Inisialisasi () { Akar = NULL; Head = NULL; } void BuatSimpul(char X) { P = (Simpul*) malloc(sizeof(Simpul)); if(P !=NULL) { P->INFO = X; P->Left = NULL; P->Right = NULL; P->FlagKiri = 0; P->FlagKanan = 0; else { printf("Memory Penuh"); exit(1); void BuatSimpulAkar( ) { if(Akar == NULL) { Akar = P; Akar->INFO = 'A'; else { printf("Akar Sudah ada"); void BuatSimpulHead( ) { if(Head == NULL) { Head = P; Head->Left = Akar; Head->Right = Head; else { printf("Head Sudah ada"); INFO Flag Kiri Kanan Left Right X B D 1 E G H h Head C F A Akar Gambar-6.33 234
void InOrderBenang(Simpul *T) { Simpul *Q, *R; Q = T; do { R = Q->Right; if(Q->FlagKanan == 0) { while(R->FlagKiri == 0) { R = R->Left; } } Q = R; if(Q != T) printf("%c ", Q->INFO); while(Q != T); int main() { clrscr(); Inisialisasi(); BuatSimpul('A'); BuatSimpulAkar(); BuatSimpul('h'); BuatSimpulHead(); BuatSimpul('B'); Akar->Left = P; BuatSimpul('C'); Akar->Right = P; P->Right = Head; P->FlagKanan = 1; BuatSimpul('D'); Akar->Left->Left = P; P->Left = Head; P->FlagKiri = 1; P->Right = Akar->Left; P->FlagKanan = 1; BuatSimpul('E'); Akar->Left->Right = P; Q = P; BuatSimpul('F'); Akar->Right->Left = P; P->Left = Akar; P->Right = Akar->Right; P->FlagKiri = 1; P->FlagKanan = 1; BuatSimpul('G'); Q->Left = P; P->Left = Akar->Left; P->Right = Q; BuatSimpul('H'); Q->Right = P; P->Left = Q; P->Right = Akar; printf("\n"); InOrderBenang(Head); getch(); return(0); B D 1 E G H h T = Head C F A Gambar-6.34 Catatan : Pembuatan simpul-simpul dilakukan secara manual untuk memudahkan pem-buatan contoh. 235
6.14. Soal-Soal Latihan Mandiri. Untuk semua soal yang berkaitan dengan algoritma, maka dinyatakan bahwa simpul akar pohon biner yang dijadikan soal, telah ditunjuk oleh pointer Root. 1. Sebuah pohon biner kedalamnya = 10. E G H D F I B C A Gambar-6.34 Ditanya : a. Jumlah maksimum simpul pada level 10. b. Jumlah minimum simpul pada level 10. c. Jumlah maksimum seluruh simpul d. Jumlah minimum seluruh simpul 2. Sebuah pohon biner mempunyai jumlah simpul = 125. Ditanya : a. Kedalaman maksimum pohon tersebut. b. Kedalaman minimum pohon tersebut. 3. Perhatikan pohon biner Gambar-6.34 diatas. Sebutkan nomor simpul yang isi INFOnya adalah huruf “ I ”. 4. Simpan pohon biner Gambar-6.34 diatas ke dalam array satu dimensi. 5. Diketahui sebuah array satu dimensi yang dibuat dengan char A[15]; Sudah ada isinya sebagai berikut : A B C D E F G 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 Gambarkan Pohon Biner-nya bila array satu dimensi diatas direpresentasikan kedalam sebuah pohon biner tersbut 6. Sebuah pohon biner kedalamanya = 7. Berapa paling sedikit elemen array yang perlu disiapkan agar dapat menampung isi pohon biner tersebut. 7. Pada sebuah pohon biner. Bila kita bergerak mulai dari simpul Akar dengan arah gerakan sebagai berikut : kanan, kiri, kanan, kiri, kiri Maka kita akan sampai pada simpul nomor berapa ? Gambar-6.35 E D H B C G A Root F I 8. Pada sebuah pohon biner. Sebutkan arah gerakan (kiri / kanan) bila bergerak mulai dari simpul Akar menuju simpul no. 100. 9. Tuliskan hasil penelusuran pohon biner pada Gambar-6.35 bila ditelusuri atau dibaca dengan cara : a. Penelusuran Level per level b. Penelusuran inorder c. Penelusuran preorder d. Penelusuran postorder 236
Gambarkan pohon biner tersebut yang : 10. Tuliskan penggalan program (atau fungsi) untuk membaca atau menelusuri sebuah pohon biner tanpa proses recursive bila ditelusuri secara : a. Level per level b. inorder c. preorder 11. Sebuah pohon biner, field INFOnya bertipe integer. Tuliskan penggalan program (atau fungsi) untuk mencetak TOTAL isi INFO. 12. Tuliskan penggalan program (atau fungsi) untuk mencetak JUMLAH simpul sebuah pohon biner. 13. Sauatu pohon biner, INFOnya bertipe int. Tuliskan penggalan program (atau fungsi) untuk mencetak nilai INFO yang terbesar. 14. Sauatu pohon biner, INFOnya bertipe int. Tuliskan penggalan program (atau fungsi) untuk mencetak nilai INFO simpul yang berada pada ujung paling kanan. 15. Tuliskan penggalan program (atau fungsi) untuk mencetak nomor simpul yang paling besar (paling tinggi). 16. Tuliskan penggalan program (atau fungsi) untuk mencetak kedalaman sebuah pohon biner. 17 Ada banyak pohon biner yang bila ditelusuri dengan cara preorder, hasilnya sebagai berikut : A B C D E F G H Gambarkan pohon biner tersebut yang : Gambar-6.36 E D H B C G A Root F I Mempunyai kedalam minimum. Mempunyai kedalam maximum 18. Gambarkan pohon biner berbenang untuk pohon biner yang digambar pada Gambar-6.36. 19. Tuliskan penggalan program (atau fungsi) untuk memeriksa apakah simpul no 100 ada dalam sebuah pohon biner. Bila ada cetak perkataan “ADA”, sebaliknya cetak perkataan “TIDAK ADA”. 20. Sudah ada sebuah simpul baru yang ditunjuk oleh pointer P. Tuliskan penggalan program (atau fungsi) untuk menginsert simpul tersebut sebagai simpul no 100, bila dipastikan simpul no 100 belum ada, tapi simpul nomor 50 sudah ada. 21. Sudah ada sebuah simpul baru yang ditunjuk oleh pointer P. Tuliskan penggalan program (atau fungsi) untuk menginsert simpul tersebut sebagai simpul no 100, bilamana memungkinkan. Bila tidak mungkin dapat diinsert, maka cetak perkataan “TIDAK DAPAT DIINSERT”. Tidak dapat diinsert bila simpul superordinat dari simpul nomor 100 tidak ada, atau simpul nomor 100 itu sendiri sudah ada. 237
22. Sudah ada pohon biner seperti yang diilustrasikan pada Gambar-6-37. Susun algoritma untuk membaca dan mencetak isi seluruh simpul sehingga tercetak sebagai berikut : E J K D F M B C G A H V W Gambar-6-37 A B D H E J K V W C F H G 23. Susun algoritma untuk membuat pohon biner untuk menyimpan kalimat : “JAKARTA RAYA INDONESIA“ sehingga terrbuat pohon seperti Gambar-6-38. A I T N K R E O S Y J D Gambar-6.38 24. Sudah ada pohon biner INFOnya bertipe char. Susun algoritma untuk mencetak INFO seluruh simpul daun. Bila pohonnya seperti pada Gambar 6-37 diatas, maka seharusnya tercetak : H J V W M G 25. Sudah ada dua buah pohon biner. Akar pohon biner pertama ditunjuk oleh pointer Root1. Akar pohon biner kedua ditunjuk oleh pointer Root2. Susun program untuk memeriksa apakah pohon biner pertama tepat sama dengan pohon biner kedua. Yang dimaksud dengan tepat sama disini adalah jumlah dan tata letak simpulnya sama, bukan isi INFOnya. Bila tepat sama cetak perkataan “SAMA”, sebaliknya cetak perkataan “TIDAK SAMA “. Ilustrasi : Pohon pada Gambar-6-39 , tepat sama dengan pohon pada Gambar 6-40, walaupun isinya tidak sama, tapi jumlah simpul dan tata letak simpul sama. Sedangkan pohon pada Gambar-6.39 tidak “tepat sama “ dengan pohon pada Gambar-6.41 E J K D F M B C G A H T X Y S U Z Q R V P W E J D F M B C G A Gambar-6.39 Gambar-6.40 Gambar-6.41 238