Buku 3: BAHAN AJAR

advertisement
UNIVERSITAS GADJAH MADA
JURUSAN ILMU KOMPUTER DAN ELEKTRONIKA
FAKULTAS MATEMATIKA DAN ILMU
PENGETAHUAN ALAM
Buku 3: BAHAN AJAR
ALGORITMA DAN STRUKTUR DATA II
Semester Ganjil/3 sks/MIK 2201
oleh
1. Drs. Janoe Hendarto, M.Kom.
2. Anifuddin Azis, S.Si., M.Kom.
Didanai dengan dana BOPTN P3-UGM
Tahun Anggaran 2013
November 2013
1
TINJAUAN MATA KULIAH
Matakuliah ini adalah matakuliah wajib inti dan merupakan lanjutan dari matakuliah
Algoritma dan Struktur Data I, matakuliah ini memberikan pengetahuan dan ketrampilan
kepada mahasiswa untuk melakukan analisa terhadap permasalahan, perancangan algoritma
dan menentukan struktur data yang tepat agar program komputer yang dihasilkan terstruktur
dan efisien.
Pada matakuliah Algoritma dan Struktur Data II ini, lebih menitik beratkan pada struktur
datanya, yaitu membahas macam-macam struktur data baik yang linear maupun yang nonlinear dan melihat kelebihan dan kekurangannya serta membahas contoh permasalahannya,
dan juga membahas paradigma pemrograman object oriented programming (OOP) yang
merupakan paradigma pemrograman baru yang dikembangkan dari fasilitas tipe data turunan
di dalam pemrograman terstruktur.
Object oriented di masa sekarang menjadi pilihan cara pemrograman yang sering
digunakan karena pendekatannya yang cenderung lebih deskriptif dan terorganisir dengan
baik. Hasilnya saat ini, banyak software-software yang lahir menggunakan prinsip OOP
sehingga membuat metode ini menjadi sebuah metode yang umum dalam dunia
pemrograman. Oleh sebab itu, OOP menjadi sebuah topik bahasan di dalam mata kuliah
algoritma dan struktur data untuk memberikan perkembangan teknologi pemrograman yang
teraktual kepada mahasiswa.
Tujuan Pembelajaran
: Memberikan bekal kepada mahasiswa agar dapat
melakukan perancangan dan pemilihan struktur data yang
sesuai, implementasi dan melakukan analisis secara umum
pada algoritma yang dibuat serta menguasai prinsip dasar
pemrograman OOP.
Luaran/outcome
:
1. Memiliki pengetahuan mengenai teori dan konsep
dasar algoritma dan struktur data.
2. Dapat menganalisis, merancang dan mengimplementasikan struktur data linear seperti linked
list, stack dan queue.
3. Dapat menganalisis, merancang dan mengimplementasikan struktur data non linear seperti
matriks, multiple linked list dan tree.
4. Memiliki pengetahuan mengenai algoritma
searching dan sorting serta dapat mengimplementasikan dalam program komputer.
2
5. Memiliki pengetahuan mengenai teori dan konsep
dasar Object Oriented Programming (OOP).
6. Dapat membangun program komputer berbasis
OOP.
Isi Materi :
BAB
I
II
III
IV
V
VI
VII
VIII
IX
Bahasan
Pengantar
1. Struktur data statis dan dinamis
2. Tipe data abstrak
Linked List linear
1. Definisi Linked List
2. Operasi pada linked list
3. Penggunaan linked list
4. Variasi linked list
Stack
1. Definisi Stack
2. Operasi pada stack
3. Implementasi stack
4. Aplikasi stack
Queue
1. Definisi queue
2. Operasi pada queue
3. Implementasi queue
4. Aplikasi queue
Struktur data non linear
1. Matriks, Array 2 Dimensi
2. Multiple linked list
Struktur data Tree
1. Konsep dan implementasi
2. BST
3. AVL
Algoritma Sorting
1. Merge Sort dan Quick Sort
2. Heap Sort
Algoritma Searching
1. Linear search dan Binary Search
2. Searching dengan fungsi hashing
Pengenalan OOP
1. Pengenalan Bahasa Pemrograman Java
2. Prinsip dasar OOP
3. Pengertian dan implementasi instance dalam Java
3
BAB I
PENGANTAR
Pendahuluan
Deskripsi Singkat
Pada bab ini akan dijelaskan struktur data statis dan dinamis serta tipe data abstrak
yang merupakan konsep dasar dari matakuliah ini.
Manfaat
Dengan memahami struktur data statis dan dinamis serta tipe data abstrak, mahasiswa
akan dapat memilih struktur data yang efisien dan sesuai dengan kebutuhan.
Relevansi
Materi ini menjadi dasar untuk mempelajari berbagai macam struktur data yang lebih
kompleks baik yang linear maupun non linear.
Learning Outcomes
Setelah mempelajari materi ini, mahasiswa memiliki pengetahuan tentang struktur
data statis, dinamis dan tipe data abstrak dan mampu membuat program menggunakan tipe
data array dan pointer untuk membangun struktur data linear.
Penyajian
1.1 Struktur Data Statis dan Dinamis
Struktur data dilihat dari kebutuhan memorynya dapat dikelompokan menjadi 2
macam yaitu struktur data statis dan dinamis, dimana


Struktur data statis : Struktur data yang kebutuhan/alokasi memorinya tetap (fixed
size), tidak dapat dikembangkan atau diciutkan, biasanya menggunakan tipe data
array
Struktur data dinamis : Struktur data yang kebutuhan memorynya sesuai data yang
ada, dimana dapat dikembangkan atau diciutkan sesuai dengan kebutuhan.
Pengelolaan alamat secara dinamis (dynamic address) dapat dilakukan dengan
menggunakan tipe data pointer.
Array adalah suatu struktur data statis yang terdiri dari sejumlah elemen yang memiliki tipe
data yang sama. Elemen-elemen array tersusun secara sekuensial dalam memori komputer.
Array dapat berupa satu dimensi, dua dimensi, tiga dimensi ataupun banyak dimensi (multi
dimensi).
Larikan dibentuk menggunakan Array Satu dimensi, yaitu tidak lain adalah kumpulan
elemen-elemen identik yang tersusun dalam satu baris. Elemen-elemen tersebut memiliki tipe
4
data yang sama, tetapi isi dari elemen tersebut bisa berbeda.
Elemen ke-
0
1
2
3
4
5
6
7
8
9
Nilai
23
34
32
12
25
14
23
12
11
10
Berikut contoh program mengisi larik X dengan bilangan random kemudian menentukan
maximum dan minimum.
#include<iostream>
#include<stdlib.h>
#include<conio.h>
using namespace std;
main() {
int i, n, max, min, x[100];
cout<<"masukkan banyak data : ";cin>>n;
srand((unsigned)time(NULL));
for (i=1;i<=n;i++) {
x[i]=rand()%100+1;
cout<<x[i]<<" ";
if (i%10==0) cout<<endl;
}
cout<<endl;
max=x[1];min=x[1];
for (i=2;i<=n;i++){
if (x[i]>max) max=x[i];
else if(x[i]<min) min=x[i];
}
cout<<"data max adalah : "<<max<<endl;
cout<<"data min adalah : "<<min<<endl;
}
Pemakaian array tidak selalu tepat untuk program-program terapan yang kebutuhan
pengingatnya selalu bertambah selama eksekusi program tersebut. Untuk itu diperlukan satu
tipe data yang dapat digunakan untuk mengalokasikan (membentuk) dan mendealokasikan
(menghapus) pengingat secara dinamis, yaitu sesuai dengan kebutuhan pada saat suatu
program dieksekusi. Oleh karena itu akan dijelaskan suatu tipe data yang dinamakan sebagai
tipe Data Pointer.
Nama peubah yang kita gunakan untuk mewakili suatu nilai data sebenarnya
merupakan / menunjukkan suatu lokasi tertentu dalam pengingat komputer di mana data yang
diwakili oleh tipe data tersebut disimpan. Pada saat sebuah program dikompilasi maka
5
compiler akan melihat pada bagian deklarasi peubah untuk mengetahui nama-nama peubah
apa saja yang digunakan, sekaligus mengalokasikan atau menyediakan tempat dalam memory
untuk menyimpan nilai data tersebut. Dari sini kita bisa melihat bahwa sebelum program
dieksekusi, maka lokasi-lokasi data dalam memory sudah ditentukan dan tidak dapat diubah
selama program tersebut dieksekusi. Peubah-peubah yang demikian itu dinamakan sebagai
Peubah Statis (Static Variable).
Dari pengertian diatas kita perhatikan bahwa sesudah suatu lokasi pengingat
ditentukan untuk suatu nama peubah maka dalam program tersebut peubah yang dimaksud
akan tetap menempati lokasi yang telah ditentukan dan tidak mungkin diubah. Dengan
melihat pada sifat-sifat peubah statis maka bisa dikatakan bahwa banyaknya data yang bisa
diolah adalah sangat terbatas. Misalnya peubah dalam bentuk Array yang dideklarasikan sbb :
int matriks[100][100], maka peubah tersebut hanya mampu menyimpan data sebanyak
100x100=10000 buah data. Jika kita tetap nekat memasukkan data pada peubah tersebut
setelah semua ruangnya penuh maka eksekusi program akan terhenti dan muncul error.
Memang kita dapat mengubah deklarasi program diatas dengan memperbesar ukurannya.
Tetapi jika setiap kali kita harus mengubah deklarasi dari tipe daa tersebut sementara,
banyaknya data tidak dapat ditentukan lebih dahulu, maka hal ini tentu merupakan pekerjaan
yang membosankan.
Sekarang bagaimana jika kita ingin mengolah data yang banyaknya kita tidak yakin
sebelumnya bahwa larik yang telah kita deklarasikan sebelumnya mampu menampung data
yang kita miliki ? Untuk menjawab pertanyaan di atas maka bahasa pemrograman
menyediakan satu fasilitas yang memungkinkan kita untuk menggunakan suatu peubah yang
disebut dengan Peubah Dinamis (Dynamic Variable). Peubah dinamis adalah peubah yang
dialokasikan hanya pada saat diperlukan, yaitu setelah program dieksekusi. Dengan kata lain,
pada saat program dikompilasi, lokasi
untuk peubah belum ditentukan sebagai peubah
dinamis. Hal ini membawa keuntungan pula, bahwa peubah-peubah dinamis tersebut dapat
dihapus pada saat program dieksekusi sehingga ukuran memory selalu berubah. Hal inilah
yang menyebabkan peubah tersebut dinamakan sebagai peubah dinamis.
Pada peubah statis, isi dari peubah adalah data sesungguhnya yang akan diolah. Pada
peubah dinamis nilai peubah adalah alamat lokasi lain yang menyimpan data sesungguhnya.
Dengan demikian data yang sesungguhnya tidak dapat dimasup secara langsung. Oleh karena
itu, peubah dinamis dikenal dengan sebutan POINTER yang artinya menunjuk ke sesuatu,
yang berisi adress/alamat dalam RAM.
6
Deklarasi variabel bertipe pointer :
tipe data *namavariabel;
Contoh : int *p
Maka variabel p menunjuk suatu alamat pada memori. Jika ada variabel A bertipe integer,
maka alamat variabel tersebut pada memori bisa diketahui dengan pernyataan &A. Variabel
pointer p, bisa menunjuk ke alamat variabel A, yaitu dengan pernyataan :
p = &A;
atau dengan memesan sendiri memory baru yaitu dengan perintah
p = new int;
Sedangkan untuk mengetahui isi dari variabel yang alamatnya ditunjuk oleh p, dengan
pernyataan *p;
Contoh Program menuliskan alamat dan nilai dari suatu variabel pointer :
#include<iostream>
using namespace std;
main(){
int a,*b;
a=10;
b=&a;
c=new int;
*c=25;
cout<<b<<" "<<*b<<" "<<c;
getchar();
}
1.2 Tipe Data Abstrak
Menurut Wikipedia, Tipe data abstrak (TDA) atau lebih dikenal dalam bahasa
Inggris sebagai Abstract data type (ADT) merupakan model matematika yang merujuk
pada sejumlah bentuk struktur data yang memiliki kegunaan atau perilaku yang serupa;
atau suatu tipe data dari suatu bahasa pemrograman yang memiliki semantik yang serupa.
Tipe data abstrak umumnya didefinisikan tidak secara langsung, melainkan hanya melalui
operasi matematis tertentu sehingga membutuhkan penggunaan tipe data tersebut meski
dengan resiko kompleksitas yang lebih tinggi atas operasi tersebut.
Dengan kata lain Tipe data abstrak (ADT) dapat didefinisikan sebagai model
matematika dari objek data yang menyempurnakan tipe data dengan cara mengaitkannya
dengan fungsi-fungsi yang beroprasi pada data yang bersangkutan. Merupakan hal yang
sangat penting untuk mengenali bahwa operasi-operasi yang akan dimanipulasi data pada
objek yang bersangkutan termuat dalam spesifikasi ADT. Sebagai contoh, ADT
HIMPUNAN didefinisikan sebagai koleksi data yang diakses oleh operasi-operasi
7
himpunan seperti penggabungan (UNION), irisan (INTERSECTION), dan selisih antarhimpunan (SET DIFFERENCE).
Implementasi dari ADT harus menyediakan cara tertentu untuk merepresentasikan
unsur tipe data (seperti matrix) dan cara untuk mengimplementasikan operasi -operasi
matrix. Secara tipikal, kita akan mendeskripsikan operasi-operasi pada ADT
dengan algoritma (logika berfikir) tertentu. Algoritma ini biasanya berupa urutan instruksi
yang menspesifikasi secara tepat bagaimana operasi-operasi akan dilakukan/dieksekusi
oleh komputer.
Kita sekarang akan membahas lebih konkret tentang apa itu ADT. Pada dasarnya,
ADT adalah tipe data tertentu yang didefinisikan oleh pemrogram untuk kemudahan
pemrograman serta untuk mengakomodasi tipe-tipe data yang tidak secara spesifik
diakomodasi oleh bahasa pemrograman yang digunakan. Maka, secara informal dapat
dinyatakan bahwa ADT adalah :
1. Tipe data abstrak ADT pertama kali ditemukan oleh para ilmuan komputer utuk
memisahkan struktur penyimpanan dari perilaku tipe data yang abstrak seperti misalnya,
Tumpukan(Stack) serta antrian(Queue). Seperti kita duga, pemrogram tidak perlu tahu
bagaimana Tumpukan(Stack) perubahan inplementasi ADT tidak mengubah program yang
menggunakannya secara keseluruhan, dengan catatan bahwa interface ADT tersebut
dengan ‘dunia luar’ tetap dipertahankan.
2. Pemakaian dan pembuatan ADT dapat dilakukan secara terpisah. yang perlu dibicarakan
antara pembuat dan pengguna ADT adalah interface ADT yang bersangkutan.
3. ADT merupakan sarana pengembangan sistem yang bersifat modular, memungkinkan
suatu sistem dikembangkan oleh beberapa orang anggota tim kerja dimana masing-masing
anggota tim bisa melakukan bagiannya sendiri-sendiri dengan tetap mempertahankan
keterpaduannya dengan anggota tim yang lain.
Dalam hal ini perlu dibedakan antara pengertian struktur data dan ADT. Struktur
data hanya memperlihatkan bagaimana data-data di organisir, sedangkan ADT bercakupan
lebih luas, yaitu memuat/mengemas struktur data tertentu sekaligus dengan operasioperasi yang dapat dilakukan pada struktur data tersebut. Dengan demikian, definisi umum
tentang ADT di atas dapat diperluas sebagai berikut :
8
Implementasi ADT = {Struktur Data (Operasi-operasi yang dapat dilakukan
terhadap Struktur Data)}
Contoh ADT
 Tipe jadi (built-in): boolean, integer, real, array, dll
 Tipe buatan (user-defined): stack, queue, tree, dll
 ADT Built-in:
Boolean
Nilai: true dan false
Operasi: and, or, not, xor, dll
Integer
Nilai: Semua bilangan
Operasi: tambah, kurang, kali,bagi, dll
 ADT buatan (user-defined) :
Stack (tumpukan)
Nilai : elemen dalam stack
Operasi: Initstack, Push, Pop
Queue (antrian)
Nilai: elemen dalam Queue
Operasi: InitQueue, Enqueue, Dequeue.
Tree (pohon)
Nilai: elemen dalam pohon
Operasi: insert, delete, find, traverse
9
Penutup
Latihan Soal
1. Tulislah output dari cuplikan program berikut :
#include<iostream>
using namespace std;
main(){
int a,*b, *c;
a=10;
b=&a;
cout<<*b<<endl;
c=new int;
*c=25;
b=c;
cout<<*b<<endl;
getchar();
}
2. Diketahui subprogram berikut :
void buatA(list &l)
{
int i,n;
list b,t;
n=10;
for (i=1;i<=n;i++){
b=new node; b->next=NULL;
b->data=(i+i*i*2)%40;
cout<<b->data<<" ";
if (l==NULL) l=b;
else if (b->data%2==0) {b->next=l;l=b;}
else {
t=l;
while (t->next!=NULL) t=t->next;
t->next=b;
}
}
}
Jika dipanggil
list p;
BuatA(p);
cetakdata(p);
Maka tulis outputnya.
3. Jelaskan tentang nilai dan operasi-operasi pada ADT graf
10
BAB II
LINKED LIST LINEAR
Pendahuluan
Deskripsi Singkat
Pada bab ini akan dijelaskan struktur data linked list, operasi-operasi pada linked list,
dan contoh penggunaannnya.
Manfaat
Dengan memahami linked list, mahasiswa akan mudah mengimplementasikan
struktur data yang lain, seperti stack, queue, dan tree.
Relevansi
Materi ini menjadi dasar untuk mempelajari struktur data yang lain, seperti stack,
queue, dan tree.
Learning Outcomes
Setelah mempelajari materi ini, mahasiswa memahami dan mampu membuat program
operasi-operasi pada linked list.
Penyajian
Struktur data linear adalah kumpulan komponen-komponen yang tersusun membentuk
satu garis linear. Bila komponen-komponen ditambahkan (atau dikurangi), maka strukturstruktur tersebut berkembang (atau menyusut). Pemakaian struktur data yang tepat di dalam
proses pemrograman akan menghasilkan algoritma yang lebih jelas dan tepat , sehingga
menjadikan program secara keseluruhan lebih efisien dan sederhana.
Struktur data linear yang akan dibahas pada bab ini dan bab-bab selanjutnya adalah
linear linked list serta stack dan queue.
2.1 Definisi Linked List
Linked list adalah kumpulan data yang bertipe sama dengan setiap elemen berisi dua
bagian, yaitu : data and link (next). Nama linked list sama dengan nama suatu variable
bertipe pointer.
Gambar 2.1 menunjukkan linked list nilai yang memiliki empat elemen (node).
Linked list kosong adalah pointer null, seperti pada Gambar 1.1.
11
Gambar 2.1 Linked List
Contoh deklarasi linked list yang berisi nilai integer :
typedef struct elmt {
int isi;
elmt *next;
}elemen, nodptr;
typedef struct {
elemen *first;
}list;
2.2 Operasi pada linked list
Operasi-operasi pada linked list adalah :
1. Buat linked list
2. Sisip node pada linked list
3. Hapus node pada linked list
4. Kunjungi node pada linked list
1. Operasi Buat list
Operasi ini untuk membuat sebuah linked list. Linked list yang dideklarasikan merupakan
list yang masih kosong.
Prosedurnya :
void buatList(list *L) {
(*L).first = NULL;
}
2. Operasi sisip node pada linked list.
Operasi ini untuk menambkan data baru ke dalam linked list. Data tersimpan di dalam
node baru. Ada 3 cara penambahan data baru ke dalam list, yaitu :
12
a. Penambahan di depan
Pada cara ini, node baru akan diletakkan di tempat paling depan pada linked list.
Gambar 2.2 menunjukkan proses penambahan node di awal list.
Gambar 2.2 Penyisipan node di awal list (Sisip depan)
Prosedurnya :
void sisipDepan (list *L, int IB) {
elemen *NB;
NB = (elemen *) malloc (sizeof (elemen));
NB->isi = IB;
NB->next = (*L).first;
(*L).first = NB;
NB = NULL;
free(NB);
}
b. Penambahan node di belakang
Pada cara ini, node baru akan diletakkan di akhir list. Untuk menyisipkan node di
akhir list, diperlukan pointer bantu untuk mencari alamat node yang terakhir (paling
belakang). Proses penambahan node di akhir list, setelah node paling akhir ditemukan,
ditunjukkan pada Gambar 2.3.
13
Gambar 2.3 Penyisipan di akhir list
Prosedurnya :
void sisipBlk (list *L, int IB) {
elemen *NB;
NB = (elemen *) malloc (sizeof (elemen));
NB->isi = IB;
NB->next = NULL;
if ((*L).first==NULL){
(*L).first =NB;
}
else {
elemen *p;
p = (elemen *) malloc (sizeof (elemen));
p=(*L).first;
while (p->next != NULL){
p = p->next;
}
p->next=NB;
NB->next=NULL;
}
}
14
c. Penyisipan node di tempat tertentu
Pada penyisipan ini, node baru akan diletakkan setelah node tertentu, misalkan setelah
node yang datanya terbesar yang lebih dari data node baru (pada kasus linked list
dengan data diletakkan secara terurut naik). Proses penyisipan seperti pada Gambar
2.4.
Gambar 2.4 Proses penyisipan node secara terurut naik
Prosedurnya :
void sisipUrut(list *L, int IB) {
elemen *NB;
NB = (elemen *) malloc (sizeof (elemen));
NB->isi = IB;
NB->next = NULL;
if (((*L).first == NULL) ||(IB < (*L).first->isi)){
NB->next = (*L).first;
(*L).first = NB;
}
else {
elemen *p ;
p = (nodptr *) malloc (sizeof (nodptr));
p=(*L).first;
while ((p->next != NULL) && (p->next->isi < IB)){
p = p->next;
}
15
NB->next = p->next;
p->next = NB;
}
}
3. Operasi Hapus Node
Operasi ini untuk menghapus node pada linked list. Sebelum node dihapus, ada proses
pencarian untuk mencari node yang dihapus. Sehingga diperlukan pointer bantu, yang
akan menunjukkan alamat di depan alamat node yang akan dihapus. Gambar 2.5 berikut
ini menunjukkan prose penghapusan node. Sebelum dihapus, alamat yang ditunjuk oleh
node yang akan dihapus, akan ditunjuk pula oleh pointer bantu.
Gambar 2.5 Proses penghapusan node
Jika setelah dihapus, linked list jadi kosong, maka linked list diset null.
4. Operasi Kunjungi Node
Pada operasi ini, dilakukan kunjungan pada linked list, dari node paling depan ke node
paling akhir.
Gambar 2.6 Kunjungan pada linked list
Prosedurnya :
void cetakList (list L) {
if (L.first != NULL) {
elemen *p;
p=L.first;
16
while (p != NULL){
cout<<p->isi<<endl;
p = p->next;
}
}
}
2.3 Penggunaan Linked List
Linked list adalah struktur data yang sangat efisien untuk pengurutan list. Linked list
adalah stuktur data dinamis yang bisa ditambah elemen dengan mudah. Node juga dengan
mudah dihaus tanpa menukar tempat, seperti pada array.
Struktur data linked list digunakan juga sebagai implementasi pada struktur data
stack, queue, tree, dan graph.
2.4 Variasi Linked List
1. Doubly-linked lists: Tiap list node menyimpan referensi node sebelum dan sesudahnya.
Berguna bila perlu melakukan pembacaan linked list dari dua arah.
Gambar 2.7 Doubly-linked list
Deklarasi struktur data Doubly-linked list :
struct Node {
int isi;
Node *prev, *next;
};
A. Operasi Menambah Data
a. Menambah data pada Doubly linked list yang kosong :
pNew = (struct node *) malloc(sizeof(struct dllnode));
pNew -> data = 39;
pNew -> prev = pHead;
pNew -> next = pHead;
17
pHead = pNew;
b. Menambah data di tengah Doubly linked list
pNew = (struct node *) malloc(sizeof(struct dllnode));
pNew -> data = 64;
pNew -> prev = pCur;
pNew -> next = pCur -> next;
pCur -> next -> prev = pNew;
pCur -> next = pNew;
c. Menambah data di akhir Doubly linked list
pNew = (struct node *) malloc(sizeof(struct dllnode));
pNew -> data = 84;
pNew -> prev = pCur;
pNew -> next = pCur -> next;
pCur -> next = pNew;
B. Menghapus node pada Doubly linked list
if (pCur -> left == NULL){
//menghapus node paling depan
pHead = pCur -> next;
pCur -> next -> prev = NULL;
{
else {
//menghapus node di tengah atau belakang linked list
pCur -> prev -> next = pCur -> next;
pCur -> next -> prev = pCur -> prev;
}
free(pCur).
2. Circular-linked lists: Node terakhir menyimpan referensi node pertama. Dapat diterapkan
dengan atau tanpa header node.
18
Gambar 2.8 Circular-linked list
Penutup
Latihan Soal
1. Jelaskan tentang linked list linear!
2. Apa yang dibutuhkan pada linked list linear dan apa keunggulannya dibanding struktur
data larikan/menggunakan tipe array ?
3. Tuliskan program untuk menyisipkan node baru setelah suatu node tertentu.
4. Tuliskan program untuk menyisipkan node baru sebelum suatu node tertentu..
19
BAB III
STACK
Pendahuluan
Deskripsi Singkat
Pada bab ini akan dijelaskan struktur data stack, operasi-operasi pada stack, dan
contoh penggunaannnya.
Manfaat
Dengan memahami stack, maka mahasiswa akan bisa menerapkan stack pada suatu
permasalahan, seperti antara lain pada algoritma pelacakan DFS (Depth First Search).
Relevansi
Materi ini terkait dengan materi berikutnya seperti struktur data Tree dan juga pada
materi kuliah Analisis dan Desain Algoritma 1 dan 2, seperti algoritma DFS.
Learning Outcomes
Setelah mempelajari materi ini, mahasiswa memahami dan mampu membuat program
untuk operasi-operasi pada stack dan mampu menggunakan stack untuk mengkonversi notasi
infix menjadi postfix.
Penyajian
3.1 Definisi Stack
Stack adalah struktur data linear di mana penambahan/pengurangan elemen dilakukan
di satu ujung saja, sehingga elemen yang pertama ditambahkan, akan diambil terakhir.
Sehingga stack dikenal jug sebagai struktur last in first out (LIFO). Contoh stack (tumpukan)
dalam kehidupa sehari-hari seperti pada Gambar 3.1
Gambar 3.1 Contoh stack (tumpukan) dalam kehidupan sehari-hari
3.2 Operasi pada Stack
Terdapat 4 operasi dasar pada stack, yaitu : inisialisasi stack, push, pop, dan empty.
20
1. Operasi Buat Stack
Operasi buat stack menciptakan stack kosong, yaitu stack yang belum memiliki elemen.
Bentuk pernyataannya adalah : BuatStack(NamaStack)
Gambar 3.2 Operasi buat stack
2. Operasi Push
Operasi push menambah data ke tempat paling atas pada stack. Pernyaannya adalah
push(NamaStack, data). Operasi push ditunjukkan oleh Gambar 3.3.
Gambar 3.3 Operasi Push
3. Operasi Pop
Operasi pop mengambil data pada stack. Data yang diambil adalah data yang berada pada
tempat teratas pada stack. Pernyataan operasi pop : pop(NamaStack, Data). Operasi pop
ditunjukkan pada Gambar 3.4.
Gambar 3.4 Operasi Pop
4. Operasi Empty
Operasi empty mengecek apakah stack memiliki elemen atau tidak. Pernyataan operasi :
empty(NamaStack). Jika stack kosong, maka operasi akan mengembalikan nilai true, jika
tidak maka nilainya false.
21
3.3 Implementasi Stack
Struktur Data Stack bisa diimplementasikan dengan 2 cara, yaitu dengan array dan
dengan linked list. Pada implementasi dengan array, digunakan array of record. Setiap record
memiliki dua field yaitu field data, untuk menyimpan nilai data, dan top untuk menyimpan
indeks tempat paling atas pada stack. Sedangkan pada implementasi dengan linked list, setiap
node juga berupa record untuk menyimpan data dan penunjuk ke alamat node lain.
Implementasi stack ditunjukkan pada Gambar 3.5.
Gambar 3.5 Implementasi Stack
1. Implementasi dengan array
Stack dapat diimplementasi dengan suatu array dan suatu integer top yang mencatat
indeks dalam array dari top of the stack. Untuk stack kosong maka top berharga -1. Saat
terjadi push, lakukan dengan increment counter top, dan tulis ke dalam posisi top tsb dalam
array. Saat terjadi pop, lakukan dengan decrement counter top.
Deklarasi struktur data stack menggunakan array, missal stack berisi data integer dengan
maksimum banyaknya elemen 100 :
typedef struct{
int TOP;
int data[99];
}stack;
A. Prosedur Buat Stack
void buatStack(stack &S){
int i;
S.TOP=-1;
}
B. Prosedur Push
void push(stack &S, int IB){
22
S.TOP= S.TOP + 1;
S.data[S.TOP] = IB;
}
C. Prosedur Pop
void pop(stack &S, int &EB){
if (stackKosong(S)!= 1){
EB = S.data[S.TOP];
S.TOP= S.TOP-1;
}
}
D. Fungsi Empty
int stackKosong(stack S){
int hasil;
if (S.TOP== -1) {
hasil = 1;
}
else hasil = 0;
return hasil;
}
2. Implementasi dengan linked list
Secara lojik, sebuah STACK dapat digambarkan sebagai list linier yang setiap elemennya
adalah :
Type ElemenStack
<Info : InfoType,
Next : address >
Type Stack <top : address>
Dalam bahasa C, deklarasi stack dengan linked list adalah :
typedef struct elmt *alamatelmt;
typedef struct elmt {
int isi;
alamatelmt next;
}Tstack;
typedef Tstack *stack;
23
A. Prosedur Buat Stack
void buatStack(stack *S){
(*S) = NULL;
}
B. Prosedur Push
void push(stack *S, int IB){
Tstack *NB;
NB = (Tstack *) malloc (sizeof (Tstack));
NB->isi = IB;
NB->next = NULL;
if ((*S) == NULL) {
(*S)=NB;
}
else {
NB->next=(*S);
(*S)=NB;
}
}
C. Prosedur Pop
void pop(stack *S,int &EB){
Tstack *p;
EB = (*S)->isi;
p = (*S);
if ((*S)!=NULL){
(*S)=(*S)->next;}
free(p);
}
D. Fungsi Stack Kosong
int stackKosong(stack S){
int hasil;
if (S == NULL) {
hasil = 1;
}
24
else hasil = 0;
return hasil;
}
3.4 Aplikasi Stack
Terdapat banyak penggunaan stack dalam algoritma atau suatu permasalahan. Misal
pada algoritma pelacakan DFS (Depth First Search), untuk mengevaluasi suatu ekspresi
dalam notasi postfix/prefix, untuk mengubah suatu ekspresi dalam notasi infix menjadi
postfix/prefix.
A. Algoritma evaluasi ekspresi dalam notasi postfix
Berikut adalah langkah-langkah mengevaluasi ekspresi dalam notasi postfix.
1. Inisialisasi stack
2. Ulangi langkah berikut sampai akhir ekspresi
a) Ambil token (const, var, operator) pada ekspresi
b) Jika operan, push ke dalam stack
c) Jika operator
Lakukan :
i.
Pop 2 nilai dari stack
ii.
Operasikan denga operator ke dua nilai tersebut
iii.
Hasilnya di push ke stack
3. Pada saat ekspresi sudah habis, maka nilai terakhir yang ada di stack adalah nilai dari
ekspresi tersebut.
B. Algoritma konversi ekspresi dalam infix ke postfix
1. Inisialisasi stack operator
2. Selama ekspresi masih ada :
a. Ambil token dari ekspresi infix
b. Jika token :
i. "(" : push ke dalam stack
ii. “)” : pop dan tampilkan elemen stack sampai ditemui “(“, jangan
ditampilkan
iii. operator
25
Jika operator memiliki prioritas lebih tinggi daripada top stack, maka
push token ke dalam stack, jika tidak pop dan tampilkan top stack dan
ulangi perbandingan dengan top stack
iv. operand
tampilkan
3. Ketika akhir dari infix sudah diperoleh, pop dan tampilkan stack sampai stack
kosong.
Penutup
Latihan Soal
1. Tulis program non-rekursif untuk membalik string menggunakan stack.
2. Jelaskan ekspresi prefix, infix, and postfix dengan contoh.
3. Tulis program untuk mengevaluasi eskpresi dalam notasi postfix.
26
BAB IV
QUEUE
Pendahuluan
Deskripsi Singkat
Pada bab ini akan dijelaskan struktur data queue, operasi-operasi pada queue, dan
contoh penggunaannnya.
Manfaat
Dengan memahami queue, maka mahasiswa akan bisa menerapkan queue pada suatu
permasalahan, seperti antara lain pada algoritma pelacakan BFS (Breadth First Search) dan
pada masalah antrian yang lain.
Relevansi
Materi ini terkait dengan materi selanjutnya seperti Tree dan juga materi pada kuliah
Analisis dan Desain Algoritma 1 dan 2, seperti algoritma BFS.
Learning Outcomes
Setelah mempelajari materi ini, mahasiswa memahami dan mampu membuat program
untuk operasi-operasi pada queue dan mampu menggunakan queue pada suatu permasalahan.
Penyajian
4.1 Definisi Queue
Queue adalah struktur data linear seperti Stack, hanya saja penambahan dan
penghapusan elemen dilakukan pada tempat yang berbeda. Penambahan elemen dilakukan
pada bagian belakang Queue, sedangkan penghapusan elemen dilakukan pada bagian depan
Queue. Mekanisme ini dikenal sebagai First-In-First-Out (FIFO). Beberapa contoh aplikasi
queue atau antrian adalah : antrian printer, antrian kasir, dsb.
4.2 Operasi pada Queue
Terdapat lima operasi dasar pada queue : Buat Queue, enqueue, dequeue, kosong, dan
penuh.
1. Buat Queue
Operasi
ini
untuk
membuat
queue
kosong.
Formatnya
adalah
:
BuatQueue(NamaQueue)
Gambar 4.1 Operasi Buat Queue
27
2. Queue Kosong
Operasi ini untuk mengecek apakah queue kosong atau tidak. Formatnya :
Kosong(NamaQueue).
3. QueuePenuh
Operasi ini untuk mengecek apakah queue penuh atau tidak (dalam hal ini, queue
yang diimplementasikan dengan array). Formatnya : Penuh(NamaQueue).
4. Operasi Enqueue
Operasi ini untuk menambahelemen baru pada queue, dan diletakkan di posisi paling
belakang dari queue. Formatnya : Enqueue(NamaQueue, Nilai).
Gambar 4.2 Operasi Enqueue
5. DeQueue
Operasi ini untuk mengambil elemen queue yang berada di posisi paling depan.
Formatnya : Dequeue(NamaQueue, Nilai).
Gambar 4.3 Operasi Dequeue
4.3 Implementasi Queue
Struktur data queue dapat diimplementasikan menggunakan array atau linked list
.Gambar 3.4 menggambarkan implementasi queue dengan array dan linked list. Pada
implementasi dengan array, digunakan sebuah array of record dengan setiap record terdiri
dari 3 field, dan salah satu field untuk menyimpan data.
Pada implementasi dengan linked list juga mirip: terdapat node yang berupa record
yang memiliki dua field berupa pointer untuk menunjuk elemen depan dan belakang.
28
Gambar 4.4 Implementasi Queue dengan array dan llinked list
1. Implementasi dengan Array – cara naive
Pada metode ini, elemen pada suatu array disimpan dengan item terdepan pada index
nol dan item terbelakang pada index belakang. Dengan cara ini, operasi Enqueue mudah &
cepat, yaitu dengan menaikkan nilai belakang. Sedangkan Dequeue tidak efisien, karena
setiap elemen harus digeserkan ke depan. Akibatnya: waktu menjadi O(N).
Deklarasi struktur data queue dengan array :
typedef struct {
int depan;
int blk;
int data[30];
}queue;
A. Operasi Buat Queue.
Operasi ini untuk membuat queue kosong, yaitu queue yang belum memiliki elemen.
void buatQueue(queue *Q){
(*Q).depan =-1;
(*Q).blk =-1;
}
B. Fungsi Kosong
Fungsi ini untuk mengecek apakah suatu queue kosong atau tidak. Jika kosong, maka
fungsi akan mengembalikan nilai 1, jika tidak kosong akan mengembalikan nilai 0.
29
int kosongQueue(queue Q){
int hasil =0;
if (Q.depan==-1) {
hasil =1;
}
return hasil;
}
C. Fungsi Penuh
Fungsi ini untuk mengecek apakah queue penuh, yaitu indeks belakang sudah
mencapai maksimum atau tidak.
int penuhQueue(queue Q){
int hasil =0;
if (Q.blk==29) {
hasil =1;
}
return hasil;
}
D. Operasi Enqueue
Operasi ini untuk menambahkan elemen baru ke dalam queue. Elemen baru
diletakkan di belakang, sehingga indeks belakang dinaikkan 1.
void enQueue(queue *Q,int db){
if (kosongQueue(*Q)==1){
(*Q).depan =0;
(*Q).blk =0;
(*Q).data[0]=db;
}
else {
if (penuhQueue(*Q)!= 1){
(*Q).blk =(*Q).blk +1;
(*Q).data[(*Q).blk]=db;
}
30
else {
cout<<"Queue penuh "<<endl;
}
}
}
E. Operasi Dequeue
Operasi ini untuk mengambil elemen pada queue, yaitu elemen pada posisi depan.
Setelah elemen diambil, dilakukan pergeseran elemen queue pada array.
void deQueue(queue *Q, int *da){
if (kosongQueue(*Q)==1){
cout<<"Queue kosong, tdk bisa diambil"<<endl;
}
else {
if ((*Q).blk == 0){
*da =(*Q).data[0];
(*Q).depan =-1;
(*Q).blk =-1;
}
else {
int i;
*da =(*Q).data[(*Q).depan];
for (i=((*Q).depan+1);i<=(*Q).blk;i++){
(*Q).data[i-1]=(*Q).data[i];
}
(*Q).blk=(*Q).blk-1;
}
}
}
Sehingga terjadi pergeseran pada semua elemen queue, Terdapat ide lain, yaitu
menggunakan indeks depan untuk mencatat indeks terdepan, sehingga Dequeue dilakukan
dengan menaikkan depan dan waktu Dequeue tetap O(1). Namun permasalahan yang timbul
31
adalah, ada suatu keadaan setelah proses Dequeue, indeks belakang = panjang array -1,
sehingga queue seperti kosong, padahal masih bias diisi.
Solusinya adalah dengan menggunakan wraparound untuk menggunakan kembali selsel di awal array yang sudah kosong akibat dequeue. Jadi setelah increment, jika index depan
atau belakang keluar dari array maka ia kembali ke 0.
2. Implementasi dengan List Linear
Pada implementasi Queue (Antrian) dengan list linier, maka :
1. Dikenali elemen pertama (depan) dan elemen terakhirnya (belakang).
2. Aturan penyisipan dan penghapusan elemennya didefinisikan sebagai berikut :
- Penyisipan selalu dilakukan setelah elemen terakhir.
- Penghapusan selalu dilakukan pada elemen pertama.
3. Satu elemen dengan elemen lain dapat diakses melalui informasi Next.
Deklarasi Queue (Antrian) dengan list linier :
typedef struct node {
int isi;
node *next;
}Tqueue;
typedef struct {
Tqueue *depan;
Tqueue *blk;
}Queue;
A. Operasi Buat Queue
void buatQueue(Queue *Q){
(*Q).depan = NULL;
(*Q).blk = NULL;
}
B. Operasi Enqueue
void enQueue(Queue *Q, int IB){
Tqueue *NB;
NB = (Tqueue *) malloc (sizeof (Tqueue));
NB->isi = IB;
NB->next = NULL;
32
if ((*Q).depan == NULL) {
(*Q).depan=NB;}
else {(*Q).blk->next = NB;}
(*Q).blk =NB;
NB= NULL;
}
C. Operasi Dequeue
void deQueue(Queue *Q,int &X){
Tqueue *p;
if ((*Q).depan!=NULL){
X = (*Q).depan->isi;
p = (*Q).depan;
(*Q).depan=(*Q).depan->next;}
free(p);
}
4.4 Aplikasi Queue
Aplikasi queue pada dunia nyata dapat dijumpai pada semua jenis antrian, seperti
antrian pelanggan, antrian pembeli tiket. Sedangkan antrian pada sistem komputer misalnya
antrian job yang ditangani sistem operasi, antrian layanan cetak pada mesin printer. Struktur
data queue juga digunakan pada bucket sort dan implementasi algoritma pelacakan BFS.
Penutup
Latihan Soal
1. Apakah queue linear? Apa keterbatasan queue linear?
2. Jelaskan perbedaaan antara linear queue and circular queue, mana yang lebih baik dan
mengapa?
3. Misalkan dimiliki queue integer, dan queue q telah berisi 3 data nilai :
5
12
depan
7
belakang
Gambarkan urutan diagram yang menunjukkan isi dari queue q, setelah setiap baris
perintah ini dikerjakan.
enqueue(q,1); dequeue(q,x);enqueue(q,x); dequeue(q,y);
dequeue(q,z);enqueue(q, y-z);
33
BAB V
STRUKTUR DATA NON LINEAR
Pendahuluan
Deskripsi Singkat
Pada bab ini akan dijelaskan struktur data non linear yaitu matriks dan multiple linked
list beserta contoh aplikasinya.
Manfaat
Dengan memahami struktur data matriks dan multiple linked list, mahasiswa akan
dapat membangun struktur data yang lebih kompleks seperti Tree dan Graf.
Relevansi
Materi ini menjadi dasar untuk mempelajari berbagai macam struktur data yang lebih
kompleks terutama struktur data non linear.
Learning Outcomes
Setelah mempelajari materi ini, mahasiswa memiliki pengetahuan tentang struktur
data non linear yaitu matriks dan multiple linked list serta mampu membuat program
menggunakan tipe data array dan pointer untuk membangun struktur data non linear.
Penyajian
Pada bab-bab sebelumnya telah kita bahas tentang beberapa struktur data linear yaitu
linked list linear, stack dan queue. Struktur data non linear adalah struktur data yang tidak
linear, yaitu antara lain yang akan dibahas dalam bab ini adalah matriks, menggunakan array
2 dimensi, dan multiple linked list.
5.1 Matriks, Array Dua Dimensi
Array dua dimensi sering digambarkan sebagai sebuah matriks, merupakan perluasan dari
array satu dimensi. Jika array satu dimensi hanya terdiri dari sebuah baris dan beberapa
kolom elemen, maka array dua dimensi terdiri dari beberapa baris dan beberapa kolom
elemen yang bertipe sama sehingga dapat digambarkan sebagai berikut:
34
0
1
2
3
4
5
6
0
10
21
23
43
45
78
65
1
45
43
65
12
21
12
21
2
32
34
23
56
54
34
45
3
11
12
32
23
56
76
45
Bentuk umum:
<tipe data> NamaArray [m][n];
Atau
<tipe data> NamaArray [m][n] = { {a,b,..z},{1,2,...,n-1} };
Contoh:
double matrix[4][7];
Pendeklarasian array dua dimensi hampir sama dengan pendeklarasian array satu dimensi,
kecuali bahwa array dua dimensi terdapat dua jumlah elemen yang terdapat di dalam kurung
siku dan keduanya boleh tidak sama.
Elemen array dua dimensi diakses dengan menuliskan kedua indeks elemennya dalam
kurung siku seperti pada contoh berikut:
matrix[1][2] = 65;
matrix[3][6] = 45;
Berikut contoh program tentang penggunaan array 2 dimensi.
#include<iostream>
#include<conio.h>
#include<stdio.h>
using namespace std;
int cost[10][10],dist[20],i,j,n,k,m,S[20],v,totcost,path[20],p;
int shortest(int v,int n)
{int min;
for(i=1;i<=n;i++)
{ S[i]=0;
dist[i]=cost[v][i];
}
path[++p]=v;
35
S[v]=1;
dist[v]=0;
for(i=2;i<=n-1;i++)
{ k=-1;
min=9999;
for(j=1;j<=n;j++)
{ if(dist[j]<min && S[j]!=1)
{
min=dist[j];
k=j;
}
}
if(cost[v][k]<=dist[k]) p=1;
path[++p]=k;
for(j=1;j<=p;j++) cout<<path[j]<<" ";
// cout <<"\n";
// cout <<k;
S[k]=1;
for(j=1;j<=n;j++)
if(cost[k][j]!=9999 && dist[j]>=dist[k]+cost[k][j] && S[j]!=1)
dist[j]=dist[k]+cost[k][j];
cout<<dist[j]<<endl;
}
}
main()
{
int c;
cout <<"enter no of vertices :";
cin >> n;
cout <<"enter no of edges :";
cin >>m;
cout <<"\nenter\nEDGE Cost\n";
for(k=1;k<=m;k++)
{
cin >> i >> j >>c;
cost[i][j]=c;
}
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(cost[i][j]==0 && i!=j) cost[i][j]=9999;
cout <<"enter initial vertex :";
cin >>v;
cout << v<<"\n";
shortest(v,n);
getch();
}
36
5.2 Multiple Linked list
Multiple linked list adalah linked list dengan linked field lebih dari satu dan bentuknya
tidak linear. Multiple linked sangat beragam strukturnya, berikut adalah sebagai ilustrasi
dari salah satu bentuk multiple linked list.
Implementasi dari multiple linked untuk menyimpan data peserta suatu pelatihan dimana
banyak pelatihan dan pesertanya bisa dinamis dapat dilihat pada program berikut.
#include<iostream>
#include<conio.h>
using namespace std;
typedef struct nodep
{ char nama[20];
struct nodep *next;
} *peserta;
typedef struct node
{ char pelatihan[20];
struct node *next;
peserta down;
} *list;
list L;
void InsertPelatihan(list &l)
{
int i,n;
list b;
cout<<"banyak pelatihan : ";cin>>n;
for (i=1;i<=n;i++){
b=new node;
b->next=NULL;b->down=NULL;
cout<<"Nama Pelatihan : ";cin>>b->pelatihan;
if (l==NULL) l=b;
else {b->next=l;
l=b;}
}
}
37
void cetakdata(list l)
{list p;peserta q;
if (l!=NULL) {
p=l;cout<<endl;
while (p!=NULL) {
cout<<p->pelatihan<<" : ";
q=p->down;
while (q!=NULL) {
cout<<q->nama<<", ";q=q->next;}
p=p->next;cout<<endl;
}
}
else cout<<"kosong";
}
void InsertPeserta(list &l)
{
int i,n;char namapelatihan[20];
list p;peserta b;
cout<<"Insert Peserta "<<endl;
cout<<"Nama pelatihan: ";cin>>namapelatihan;
p=l;
while (p!=NULL && strcmp(p->pelatihan,namapelatihan)!=0) p=p->next;
if (p==NULL) cout<<"nama pelatihan belum ada\n"; else
if(strcmp(p->pelatihan,namapelatihan)==0) {
cout<<"banyak peserta : ";cin>>n;
for (i=1;i<=n;i++){
b=new nodep; b->next=NULL;
cout<<"Nama peserta : ";cin>>b->nama;
if (p->down==NULL) p->down=b;
else {b->next=p->down;
p->down=b;
}
}
}
}
void HapusPeserta(list &l) {
char namapelatihan[20],namapeserta[20];
list p;peserta b,c;
cout<<"Hapus Peserta "<<endl;
cout<<"Nama pelatihan: ";cin>>namapelatihan;
p=l;
while (p!=NULL && strcmp(p->pelatihan,namapelatihan)!=0) p=p->next;
if (p==NULL) cout<<"nama pelatihan tidak ada\n";
else if(strcmp(p->pelatihan,namapelatihan)==0) {
b=p->down;
if(b==NULL)cout<<"tidak ada pesertanya";
else{
cout<<"masukkan nama peserta: ";
38
cin>>namapeserta;
if (strcmp(b->nama,namapeserta)==0)
{c=p->down;p->down=c->next;free(c);}
else {
while(b->next!=NULL && strcmp(b->next->nama,namapeserta) !=0)b=b>next;
if (b->next==NULL) cout<<"peserta tidak ada";
else if(strcmp(b->next->nama,namapeserta)==0){
c=b->next;b->next=c->next;free(c);
}
}
}
}
}
main()
{ int x;
L=NULL;
InsertPelatihan(L);
InsertPeserta(L);
cetakdata(L);
HapusPeserta(L);
cetakdata(L);
HapusPeserta(L);
cetakdata(L);
getch();
}
Penutup
Latihan Soal
1. Dengan menggunakan struktur data matriks, buatlah program untuk membuat matriks
gambar yang nilai elemennya 0..255 dan kemudian tentukan nilai dominan yaitu nilai
0..255 yang paling sering muncul.
2. Buatlah program untuk menyimpan data menu utama, submenu dan sub submenu dalam
multiple linkedlist, Program minimal mempunyai subprogram insertmenu, deletemenu dan
cetak menu.
39
BAB VI
STRUKTUR DATA POHON ( TREE )
Pendahuluan
Deskripsi Singkat
Pada bab ini akan dijelaskan struktur data Tree yaitu Binary Search Tree (BST) dan
AVL-Tree beserta implementasinya.
Manfaat
Dengan memahami struktur data Tree, mahasiswa akan dapat menyelesaikan berbagai
permasalahan yang menggunakan struktur data Tree, antara lain pada searching, sorting dan
kompresi data.
Relevansi
Materi ini menjadi dasar untuk mempelajari berbagai permasalahan seperti pada
searching, sorting dan kompresi data.
Learning Outcomes
Setelah mempelajari materi ini, mahasiswa memiliki pengetahuan tentang struktur
data Tree yaitu BST dan AVL serta mampu membuat program menggunakan tipe data array
dan pointer untuk membangun struktur data Tree.
Penyajian
Struktur data Tree atau pohon adalah struktur data yang tidak linear dan berbentuk
herarki, atau dapat didefinisikan sebagai kumpulan node atau simpul (mulai pada simpul
akar), di mana setiap node adalah struktur data yang terdiri dari nilai, bersama dengan daftar
referensi ke node anak-anaknya atau cabang-cabangnya.
Sebagai tipe data, pohon memiliki nilai dan anak-anak, dan anak-anak itu sendiri bisa
berupa pohon, nilai dan anak-anak dari pohon diinterpretasikan sebagai nilai dari simpul akar
dan subpohon anak-anak dari simpul akar. dalam hal ini daftar anak-anak dapat menjadi
ukuran tetap (percabangan faktor, terutama 2 atau "biner"), jika diinginkan.
Sebagai struktur data, pohon adalah sekelompok node, dimana setiap node memiliki
nilai dan daftar referensi ke node lain (anak-anaknya). Struktur data Tree yang akan dibahas
adalah struktur data binary tree (pohon biner).
40
Pohon biner merupakan pohon yang memiliki ketentuan setiap node hanya boleh
memiliki maksimal dua subtree dan kedua subtree tersebut harus terpisah. Sesuai dengan
definisi tersebut, maka tiap node dalam binary tree hanya boleh memiliki paling banyak dua
anak.
Berikut ini adalah ilustrasi pohon biner :
Implementasi Tree dalam program, ada beberapa hal yang perlu diperhatikan yaitu :
1. deklarasi pohon
2. membuat pohon
3. memeriksa apakah pohon kosong
4. membuat node baru
5. menambah node ke pohon
6. membaca sebuah node
7. mengunjungi pohon secara In Order
(Kunjungi Left Child, cetak isi node yang dikunjungi, kunjungi Right Child)
8. mengunjungi pohon secara Pre Order
(Cetak isi node yang dikunjungi, kunjung Left Child, kunjungi Right Child)
9. mengunjungi pohon secara Post Order
(Kunjungi Lift Child, kunjungi Right Child, cetak node yang dikunjungi)
10. mencari node tertentu dalam pohon
41
Berikut contoh implementasi program tentang Pohon Biner.
#include<iostream>
#include<stdio.h>
#include<conio.h>
using namespace std;
typedef struct node
{ char data;
struct node *kanan,*kiri;
} simpul;
typedef simpul *tree;
tree T;
void BST(tree *T,char x)
{ tree b;
if (*T==NULL) {
b=new simpul;
b->data=x;b->kanan=NULL;b->kiri=NULL;
*T=b;}
else if(x<(*T)->data) BST(&(*T)->kiri,x);
else BST(&(*T)->kanan,x);
}
void PRE(tree T)
{
if (T!=NULL) {
cout<<T->data<<" ";
PRE(T->kiri);
PRE(T->kanan);
}
}
void IN(tree T)
{
if (T!=NULL) {
IN(T->kiri);
cout<<T->data<<" ";
IN(T->kanan);
}
}
void POST(tree T)
{
if (T!=NULL) {
POST(T->kiri);
POST(T->kanan);
cout<<T->data<<" "; }
}
42
main (){
tree P;char x;int i,n;
P=NULL;
cout<<"banyak data : ";cin>>n;
for (i=1;i<=n;i++) {
x=(65+rand()%26); cout<<x<<" ";
BST(&P,x);
}
cout<<"pre : "; PRE(P); cout<<endl;
cout<<"In : "; IN(P); cout<<endl;
cout<<"post : "; POST(P);
getch();
}
Sebuah binary search tree (BST) adalah sebuah pohon biner yang boleh kosong, dan
setiap nodenya harus memiliki identifier/value. value pada semua node subpohon sebelah kiri
adalah selalu lebih kecil dari value dari parent/root, sedangkan value subpohon di sebelah
kanan adalah sama atau lebih besar dari value pada parent/root, masing – masing subpohon
tersebut (kiri&kanan) itu sendiri adalah juga BST. Sebagai gambaran berikut adalah sebuah
BST.
Operasi penambahan node/insert pada BST :
BST sebelum dilakukan Insert
BST setelah dilakukan Insert node 120
43
Sebuah BST, pada dasarnya adalah sebuah pohon biner (binary tree), oleh karena itu,
kita dapat melakukan traversal pada setiap node dengan metode inorder, preorder maupun
postorder. dan jika kita melakukan traversal dengan metode inorder, pada dasarnya kita telah
melakukan traversal valuenya secara terurut dari kecil ke besar, jadi ini sebagai sorting
algoritma.
Struktur data BST sangat penting dalam struktur pencarian, misalkan, dalam kasus
pencarian dalam sebuah larik, jika larik sudah dalam keadaan terurut maka proses pencarian
akan sangat cepat, jika kita menggunanan pencarian biner. Akan tetapi, jika kita ingin
melakukan perubahan isi larik (insert atau delete), menggunakan larik/array akan sangat
lambat, karena proses insert dan delete dalam larik butuh memindahkan banyak elemen setiap
saat. Sebaliknya binary tree memberikan jawaban sempurna atas semua permasalahan ini,
dengan memanfaatkan binary tree kita dapat melakukan pencarian elemen/node value dalam
kompleksitas algorimta O(n log n) langkah saja.
Kebanyakan aplikasi saat ini melakukan operasi penambahan dan penghapusan
elemen secara terus-menerus tanpa urutan yang jelas urutannya. Oleh karena itu sangatlah
penting untuk mengoptimasi waktu pencarian dengan menjaga agar pohon tersebut mendekati
seimbang/balance sepanjang waktu. Dan hal ini telah diwujudkan oleh 2 orang
matematikawan Russia , G.M. Adel’son-Vel’skii dan E.M. Landis. Oleh karena itu Binary
Search Tree ini disebut AVLtree yang diambil dari nama kedua matematikawan Russia
tersebut. Tujuan utama dari pembuatan AVL-Tree ini adalah agar operasi pencarian,
penambahan, dan penghapusan elemen dapat dilakukan dalam waktu O(log n) bahkan untuk
kasus terburuk pun. Tidak seperti Binary Search Tree biasa yang dapat mencapai waktu
O(1.44 log n) untuk kasus terburuk.
Dalam pohon yang benar-benar seimbang, subpohon kiri dan kanan dari setiap node
mempunyai tinggi yang sama. Walaupun kita tidak dapat mencapai tujuan ini secara
sempurna, setidaknya dengan membangun Binary Search Tree dengan metode penambahan
elemen yang nantinya akan kita bahas, kita dapat meyakinkan bahwa setiap subpohon kiri
dan kanan tidak akan pernah berselisih lebih dari 1. Jadi, sebuah AVL-Tree merupakan Binary
Search Tree yang subpohon kiri dan kanan dari akarnya tidak akan berselisih lebih dari 1 dan
setiap subpohon dari AVL-Tree juga merupakan AVL-Tree. Dan setiap simpul di AVL-Tree
mempunyai faktor penyeimbang (balance factor) yang bernilai left-higher (subpohon kiri >
kanan), equal-height (subpohon kiri = kanan), righthigher (subpohon kiri < kanan).
44
Proses balancing pada AVL-Tree dilakukan dengan cara :

Single Rotation (kiri dan kanan)

Double Rotation (kiri dan kanan)
Berikut contoh kedua proses tersebut :
AVL-Tree sebelum dilakukan insert 20
AVL-Tree setelah insert 20 dan single rotation kanan
AVL-Tree sebelum dilakukan insert 95
AVL-Tree setelah insert 95 dan double rotation
kanan
Penutup
Latihan Soal
1. Gambarlah Pohon Biner yang memenuhi informasi berikut :
Inorder
P
B
S
K
R
A
I
U
H
E
O
Preorder
A
K
P
S
B
R
U
I
O
E
H
2. Diberikan deretan data sebagai berikut:
50, 70, 60, 55, 65, 58, 68, 40, 80, 30, 75


Buatlah Binary Search Tree berdasarkan urutan data tersebut.
Buatlah AVL Tree berdasarkan urutan data tersebut.
45
BAB VII
ALGORITMA SORTING
Pendahuluan
Deskripsi Singkat
Pada bab ini akan dijelaskan tentang algoritma untuk mengurutkan data (Sorting)
yaitu Merge Sort dan Quick Sort serta Heap Sort beserta analisis algoritmanya.
Manfaat
Dengan memahami algoritma sorting yang termasuk kategori cepat dan efisien,
mahasiswa dapat menerapkan algoritma sorting untuk menyelesaikan permasalahan yang
lebih kompleks.
Relevansi
Materi ini memberi bekal untuk menyelesaikan permasalahan yang menggunakan
proses pengurutan data.
Learning Outcomes
Setelah mempelajari materi ini, mahasiswa memiliki pengetahuan tentang algoritma
sorting yang cepat dan efisien serta mampu membuat program implementasinya.
Penyajian
Pada bab ini dijelaskan beberapa algoritma pengurutan data (sorting), yaitu : Merge
Sort, Quick Sort (review) dan Heap Sort. Pengurutan atau sorting merupakan proses untuk
menyusun kembali kumpulan entri-entri yang telah dimasukkan dengan suatu aturan tertentu.
Secara umum ada 2 macam pengurutan yaitu pengurutan secara menaik (ascenden) dan
pengurutan secara menurun (descenden).
7.1 Algoritma Merge Sort dan Quick Sort
Algoritma Merge Sort dan Quick Sort algoritma yang dirancang dengan teknik devide
and conquer, yang paling optimal dan sangat cepat untuk mengurutkan data.
Algoritma merge sort membagi tabel menjadi dua tabel yang sama besar. Masingmasing tabel diurutkan secara rekursif, dan kemudian digabungkan kembali untuk
membentuk tabel yang terurut. Implementasi dasar dari algoritma merge sort memakai tiga
buah tabel, dua untuk menyimpan elemen dari tabel yang telah di bagi dua dan satu untuk
46
menyimpan elemen yang telah terurut. Namun algoritma ini dapat juga dilakukan langsung
pada dua tabel, sehingga menghemat ruang atau memori yang dibutuhkan.
Quick Sort adalah algoritma yang proses pembagian data dengan cara partisi
berdasarkan data pivot, biasanya data pertama, tanpa menggunakan memory tambahan
sehingga diharapkan lebih efisien dalam penggunaan memory.
Berikut adalah program tentang Merge Sort dan Quick Sort.
#include<iostream>
#include<stdlib.h>
#include<conio.h>
using namespace std;
typedef int larik[250001];
long long c=0;
int n,cc=0;
void cetakdata(larik x,int n)
{int i;
for (i=1;i<=n;i++) {
cout<<x[i]<<" ";
}
cout<<endl;
cout<<endl;getch();
}
void partisi(larik x,int aw,int ak,int &j)
{ int i,t,pivot;
pivot=x[aw];
i=aw;j=ak;
while (i<j){
while ((i<ak)&&(x[i]<=pivot)) {i++;cc++;}if(i<ak) cc++;
while ((j>aw)&&(x[j]>pivot)) {j--;cc++;}if(j>aw) cc++;
if (i<j) {t=x[i];x[i]=x[j];x[j]=t;}
}
x[aw]=x[j];x[j]=pivot;
}
void qsort(larik x,int aw,int ak)
{int j;
if (aw<ak) {
partisi(x,aw,ak,j);//cetakdata(x,n);
qsort(x,aw,j-1);
qsort(x,j+1,ak);
}
}
void merge(larik x, int aw,int mid,int ak)
47
{larik z;
int i,j,k,l;
i=aw; j=mid+1; k=aw;
do {
if(x[i]<=x[j]) {z[k]=x[i];i++;}
else {z[k]=x[j];j++;}
k++;}
while ((i<=mid) && (j<=ak));
if (i>mid) for (l=j;l<=ak;l++) {z[k]=x[l];k++;}
else for (l=i;l<=mid;l++) {z[k]=x[l];k++;}
for (k=aw;k<=ak;k++) x[k]=z[k];
}
void mergesort(larik x,int aw,int ak)
{int mid;
if(aw<ak) {
mid =(aw+ak)/2;
mergesort(x,aw,mid);
mergesort(x,mid+1,ak);
merge(x,aw,mid,ak);
}
}
void buatdata(larik x,int &n)
{int i;
cout<<"banyak data :";cin>>n;
// srand(time(NULL));
for (i=1;i<=n;i++) {
x[i]= rand()%100+1;
// cout<<x[i]<<" ";
}
cout<<endl;
// cout<<endl;
}
main()
{ int i,j;
larik x;
buatdata(x,n);
cetakdata(x,n);
clock_t begin_time = clock();
mergesort1(x,1,n);
cout << float( clock () - begin_time )/CLOCKS_PER_SEC;
cetakdata(x,n);
}
48
7.2 Algoritma Heap Sort
HeapSort adalah algoritma pengurutan data berdasarkan perbandingan, dan termasuk
golongan selection sort. Walaupun lebih lambat daripada quick sort pada kebanyakan mesin ,
tetapi heap sort mempunyai keunggulan yaitu kompleksitas algoritma pada kasus terburuk
adalah n log n.
Algoritma pengurutan heap sort ini mengurutkan isi suatu larik masukan dengan
memandang larik masukan sebagai suatu Complete Binary Tree (CBT).
Setelah itu Complete Binary Tree (CBT) ini dapat dikonversi menjadi suatu heap tree.
Setelah itu Complete Binary Tree (CBT) diubah menjadi suatu priority queue.
Algoritma pengurutan heap dimulai dari membangun sebuah heap dari kumpulan data yang
ingin diurutkan, dan kemudian menghapus data yang mempunyai nilai tertinggi dan
menempatkan dalam akhir dari larik yang telah terurut.
Setelah memindahkan data dengan nilai terbesar, proses berikutnya adalah membangun ulang
heap dan memindahkan nilai terbesar pada heap tersebut dan menempatkannya dalam tempat
terakhir pada larik terurut yang belum diisi data lain.
Proses ini berulang sampai tidak ada lagi data yang tersisa dalam heap dan larik yang terurut
penuh. Dalam implementasinya kita membutuhkan dua larik – satu untuk menyimpan heap
dan satu lagi untuk menyimpan data yang sudah terurut.
Tetapi untuk optimasi memori, kita dapat menggunakan hanya satu larik saja.
Yaitu dengan cara menukar isi akar dengan elemen terakhir dalam heap tree.
Jika memori tidak menjadi masalah maka dapat tetap menggunakan dua larik yaitu larik
masukan dan larik hasil.
49
Heap Sort memasukkan data masukan ke dalam struktur data heap.
Nilai terbesar (dalam max-heap) atau nilai terkecil (dalam min-heap) diambil satu per satu
sampai habis, nilai tersebut diambil dalam urutan yang terurut.
Algoritma untuk heap sort :
function heapSort(a, count)
input: sebuah larik tidak terurut a dengan panjang length
(pertama letakkan a dalam max-heap) heapify(a, count)
end = count -1
while end > 0 {
remove ( )
reheapify ( )
end = end – 1
}
Algoritma Heapify
Algoritma Heapify adalah membangun sebuah heap dari bawah ke atas, secara berturut-turut
berubah ke bawah untuk membangun heap. Permasalahan pertama yang harus kita
pertimbangkan dalam melakukan operasi heapify adalah dari bagian mana kita harus
memulai.
Bila kita mencoba operasi heapify dari akar maka akan terjadi operasi runut-naik seperti
algoritma bubble sort yang akan menyebabkan kompleksitas waktu yang ada akan berlipat
ganda. Sebuah versi lain adalah membangun heap secara atas-bawah dan berganti-ganti ke
atas untuk secara konseptual lebih sederhana untuk ditangani. Versi ini mulai dengan sebuah
heap kosong dan secara berturut-turut memasukkan data.
Versi lainnya lagi adalah dengan membentuk pohon heap-pohon heap mulai dari
subtree-subtree yang paling bawah. Jika subtree-subtree suatu simpul sudah membentuk heap
maka pohon dari simpul tersebut mudah dijadikan pohon heap dengan mengalirkannya ke
bawah. Setelah diuji, maka ide yang paling efisien adalah versi yang terakhir, yang
kompleksitas algoritmanya pada kasus terburuk adalah O(n), sedangkan versi membentuk
heap tree-heap tree dari atas ke bawah kompleksitas nya O(n log n).
Jadi, algoritma utama heapify adalah melakukan iterasi mulai dari internal simpul
paling kanan bawah (pada representasi larik, adalah elemen yang berada di indeks paling
besar) hingga akar, kemudian kearah kiri dan naik ke level di atasnya, dan seterusnya hingga
50
mencapai akar (sebagai larik [0..N-1]). Oleh karena itu, iterasi dilakukan mulai dari j= N/2
dan berkurang satu-satu hingga mencapai j=0. Pada simpul internal tersebut, pemeriksaan
hanya dilakukan pada simpul anaknya langsung (tidak pada level-level lain di bawahnya).
Pada saat iterasi berada di level yang lebih tinggi, subtree subtree selalu sudah membentuk
heap. Jadi, kasus akan mengalirkan simpul tersebut kearah bawah. Dengan demikian, heapify
versi ini melakukan sebanyak N/2 kali iterasi, dan pada kasus yang paling buruk akan
melakukan iterasi sebanyak log (N) kali.
Algoritma Remove
Algoritma remove ini menukar akar (yang berisi nilai maksimum) dari heap dengan elemen
terakhir. Secara logika, simpul yang berada paling kanabawah dipindahkan ke akar untuk
menggantikan simpul akar yang akan diambil.
Algoritma Reheapify
Algoritma reheapify ini melakukan pembuatan ulang heap dari atas ke bawah seperti halnya
iterasi terakhir dari algoritma metoda heapify. Perbedaan antara metode heapify dengan
metode reheapify ada pada iterasi yang dilakukan oleh kedua algoritma tersebut. Algoritma
metode reheapify ini hanya melakukan iterasi terakhir dari algoritma heapify. Hal ini
disebabkan baik subtree kiri maupun subtree kanannya sudah merupakan heap, sehingga
tidak perlu dilakukan iterasi lengkap seperti algoritma heapify. Dan setelah reheapify maka
simpul yang akan diiterasikan berikutnya akan berkurang satu.
Perbandingan Dengan Algoritma Pengurutan Lain
Heapsort hampir setara dengan quick sort, algoritma pengurutan data lain berdasarkan
perbandingan yang sangat efisien. Quick sort sedikit lebih cepat, karena cache dan faktorfaktor lain, tetapi pada kasus terburuk kompleksitasnya O(n), yang sangat lambat untuk data
yang berukuran sangat besar. Lalu karena heap sort memiliki (N log N) maka sistem yang
memerlukan pengamanan yang ketat biasa memakai heap sort sebagai algoritma
pengurutannya.
Heap
sort
juga
sering dibandingkan
dengan
merge
sort,
yang
mempunyaikompleksitas algoritma yang sama, tetapi kompleksitas ruang nya (n) yang lebih
besar dari heap sort. Heap sort juga lebih cepat pada mesin dengancache data yang kecil atau
lambat.
Dengan memanfaatkan struktur data pohon, kita bisa mendapatkan algoritma
51
pengurutan data yang mangkus yang bisa dimanfaatkan untuk membangun program aplikasi
yang baik. Algoritma pengurutan heap sort bisa dimasukkan ke dalam algoritma divide and
conquer yang disebabkan pembagian dilakukan dengan terlebih dahulu menerapkan
algoritma metoda heapify sebagai inisialisasi untuk mentransformasi suatu tree menjadi heap
tree, dan pada setiap tahapan diterapkan algoritma metoda reheapify untuk menyusun ulang
heap tree.
Penutup
Latihan Soal
1. Dengan menggunakan data input di bawah ini, Tuliskan urutan data sampai terurut
(acending) dan hitung berapa kali operasi perbandingan dilakukan, juga tentukan set data
tsb termasuk best, worst atau avaragecase?
42, 68, 35, 1, 70, 25, 79, 59, 63, 65, 6, 46, 82, 28, 62
jika digunakan algoritma :
a. Merge sort
b. Quick sort
c. Heap sort
2. Jelaskan kelebihan dan kekurangan dari algoritma merge sort, quick sort dan heap sort.
52
BAB VIII
ALGORITMA SEARCHING
Pendahuluan
Deskripsi Singkat
Pada bab ini akan dijelaskan tentang algoritma untuk mengurutkan data (Sorting)
yaitu Merge Sort dan Quick Sort serta Heap Sort beserta analisis algoritmanya.
Manfaat
Dengan memahami algoritma sorting yang termasuk kategori cepat dan efisien,
mahasiswa dapat menerapkan algoritma sorting untuk menyelesaikan permasalahan yang
lebih kompleks.
Relevansi
Materi ini memberi bekal untuk menyelesaikan permasalahan yang menggunakan
proses pengurutan data.
Learning Outcomes
Setelah mempelajari materi ini, mahasiswa memiliki pengetahuan tentang algoritma
sorting yang cepat dan efisien serta mampu membuat program implementasinya.
Penyajian
Pertama akan dibahas 2 algoritma pencarian data (Searching) yang biasa dilakukan,
yaitu pencarian sekuensial (sequential search) dan pencarian biner (binary search). Pencarian
sekuensial lebih cocok digunakan untuk mencari data pada sejumlah data yang belum terurut
sedangkan pencarian biner digunakan pada sejumlah data yang sudah terurut. Kemudian
dibahas metode pencarian dengan fungsi hashing.
8.1 Pencarian Sekuensial
Pada pencarian sekuensial, data yang dicari, dibandingkan satu per satu dengan data
pada suatu larik data.
Algoritmanya adalah sebagai berikut :
Misalkan dimiliki N data integer yang disimpan pada larik A, dan data yang dicari adalah X.
1. Ketemu = 0, indeks = 1.
2. Selama data belum ketemu (ketemu = 0) dan indeks
N:
a. Jika X = A[indeks], maka data ketemu, lalu nilai ketemu =1.
53
b. Jika X A[indeks], maka indeks = indeks +1
Kode programnya sebagai berikut :
while ((ketemu == 0) && (indeks <= N){
if (X = A[indeks]){
ketemu=1;}
else {
indeks = indeks +1;}
}
8.2 Pencarian Biner
Pencarian biner adalah metode pencarian data pada sekumpulan N data (larik) yang
sudah urut dengan prinsip membagi dua larik tersebut, kemudian data dicari pada salah satu
dari pecahan larik tadi. Jika data yang dicari nilainya lebih besar dari nilai tengah larik awal,
maka data dicari pada pecahan larik indeks tengah+1 sampai indeks N, jika tidak, maka data
dicari mungkin berada pada lariks indeks 1 sampai tengah-1.
Algoritmanya sebagai berikut :
Akan dicari data X pada larik A yang berjumlah N elemen. Larik A terurut naik (ascending).
1. Ketemu = 0, awal =1, akhir = N.
2. Selama ketemu = 0 dan awal
akhir , maka tengah = (awal +akhir) / 2 :

Jika X = A[tengah], maka ketemu =1.

Jika X < A[tengah], maka akhir =tengah- 1

Jika X > A[tengah], maka awal =tengah+1
Kode programnya sebagai berikut :
awal =1; akhir = N
while ((ketemu == 0) && (awal
akhir){
tengah = (awal + akhir) /2;
54
if (X = A[tengah]){
ketemu=1;}
else if (X < A[tengah]){
akhir = tengah-1;}
else awal = tengah +1;
}
8.3 Pencarian Dengan Fungsi Hashing
Pada metode-metode pencarian yang telah kita bahas di atas, secara umum banyaknya
pembandingan untuk mencari data atau rekaman yang diinginkan tergantung dari banyaknya
data atau rekaman yang diketahui. Jika setiap data atau rekaman bisaditemukan dengan sekali
pemasupan terhadap tabel yang digunakan untuk menyimpan data atau rekaman tersebut,
maka lokasi data atau rekaman dalam tabel hanya tergantung dari kunci yang digunakan dan
tidak tergantung dari kunci yang lain, seperti dalam pohon. Cara yang paling efisien untuk
mengorganisir tabel ini adalah dengan menggunakan larik. Jika kunci berupa integer, kunci
tersebut sekaligus bisa digunakan sebagai subskrip dari larik yang dimaksud.
Suatu fungsi untuk mengkonversikan suatu data ke nomor posisi dari larik yang
diketahui. Fungsi ini disebut dengan fungsi hash. Metode pencarian yang memanfaatkan
fungsi hash disebut hashing atau hash addressing. Tujuan utama dalam penentuan fungsi
hash adalah agar dua buah kunci yang berbeda tidak mempunyai nilai hash yang sama. Jika
hal ini terjadi, akan menyebabkan terjadinya tabrakan (hash collision / hash clash).
1. Fungsi Hash
Secara umum fungsi hash (H) adalah fungsi untuk mengkonversikan himpunan kunci
rekaman (K) menjadi himpunan alaman pengingat (posisi subskrib dalam larik / L) dan bisa
dituliskan dengan menggunakan notasi
H:K→L
Dua aspek penting yang perlu dipertimbangkan dalam pemilihan fungsi hash adalah
sebagai berikut. Pertama, fungsi H harus mudah dan cepat dicari atau dihitung. Kedua, fungsi
H sebisa mungkin mendistribusikan posisi yang dimaksud secara uniform sepanjang
himpunan L, sehingga banyaknya tabrakan yang mungkin terjadi bisa diminimalkan. Secara
alamiah, tidak ada garansi yang memungkinkan bahwa aspek kedua bisa dipenuhi tanpa
55
terlebih dahulu mengetahui kunci-kunci yang ada. Meskipun demikian, ada beberapa metode
untuk memotong-motong kunci dalam himpunan K menjadi kombinasi tertentu yang akan
dipakai sebagai fungsi H.
Berikut disajikan beberapa cara untuk memotong-motong kunci sehingga bisa
diperoleh fungsi hash yang dengan mudah bisa dihitung.
a. Metode Pembagian
Dalam cara ini kita bisa memlih suatu perubah m yang nilainya lebih besar dibanding
banyaknya kunci dalam K, misalnya n, dan biasanya dipilih suatu bilangan prima. Fungsi
hashnya ditentukan sebagai :
H(k) = k mod m atau H(k) = k mod m + 1
Persamaan pertama dipilih apabila diinginkan alamat kunci adalah 0 sampai m – 1.
Persamaan kedua dipilih jika diinginkan alamat kunci adalah 1 sampai m. Sebagai contoh,
nomor mahasiswa terdiri dari 5 buah digit. Misalkan L terdiri dari 100 buah alamat yang
masing-masing alamat terdiri dari 2 karakter : 00...99. Nomor mahasiswa yang diketahui
misalnya 10347, 87492, 34212 dan 88688. Untuk menentukan alamat dari keempat nomor
mahasiswa ini kita pilih suatu bilangan prima yang dekat dengan 99, misalnya m = 97.
Dengan menggunakan fungsi H(k) = k mod m, diperoleh H(10347) = 65, H(87492) =
95, H(34212) = 68, H(88688) = 30 Dengan demikian, nomor mahasiswa 10347 akan
disimpan dalam alamat 65, nomor mahasiswa 87492 akan disimpan dalam alamat 95, nomor
mahasiswa 34212 akan disimpan dalam alamat 68 dan nomor mahasiswa 88688 akan
disimpan dalam alamat 30.
Jika dipilih fungsi H(k) = k mod m + 1, maka keempat nomor mahasiswa diatas
masing masing akan disimpan dalam alamat 66, 96, 69 dan 31.
b. Metode Midsquare
Dalam metode ini, kunci yang diketahui dikuadratkan dan fungsi hash yang dipilih adalah :
H(k) = l
Nilai l diperoleh dengan menghapus digit-digit pada kedua sisi dari k2, dengan catatan bahwa
banyaknya digit di sebelah kiri dan sebelah kanan harus sama. Jika tidak sama, maka pada
digit di sebelah kiri seolah-olah ditambahkan sejumlah trailing zero, sehingga
akan menghasilkan alamat yang benar. Dengan menggunakan contoh yang sama dengan
diatas, maka alamat dari masing-masing nomor mahasiswa diatas adalah :
k:
2
k :
10347
87492
34212
107060409
76548500564 1170460944
88688
7865561344
56
H(k):
06
85
46
56
c. Penjumlahan Digit
Dalam penjumlahan digit, kunci yang diketahui bisa dipecah menjadi beberapa kelompok
yang masing-masing terdiri dari beberapa buah digit, misalnya dua buah. Kemudian digitdigit dari kelompok-kelompok yang ada dijumlahkan. Pemecahan dan penjumlahan terus
dilakukan jika jumlah keseluruhan kelompok yang ada masih lebih besar dari banyaknya
alamat yang akan dipakai. Dengan menggunakan nomor mahasiswa diatas, maka alamat dari
masing-masing nomor mahasiswa bisa ditentukan sebagai berikut (dalam hal ini digunakan
kelompok dengan dua buah digit, karena alamatnya diketahui dari 00 sampai 99) :
H(10347) = 1 + 03 + 47 = 51
H(87492) = 8 + 74 + 92 = 174 = 1 + 74 = 75
H(34212) = 3 + 42 + 12 = 57
H(88688) = 8 + 86 + 88 = 182 = 1 + 82 = 83
2. Cara Mengatasi Tabrakan
Tujuan dari pemilihan fungsi hash adalah untuk menempatkan rekaman pada alamat tertentu,
sehingga bisa dihindari adanya tabrakan, yaitu suatu keadaan dimana dua buah atau lebih
rekaman yang mempunyai data kunci yang berbeda mampunyai alamat hash yang sama.
Meskipun demikian, kekmungkinan adanya tabrakan selalu tetap saja terjadi, meskipun kita
sudah menentukan fungsi hash yang cukup baik. Dengan demikian, kita harus mempunyai
satu cara untuk mengatasi tabrakan yang mungkin terjadi, yang disebut dengan collision
resolution.
Prosedur yang baik untuk mengatasi adanya tabrakan gayut antara lain terhadap
perbandingan banyaknya data kunci (n) dalam K, dan banyaknhya alamat hash (m) dalam
L. Perbandingan ini, λ = n/m, disebut faktor beban. Lebih lanjut, efisiensi fungsi hash yang
dilengkapi
dengan
prosedur
untukmengatasi
tabrakan
diukur
dengan
banyaknya
pembandingan kunci (probe) yang diperlukan untuk mencari alamat dari rekaman yang
mempunyai kunci k. Efisiensi ini gayut terhadap faktor beban dan diukur menggunakan dua
besaran berikut ini :
B(λ) = rata-rata probe untuk pencarian yang berhasil
G(λ) = rata-rata probe untuk pencarian yang gagal
57
a. Pengalamatan Terbuka
Secara umum, cara mengatasi tabrakan dengan pengalamatan terbuka (open addressing) bisa
dijelaskan sebagai berikut. Dimisalkan sebuah rekaman dengan kunci k akan disisipkan ke
dalam tabel alamat hash. Berdasarkan fungsi hash yang dipakai, alamat untuk kunci k
tersebut dihitung, misalnya pada alamat h. Jika kemudian ternyata bahwa alamat h sudah
terisi, maka harus dicari alamat lain yang masih kosong. Cara yang termudah adalah dengan
mencari alamat berikutnya yang kosong. Cara ini disebut dengan linear probing.
Dari gambaran diatas kita bisa melihat, bahwa untuk mencari rekaman dengan kunci
k, harus dilakukan pencarian pada alamat h, h + 1, h + 2, ... dan seterusnya.
Berdasarkan hal ini, rata-rata pencarian yang berhasil dan tidak berhasil adalah :
B(λ) = ½ (1 + 1/(1 - λ)) , G(λ) = ½ (1 + 1/(1 - λ)2)
Dari gambaran diatas bisa dilihat satu kerugian yang utama dari linear probing ini adalah
data cenderung untuk mengumpul pada satu tempat. Hal ini bisa dipahami karena jika ada
suatu data yang akan disisipkan pada suatu alamat dan alamat yang dimaksud sudah dipakai,
maka data baru tersebut akan ditempatkan pada lokasi berikutnya yang letaknya berurutan.
Kedua cara ini disebut dengan quadratic probing atau double hashing.
Dalam quadratic probing, jika alamat untuk suatu data baru yang akan disisipkan
sudah dipakai (misalnya alamat h), maka data baru tersebut tidak ditempatkan pada posisi h +
1 atau h + 2 (alamat h + 1 juga sudah dipakai) dan seterusnya, tetapi data baru akan
diletakkan pada alamat dengan urutan
h, h + 1, h + 4, h + 9, ...
Dengan demikian, pencarian akan dilaksanakan pada alamat diatas. Hal ini membawa
keuntungan, bahwa jika banyaknya alamat yang tersedia adalah merupakan bilangan prima,
cara diatas akan melakukan pencarian pada separuh dari seluruh alamat yang ada dalam
doubel hashing yang digunakan dua buah fungsi hash untuk menghindari adanya tabrakan.
Secara sederhana cara ini bisa dijelaskan sebagai berikut. Dari kunci k ditentukan alamat
hash-nya yang pertama, misalnya H(k) = h. Kemudian ditentukan alamat hash yang kedua,
misalnya H’(k) = h’ ≠ m (denga m adalah banyaknya alamat hash yang dihasilkan darifungsi
hash yang pertama). Dengan demikian, pencarian dilakukan secara urut pada alamat alamat :
h, h + h’, h + 2h’, h + 3h’, ...
Satu kerugian yang cukup mendasar dalam sistem pengalamatan terbuka adalah sebagai
berikut. Dimisalkan bahwa kita akan menyisipkan sebuah rekaman baru, misalnya rek2, yang
akan menempati alamat x pada tabel hash. Tetapi karena alamat x sudah terisi, maka rekaman
58
rek2 ini akan ditempatkan pada lokasi kosong yang pertama sesudah alamat x, misalnya x1.
Sekarang misalnya rekaman yang ada pada alamat x dihapus. Dengan demikian, maka alamat
x sekarang menjadi kosong. Jika kemudian kita akan mencari rekaman rek2 kita akan
mendapatkan kenyataan bahwa program mungkin tidak akan mendapatkan kenyataan bahwa
program mungkin tidak akan menemukan rekaman tersebut meskipun sesungguhnya ada.
Sebabnya adalah bahwa pada saat rekaman rek2 akan dicari, maka berdasar fungsi hash yang
dipakai, rekaman tersebut akan menempati alamat x. Tetapi karena sekarang alamat x sudah
kosong, maka program tidak akan meneruskan pencariannya ke alamat-alamat yang lain.
Salah satu cara untuk mengatasi persoalan diatas adalah dengan memberi tanda
khusus pada alamat-alamat yang isi sesungguhnya sudah dihapus. Dengan demikian program
akan meneruskan pencarian jika program membaca alamat yang diberi tandai “dihapus”.
Tetapi persoalan lain bisa timbul, yaitu jika hampir semua alamat diisi dengan tanda
“dihapus”. Dengan cara ini, maka pencarian bisa menjadi pencarian berurutan.
b. Penggandengan
Penggandengan (chaining) merupakan metode lain yang digunakan untuk mengatasi
kemungkinan adanya tabrakan alamat hash. Metode ini pada prinsipnya memanfaatkan
senarai berantai (yang juga bisa diimplementasikan menggunakan larik) yang dipasang pada
setiap alamat hash yang diketahui. Dengan demikian, kika kita melihat pada sebuah alamat
hash lengkap dan senarai yang menyimpan rekamanrekaman yang mempunyai alamat hash
yang sama, maka kita akan melihat adanya sebuah senarai berantai tunggal berkepala denga
kepalanya adalah alamat hash.
Sebagai contoh, jika kita mempunyai rekaman-rekaman yang kunci rekamannya bisa
dituliskan sebagai
34 56 123 78 93 70 100 21 11 77 28
dan fungsi hash yang dipilih adalah k mod 10. Dengan demikian, alamat hash akan terdiri
dari sepuluh buah alamat yang bernomor 0 samapi 9 sebagai berikut :
0 : 70  100
1 : 21  11
2:
3 : 123  93
4 : 34
5:
6 : 56
7 : 77
8 : 78  28
9:
59
Hal ini menunjukkan bahwa alamat hash sebaiknya menggunakan senarai berantai untuk
menyimpan rekaman-rekaman diatas, yaitu kita bisa menyusun struktur data untuk
menyajikan metode penggandengan dengan menggunakan link list.
Penutup
Latihan Soal :
1. Buatlah program untuk menyimpan sejumlah N data mahasiswa yang terdiri dari NIM,
Nama, dan IPK, lalu buatlah fungsi untuk menampilkan data mahasiswa dengan NIM
tertentu.
2. Buatlah program pencarian biner secara rekursif.
3. Buatlah sebuah program untuk menyelesaikan proses mapping pada nomor telepon yang
ada di Telkom dengan menggunakan metode Hashing. Data yang ada berupa struktur yang
terdiri dari no telpon, nama, alamat pelanggan. Program memberikan pilihan berupa
menampilkan data, menambah data, menghapus data.
4. Buatlah sebuah program untuk menyelesaikan proses mapping pada sistem jaringan
komputer yang ada di PENS dengan menggunakan metode Hashing. Data yang ada berupa
struktur yang terdiri dari no IP, nama komputer, letak komputer. Program memberikan
pilihan berupa menampilkan data, menambah data, menghapus data.
5. Jika diketahui data key adalah :
32, 83, 49, 88, 97, 24, 87, 8, 78, 26, 89, 71
Menggunakan fungsi hash dengan metode sisa pembagian (key mod P) + 1, tempatkan key
tersebut pada larik H1, jika terjadi tabrakan gunakan metode linked dan kemudian tentukan
rata-rata pencariannya. {P: bilangan prima terkecil yang >n}
selanjutnya tempatkan key tersebut pada larik H2, jika terjadi tabrakan gunakan linear
probing dan kemudian tentukan rata-rata pencariannya.
60
BAB IX
PENGENALAN OOP
Pendahuluan
Deskripsi Singkat
Pada bab ini akan dijelaskan tentang materi pengenalan Object Oriented Programming
(OOP) meliputi pengenalan bahasa pemrograman Java, prinsip dasar OOP dan contoh
implementasi dalam java.
Manfaat
Dengan memahami dasar – dasar pemrograman berorientasi objek, mahasiswa dapat
menerapkan algoritma sorting untuk menyelesaikan permasalahan yang lebih kompleks.
Relevansi
Materi ini memberi bekal untuk menyelesaikan permasalahan yang menggunakan
proses pengurutan data.
Learning Outcomes
Setelah mempelajari materi ini, mahasiswa memiliki pengetahuan tentang algoritma
sorting yang cepat dan efisien serta mampu membuat program implementasinya.
Penyajian
Pemrograman berorientasi objek (OOP) sangat ampuh dan merupakan paradigma alami untuk
membuat program yang dapat bertahan terhadap kemungkinan perubahan yang berkaitan
dengan pertumbuhan dan pertambahan umur sistem apapun. Karena anda telah memahami
fungsi masing-masing objek dan memiliki antar muka yang jelas dan layak antar objek anda
dapat mengatur ulang bagian yang sama dari sistem yang lama tanpa takut-takut.
Para guru besar ilmu komputer mengajarkan mahasiswa mereka untuk berpikir
terorientasi objek selama bertahun-tahun sebelum mereka belajar bahasa pemrograman
dimana mereka secara langsung menerapkan konsep tersebut. Pendekatan ini disebut
rancangan atas-bawah (top-down design). Anda diajari untuk memikirkan masalah pertama
kali dalam bentuk paling abstrak baru kemudian mendefinisikan subrutin yang berkaitan
dengan implementasi yang lebih konkrit. Anda juga diajari untuk menghindari pembuatan
variabel global dan melewatkan pointer ke dalam struktur.
Semakin banyak anda menggunakan variable global untuk menjaga agar program
berjalan dengan baik semakin banyak variabel yang mengarah kepada bencana kegagalan
61
karena banyak interaksi antar program yang anda buat tak terlihat. Bahasa berorientasi objek
sejati menyediakan mekanisme yang dikenal sebagai enkapsulasi, inheritansi dan
polimorfisme.
9.1 Pengenalan Bahasa Pemrograman Java
Java adalah satu dari beberapa kemajuan terpenting di bidang software komputer dalam 20
tahun terakhir. Sama pentingnya dengan HyperText Markup Language(HTML) yang sangat
sukses dalam penerbitan homepage static di World wide Web (WWW). Java meledakkan
internet dengan isi yang lebih menarik dan interaktif.
Ada tiga kombinasi kunci yang membuat Java menjadi teknologi yang secara
fundamental berbeda dari yang lain yang ada saat ini. Pertama dan yang paling menarik
adalah semua orang dapat menggunakan applet yang kecil, aman, dinamik, lintas platform,
aktif dan siap dijalankan di jaringan. Sejak awal, Applet dapat disusun dan didstribusikan
secara aman dalam bentuk homepage semudah aspek-aspek HTML.
Kedua, Java adalah bahasa pemrograman yang ampuh dan memiliki kekuatan desain
berorientasi objek dengan sintaks yang sederhana dan mudah dikenal disertai dukungan
lingkungan yang kokoh serta enak digunakan. Java memungkinkan programmer untuk
membuat
program
dan
komponen
dan
applet
baru
yang
lebih
menarik.
Ketiga, Java adalah kumpulan class objek yang ampuh sehingga dapat melayani programmer
dengan uraian yang jelas untuk menerangkan berbagai fungsi sistem yang umum seperti
pembuatan window, penggunaan jaringan dan input / output. Kunci class-class ini adalah
kemampuannya yang dapat melayani aplikasi lintas platform untuk beragam variasi yang
umum digunakan sebagai antarmuka sistem.
1. Sejarah Java
Java mulai dirilis pada tahun 1990 sebagai bahasa program yang disebut Oak, Kemudian Sun
MycroSystem mendirikan kelompok kerja yang terdiri atas para programmer handal untuk
membuat produk baru dan memperluas pasar Sun. Oak didesain pertama kali untuk personal
digital assistance yang disebut *7 yang akan dipasrkan Sun dengan fasilitas Graphical User
Interface.
Ternyata *7 tidak pernah dipasarkan dan secara kebetulan Sun membentuk suatu
perusahaan yang disebut Firstperson untuk mengembangkan *7 dalam bentuk TV set-top
boxes untuk televisi interaktif. Karena persaingan yang begitu ketat akhirnya prospek TV
interaktif menurun dan akhirnya Oak tidak laku di pasaran. Akan tetapi semenjak FirstPerson
dan Oak mengalami kegagalan bermunculanlah para perintis internet khususnya World Wide
62
Web seperti Netscape yang mulai membuat software yang memungkinkan terjadinya koneksi
antara Internet dengan WWW. Sun akhirnya menyadari bahwa Oak memiliki kemungkinan
besar untuk membuat jalur akses ke dunia Web. Tidak lama kemudian Oak diluncurkan di
Internet dengan nama baru, yaitu Java.
Sekarang ini Java masih dalam taraf pengembangan dan sudah mulai mempengaruhi
arah pemrogaman komputer dan internet. Bahasa pemrograman Java dirilis secara gratis di
internet dan Sun memberikan lisensi penuh terhadap implementasi Java dan segala
komponennya untuk digunakan di berbagai vendor software Internet dengan harapan supaya
dapat menciptakan standard bagi pemrograman web
Modul objek Java adalah sederhana dan mudah dikembangkan namun sejalan dengan
itu, bilangan dan tipe data sederhana lain dianggap sebagai non objek berkinerja tinggi.
Kebanyakan sistem berorientasi objek lain memilih hirarki objek yang kaku dan susah diatur
atau memilih menggunakan model objek dinamik yang tidak memiliki kinerja tinggi dan
kelengkapan . Java sekali lagi memiliki keseimbangan yang menyediakan mekanisme pengclass-an sederhana dengan model antarmuka dinamik yang intuitif hanya jika diperlukan.
Memahami gaya pemrograman berorientasi objek sangat penting dan membantu mempelajari
bagaimana membuat program dengan Java.
2. Contoh Program Java
Pada subbab ini kita akan langsung menulis mengcompile dan menjalankan program "Hello
World" yang banyak digunakan sebagai contoh pada bahas lain. Kemudian kita akan
menelusuri contoh pada bahasa lain. Kemudian kita akan menelusuri contoh sederhana ini
baris demi baris untuk mengenal dasar pemrograman Java yang berhubungan dengan isi dua
bab awal. Setelah itu, kita akan mendefinisikan semua unsur penting tata bahasa yang
diterima oleh compiler Java termasuk spasi kosong (whitespace), komentar (comment), kata
kunci (keywords), pengenal (identifier), literal, operator dan pemisah (separator). Di akhir
bab, kita telah melengkapi bangunan fondasi bahasa Java sehingga anda mungkin telah
mampu mengenal dan menemukan cara sendiri untuk membuat program Java yang baik.
Hello World
class HelloWorld
{
public static void main ( String args[] )
{
System.out.println ( "Hello World ") ;
63
}
}
Java membutuhkan semua program berada dalam suatu class yang diberi nama tertentu. Anda
harus menyimpan file teks ini dalam file dengan nama HelloWorld.java; pastikan besar
kecilnya huruf nama file sama dengan nama class. Peraturan penggunaan nama file yang
sama dengan nama class ini nantinya akan membantu saat anda menjalankan program.
Java memiliki delapan tipe data sederhana, yaitu: byte, short, int, long, char, float,
double dan Boolean. Berikut ini adalah pembahasan masing-masing tipe data :
Berikut ini adalah contoh program mengenai tipe data
class SimpleType
{
public static void main (String args[] )
{
byte b=100;
short s=30000;
int i = 1000000;
long l = 4123456789;
char c = 'a';
double d = .00001234;
boolean bool = true;
System.out.println("byte b
= "+b);
System.out.println("short s
= "+s);
System.out.println("int i
= "+i);
System.out.println("long l
= "+l);
System.out.println("char c
= "+c);
System.out.println("double d
= "+d);
System.out.println("boolean bool = "+bool);
}
}
Hasilnya adalah :
byte b
= 100
short s
= 30000
64
int i
= 1000000
long l
= 4123456789
char c
=a
double d
= 1.234E-005
boolean bool = true
9.2 Prinsip dasar OOP
1. Enkapsulasi
Semua program pada tingkat paling sederhana terdiri dari dua hal: program dan data. Pada
model pemrograman tradisional data dialokasikan pada memori dan diolah oleh program
yang ada dalam subrutin atau fungsi. Enkapsulasi program yang mengolah data dengan
deklarasi dan penyimpanan data adalah kunci dari rancangan berorientasi objek.
Enkapsulasi dapat dipikirkan sebagai bungkusan pelindung program dan data yang sedang
diolah. Pembungkus ini mendefinisikan perilaku dan melindungi program dan data agar tidak
diakses sembarangan oleh program lain
Pada Java, dasar enkapsulasi adalah class. Anda membuat suatu class yang
menyatakan abstraksi dari sekelompok objek yang berbagi struktur dan sifat yang sama.
Objek adalah keadaan tertentu suatu class yang memepertahankan struktur dan sifat
sebagaimana didefinisikan oleh class tersebut seolah-olah keluar dari cetakan class yang
sama. Objek-objek ini sering di sebut sebagai instan dari class. Struktur tertentu atau
representasi data dari suatu class didefinisikan oleh sekumpulan variabel instan. Variabelvariabel ini menyimpan keadaan dinamis setiap instan suatu class. Sifat dan antarmuka suatu
class didefinisikan dengan methods yang beroperasi pada data instan tersebut. Method adalah
perintah untuk melakukan beberapa aksi terhadap sebuah objek. Perintah ini sangat mirip
dengan pemanggilan subrutin dalam bahasa prosedural.
Karena tujuannya mengkapsulasi kesulitan ada mekanisme untuk menyembunyikan
kerumitan implementasi dari class. Setiap method atau variable dalam class menunjukkan
semua yang perlu atau harus diketahui oleh pemakai. Anda dapat menyatakan method dan
data instan sebagai private sehingga tidak dapat diakses oleh program lain di luar
implementasi class anda. Interface public harus dipilih dengan hati-hati supaya tidak terlalu
banyak membuka bagian dalam class. Enkapsulasi ini bekerja dua arah karena anda yakin
tidak akan secara tidak sengaja mempengaruhi bagian lain system dengan program dan data
65
private anda dapat membuat program dan dengan bebas dan nyaman dan menelusuri program
dengan penuh kepastian.
Apa beda class dengan instan? Class adalah sesuatu yang menjelaskan atribut dan
umum sebuah objek termasuk tipe setiap atribut method yang dapat mengoperasikan objek
tersebut . Sebuah instance adalah keadaan tertentu sebuah class objek.
2. Inheritansi
Sebagian besar kita melihat lingkungan kita sebagai objek yang saling terhubung secara
hirarkis, misalnya binatang, mamalia dan anjing. Jika kita ingin menggambarkan binatang
secara garis besar kita dapat mengatakan binatang memiliki ciri-ciri tertentu misalkan ukuran
kecerdasan dan jenis sistem kerangka tulangnya. Binatang juga memiliki aspek perilaku
tertentu mereka makan bernafas dan tidur. Penjelasan tentang struktur tubuh dan perilaku ini
adalah penjelasan class binatang.
Jika anda ingin menjelaskan lebih terinci suatu class binatang misalkan mamalia maka
harus dirinci ciri-ciri lain misalkan jenis gigi dan periode kehamilan. Ini dikenal sebagai subclass binatang di mana binatang adalah super class mamalia.
Karena mamalia secara sederhana lebih tepat dikhususkan sebagai suatu kelompok binatang
maka mamalia mewarisi (inherit) semua ciri-ciri binatang. Secara lebih mendalam penurunan
subclass diturunkan dari setiap moyang-nya dalam hirarki class.
Inheritansi juga berinteraksi dengan enkapsulasi. Jika suatu class tertentu
mengenkapsulasi sejumlah atribut. maka subclass manapun akan memiliki atribut yang sama
ditambah dengan bagian dari spesialisasinya. Ini adalah konsep kunci yang membuat
kerumitan program berorientasi objek berkembang secara linier tidak geometris. Sub-class
yang baru mencakup semua perilaku dan spesifikasi moyangnya. Sub-class tersebut tidak
memiliki interaksi tak terduga dengan sebagian besar bagian program di sistem.
3. Polimorfisme
Methode pada objek adalah informasi yang dilewatkan sebagai parameter untuk permintaan
method / parameter ini mewakili nilai yang dimasukkan ke suatu fungsi dan harus dikerjakan
oleh suatu method. Pada bahasa pemrograman fungsional yang lain untuk melengkapi dua
pekerjaan yang berbeda diperlukan dua fungsi terpisah dengan nama yang berbeda.
Polimorfisme yang berarti satu objek dengan banyak bentuk adalah konsep sederhana yang
memperbolehkan method memiliki beberapa implementasi yang dipilih berdasarkan tipe
objek yang dilewatkan pada pengerjaan metode. Ini dikenal sebagai overloading method.
66
9.3 Pengertian dan implementasi instance dalam Java
Class :
Referensi Objek
Class mendefinisikan bentuk dan sifat suatu objek.setiap class baru yang anda dapat buat
menambahkan tipe lain yang dapat diperlakukan sebagai tipe sederhana. Jadi, jika Anda
mendeklarasikan variabel baru, Anda dapat menggunakan nama suatu class sebagai tipenya.
Variabel seperti itu kemudian merujuk pada instans atau objek class tersebut. Variabelvariabel ini dikenal sebagai referensi objek. Semua referensi objek juga cocok dengan instan
sub-class dari tipe-tipe yang dideklarasikannya. Seperti kita menyatakan byte untuk variabel
yang dideklarasikan int, Anda boleh juga mendeklarasikan sebuah variabel sebagai Object
dan menyimpan sebuah referensi ke suatu instans dari sembarang sub-class Object.
Variabel Instans
Data dienkapsulasi dalam suatu class dengan mendeklarasikan variabel di antara tanda
kurung kurawal deklarasi class. Variabel yang dideklarasikan dalam cakupan ini dikenal
sebagai variabel instans. Cara mendeklarasikan variabel instans sama persis dengan cara yang
kita lakukan untuk mendeklarasikan variabel lokal dalam contoh-contoh sebelumnya, kecuali
Anda
mendeklarasikannya
di
luar
cakupan
method
tertentu,
seperti
main.
Contohnya berikut ini adalah program yang mendeklarasikan class dengan nama Point
dengan dua variabel instans integer bernama x dan y.
class Point {
int x , y;
}
Operator new
Operator new menghasilkan instans tunggal dari suatu class dan menghasilkan referensi ke
objek tersebut. Berikut ini contoh sebuah instans baru dari Point yang dibuat dan disimpan
dalam variabel p.
point p = new point()
Di sini p adalah referensi ke sebuah instans dari Point.
Berikut ini contoh yang menghasilkan objek Point tunggal , tetapi menciptakan dua variabel
yang merujuk kepadanya.
Point p = new point();
Pointp2 = p;
67
Perubahan apapun ke objek yang dirujuk p2 akan mempengaruhi objek yang sama yang
dirujuk oleh p. Pernyataan p ke p2 tidak mengalokasikan memori atau menyalin bagian
apapun dari objek asli. Kenyataannya , pernyataan untuk p pada baris kedua contoh di atas
akan melepaskan kaitan p dari objek asli tanpa mempengaruhi objeknya, seperti contoh
berikut
Point p = new point();
Point p2 = p ;
P = null;
Meskipun p telah dibuat null , p2 tetap menunjuk ke objek yang dibuat dengan operator new.
Operator Dot (.)
Operator dot (.) digunakan untuk mengakses variabel instans dan method di dalam objek.
Berikut ini bentuk umum untuk mengakses variabel instans dengan operator dot.
0bjectreference . variablename
Di sini objectreference adalah referensi ke suatu objek dan variablename adalah nama
variabel instans di dalam objek yang ingin anda akses.
Cuplikan program berikut ini menunjukkan bagaimana operator dot dapat digunakan untuk
menyimpan suatu ke dalam variabel instan.
p.x = 10 ;
p.y = 20 ;
Baris program berikut ini menunjukkan bagaimana merujuk ke suatu nilai variabel instans
dengan operator dot.
System.out.println("x = " + p.x + " y = " + p.y);
Deklarasi method
Method dideklarasikan di dalam definisi class di tingkat yang sama dengan variabel instans.
Anda harus memanggil method dalam konteks instans tertentu class tersebut. Method dapat
merujuk langsung ke variabel instans tanpa menggunakan operator dot seakan-akan mereka
itu variabel local yang dideklarasikan di luar cakupan.
Method dideklarasikan untuk memiliki nilai keluaran dengan tipe tertentu dan sekumpulan
parameter masukan.. Bentuk umum deklarasi method adalah :
68
type method name (formal-parameter-list) {
method-body;
}
Type adalah tipe besaran yang akan dikeluarkan oleh method, termasuk void jika tidak ada
nilai yang akan dikeluarkan. Method name adalah sembarang identifier yang berlaku selain
yang
telah
dipakai
untuk
nama
class
di
dalam
cakupan
yang
bersangkutan.
formal-parameter-list adalah urutan pasangan tipe dan identifier yang dipisahkan dengan
koma.
Pemanggilan method
Method dipanggil pada instans suatu class dengan menggunakan operator dot (.). Bentuk
umum pemanggilan method ditunjukkan di bawah ini ;
Objectreference.methodname (parameter-list)
Objectreference adalah sembarang variabel yang merujuk ke suatu objek , method name
adalah nama suatu method dalam class yang dideklarasikan sebagai objectreference, dan
parameter-list adalah besaran atu pernyataan yang dipisahkan dengan koma yang jumlah dan
tipenya cocok dengan method yang dideklarasikan sebagai method name dalam class yang
bersangkutan.
Point p = new (Point);
p.init(10 , 20) ;
Contoh ini membuat instan baru dari Point , menyimpan referensinya dalam p. Kemudian
operator dot digunakan untuk memanggil method init pada instans yang bersangkutan,
melewatkan 10 dan 20 secara berurutan untuk parameter a dan b . Pernyataan x ke 10 dan y
ke 20 dilakukan dan method menghasilkan nilai.
this
Java memasukkan suatu besaran referensi khusus yang disebut this yang digunakan di dalam
method yang dirujuk untuk objek yang sedang berlaku. Nilai this merujuk pada objek dimana
method yang sedang berjalan dipanggil. Anda dapat menggunakan this disembarang tempat
dimana dibutuhkan referensi ke suatu objek dari class yang berlaku. Pada contoh sebelum ini
kita menggunakan p.init tetapi saat kita berada pada method init, this akan menunjuk ke objek
yang sama dengan p. Jika objek lain mnggunakan program yang sama dikirim melalui instans
lainnya maka masing-masing objek tersebut akan memiliki hasil this-nya sendiri.
Di dalam Java tidak diperbolehkan mendeklarasikan dua variabel lokal dengan nama yang
sama di dalam cakupan yang sama. Yang menarik, diperbolehkan untuk mendeklarasikan
69
variabel lokal termasuk parameter formal suatu method yang tumpang tindih dengan nama
variabel instan. Anda akan melihat bahwa kita tidak menggunakan x dan y sebagai nama
parameter untuk method init karena mereka akan menyembunyikan variabel instan x dan y
sebnarnya untuk cakupan method tersebut. Jika kita lakukan, maka x akan merujuk pada
parameter formal, menyembunyikan variabel instan x. this justru memperbolehkan kita
merujuk langsung ke objeknya sendiri bukannya membiarkan cakupan yang berlaku
mendefinisikan aturan-aturan resolusi variabel kita. Berikut ini versi lain init yang
menggunakan x dan y untuk nama parameter formal dan kemudian menggunakan this untuk
mengakses variabel instans objek yang berlaku pada saat itu.
void
init (int x, int y) {
this.x = x ;
this.y = y;
}
Contoh TwoPoints dapat memanfaatkan method inisialisasi baru untuk init seperti
ditunjukkan di bawah ini
class Point {
int x;
int y;
void init (int x, int y) {
this.x = x;
this.y = y;
}
}
class TwoPointsInit {
public static void main( String args[] ) {
Point p1 = new Point();
Point p2 = new Point();
p1.init(10, 20);
p2.init(42, 99);
System.out.println("x = "+ p1.x + " y = "+ p1.y);
70
System.out.println("x = "+ p2.x + " y = "+ p2.y);
}
}
Contoh ini menunjukkan pembuatan dua objek Point dan method init mereka yang terkait
yang dipanggil dengan pasangan nilai yang berbeda. Keluaran program ini sama dengan
contoh program TwoPoints sebelumnya.
Konstruktor
Menginisialisasi semua variabel dalam class setiap kali instans dibuat sangatlah
membosankan. Bahkan jika anda membuat fungsi yang sederhana seperti init dia atas tetap
lebih sederhana dan singkat jika semua yang diperlukan telah siap saat objek dibuat. Untuk
alasan ini, class dapat mengimplementasikan method khusus yang disebut konstruktor.
Konstruktor adalah method yang menginisialisasi objek segera setelah pembuatannya.
Konstruktor tersebut memiliki nama yang sama persis dengan class tempatnya. Sebenarnya
anda tidak dapat membuat method yang bernam sama dengan class-nya. Sekali didefinisikan,
konstruktor secara otomatis segera dipanggil sebelum operator new selesai bekerja.
Konstruktor kelihatan agak aneh karena tidak memiliki tipe keluaran, bahkan tidak memiliki
void sekalipun. Ini karena tipe hasil implisit konstruktor adalah menginisialisasi semua
keadaan internal suatu objek sehingga program yang menghasilkan instan dengan operator
new akan segera memiliki objek yang baik dan berguna.
Berikut ini adalah class point, di sini dapat kita lihat bagaimana cara menginisialisasi kedua
variabel instans sambil membentuk objek. Disini method init dari contoh terakhir digantikan
dengan method yang kelihatannya sangat mirip tetapi berbagi nama dengan class-nya dan
tidak memiliki tipe hasil.
class Point {
int x, y;
Point(int x, int y) {
this.x = x;
this.y = y;
}
}
class PointCreate {
public static void main(String args[] ) {
Point p = new Point( 10, 20);
71
System.out.println("x = " + p.x +" y = " + p.y);
}
}
Method konstruktor dipanggil tepat setelah instans dibuat dan sebelum new menghasilkan
nilai untuk pemanggilnya. Daftar parameter yang dispesifikasikan setelah nama class dalam
pernyataan new digunakan untuk melewatkan parameter ke konstruktor yang tepat. Contoh
sebelumnya yang menggunakan newPoint() memanggil konstruktor Point(), yang dibuat
default oleh konstruktor object () superclass.
Overloading Method
Dalam pemrograman Java, mungkin kita seringkali menginginkan pembuatan lebih dari satu
method dengan nama sama tetapi dengan daftar parameter yang berbeda. Ini disebut
overloading method. Overloading method digunakan untuk melayani sifat polimorfik Java.
Contoh berikut ini adalah versi class Point yang menggunakan overloading method untuk
menghasilkan konstuktor alternatif yang membuat beberapa nilai default untuk koordinat x
dan y.
class Point {
int x;
int y;
Point(int x, int y) {
this.x = x;
this.y = y;
}
Point() {
x = -1;
y = -1;
}
}
class PointCreateAlt {
public static void main(String args[] ) {
Point p = new Point();
System.out.println("x = " + p.x +" y =" + p.y);
}
72
}
Contoh ini menghasilkan sebuah objek Point yang memanggil konstruktor kedua tanpa
parameter, berbeda dengan yang pertama. Ini adalah keluarannya.
x = -1 y = -1
Penutup
Latihan soal
1.
Jelaskan tentang Object dan Class?
2.
Apa yang ada dalam sebuah class?
3.
Ciri utama OOP ada 3, jelaskan !
4.
Apa perbedaan public, private, protected?
5.
Jelaskan tipe data class!
6.
Apa perbedaan pemrograman procedural dan OOP
7.
Apa yang dimaksud dengan prepocessor?
8.
Buatlah program sederhana tentang class, object dan member functon.
73
DAFTAR PUSTAKA
Adam Drozdek, 2008, Data Structures and Algorithms in Java
Alfred V. Aho,dkk., 1988, Data Structures and Algorithms,
Cay S. Horstmann, 2009, C++ for everyone
Data Structures Using C , Tenenbaum, A., Y. Langsam, and M. Augenstein, 1990, PrenticeHall
Munir, R., 2004, Algoritma dan Pemrograman, Informatika, Bandung.
74
Download