Anda di halaman 1dari 47

Algoritma Struktur Data

IF 6121003

Pertemuan 7
List berkait & Algoritma Rekursif
Rencana
● Pengertian List
● List vs Array
● List sebagai ADT
● Implementasi List di C++
● Varian List
● Algoritma Rekursif
● Rekursif sebagai strategi algoritma
● Contoh algoritma rekursif
● Studi Kasus
Data Structure sebagai Container
● Container merupakan
wadah penampung
● Bayangkan sebagai “Jar”
wadah makanan
● Kita bisa mewadahi
makanan ke dalamnya
● Operasi yang mungkin:
menaruh benda,
mengambil benda,
mencari benda,
mengosongkan wadah
List

● Secara abstrak merupakan kumpulan elemen-elemen


yang memiliki urutan
● Kita dapat mengakses elemennya melalui posisi
indeks
● List adalah ADT yang memungkinkan operasi seperti :
tambah, kurangi, search ( seperti jar wadah makanan )

void add(Element e);


void remove(int I);
Element search( Value v );
List (2)
● ADT List paling sederhana : Array
● Selain terurut dari indeks, posisi elemen array
di memori juga terurut
● Kekurangan array :
– Ukuran harus ditetapkan ketika kompilasi
– Penyisipan elemen selalu diikuti pergeseran
elemen lain
● ADT lain yang mengikuti sifat List : Linked List (
list berkait ) atau Single Linked List / SLL )
List berkait
● Definisi : kumpulan node ( simpul ) yang membentuk
linear ordering ( urutan linear )
● Tiap node / simpul memuat : informasi dan pointer
● Pointer tersebut disebut next pointer ( link ) karena
menunjuk ke node berikutnya dalam list

● Struktur data tsb dinamakan Linked List karena tiap


node hanya menyimpan satu pointer ( link )
● Elemen pertama=Head, elemen terakhir = tail
Implementasi Linked List (C++)
● Untuk implementasi list di C++ kita bisa
menggunakan struct maupun class
● Pada contoh berikut : node menyimpan info
string dan pointer ke node berikutnya ( next )
● Diagram berikut menyatakan: StringLinkedList
terdiri dari satu atau lebih StringNode

Class StringNode Class StringLinkedList


Implementasi Node
● Keyword baru: friend class
● Artinya kelas StringNode memberi akses ke
kelas StringLinkedList
class StringNode { //definisi node
private:
string elem; //info yg dimuat
StringNode* next; //link pointer ke
next

friend class StringLinkedList; //beri


akses
};
Implementasi List
● Memuat member function: fungsi penyerta yang
nantinya digunakan untuk operasi List
● Konstruktor : memberi nilai awal di head =
NULL ( kondisi awal List dibuat adalah kosong)
class StringLinkedList {
public:
StringLinkedList(); //konstruktor
~StringLinkedList(); //destruktor
bool empty() const; //apakah kosong?
const string& front() const; //bagian depan list
void addFront(const string& e); //tambah ke depan
void removeFront(); //buang item depan list
private:
StringNode* head; //pointer ke head
};
Implementasi List (2)
● Ilustrasi List
Linked List
Head
Node

StringLinkedList::StringLinkedList() //konstruktor
: head(NULL) { } //head diisi NULL
StringLinkedList::~StringLinkedList() //destruktor
{ while (!empty()) removeFront();} //hapus tiap node

bool StringLinkedList::empty() const //apakah kosong


{ return head == NULL }

const string& StringLinkedList::front() const


{ return head->elem; } //elemen info yang ada di
head
Penyisipan (insert) depan
● Menyisipkan elemen pada posisi head
● Langkah:
– Buat elemen node
– Set next link menunjuk ke head dari list
Implementasi sisip depan
● Menambah string baru didepan list
● StringLinkedList bisa mengakses elem dan next
dari StringNode karena sudah dijadikan friend
void StringLinkedList::addFront(const string& e) {
StringNode* v = new StringNode; //buat node baru
v->elem = e; //isi info elemen
v->next = head; //set next link
head = v; //head diupdate
}
Buang/hapus (remove) depan
● Membuang elemen depan, pointer head pindah satu
elemen ke belakang
● Langkah : sebelum dihapus (dealokasi memori) ,
pointer head dipindah terlebih dulu
Implementasi hapus depan

void StringLinkedList::removeFront() {
StringNode* old=head; //head saat ini
head = old->next; //pindah head ke
blkg
delete old; //dealokasi memori
}
Fitur Generic pada C++
● Pada contoh list sebelumnya, kita membuat list yang
memuat info / data berupa string
● Fitur Generic: umum, generalisasi
● Kemampuan menangani tipe data yang beragam
● Bagaimana membuat list yang dapat memuat tipe data
apa saja ?
● Di C++, kita menggunakan template dan type variabel
● Kita membuat kelas Node yang mampu menampung
tipe generic / umum
Membuat class SNode
● Node / simpul baru berikut menggunakan
template dan type variabel <E>
● Type variabel <E> akan menggantikan tipe
standard, jadi kita node tersebut bisa memuat
tipe apapun
template <typename E>
class SNode {
private:
E elem; //tipe elemen generic
SNode<E>* next;
friend class SLinkedList<E>; //beri
akses
};
class SLinkedList
● Perhatikan perbedaan dengan StringLinkedList
template <typename E>
class SLinkedList {
SLinkedList(); //konstruktor: buat list kosong
~SLinkedList(); //destruktor
bool empty() const; //cek apakah list kosong
const E& front() const; //ambil node depan
void addFront(const E& e);//tambah node depan
void removeFront(); //buang node depan
private:
SNode<E>* head;
};
SlinkedList (2)
SlinkedList (3)
● Sisip depan dan hapus depan
Penggunaan kelas Generic
● Contoh: Membuat list of string dan list of integer
dari list generic
List berkait ganda
● List berkait ganda (doubly linked list): memiliki pointer
(link) ganda yaitu kedepan dan kebelakang
● Kelemahan list berkait tunggal : hanya memiliki link ke
depan (next) sehingga tidak bisa kembali ke belakang
● List ganda punya kemampuan menelusuri depang
belakang sekaligus
Elemen Sentinel
● List berkait ganda menggunakan konsep
sentinel yaitu node yang bukan anggota list tapi
seolah-olah ada dalam list
● Tujuannya memberi akses cepat pada elemen
pertama dan elemen terakhir
● Pada gambar berikut elemen sentinel adalah
header dan trailer
Penyisipan node pada List ganda
● Link node yang disisipkan disetup menunjuk ke
node yang sudah ada. Node depan dan
belakang di update
Penghapusan node
● Menghapus node pada list berkait ganda berarti
mengupdate prev ( link sebelum ) dan next
( link ke depan )
Implementasi List berkait ganda
● Adanya pointer tambahan (jadi ada dua link)
typedef string Elem;
class DNode { //link list ganda
Elem elem; //elemen memuat string
DNode* prev; //link menunjuk ke belakang
DNode* next; //link ke depan
friend class DLinkedList; //beri akses class
};
Implementasi
class DLinkedList {
public:
DLinkedList();
~DLinkedList();
bool empty() const;
const Elem& front() const; //elemen info depan
const Elem& back() const; //elemen info blkg
void addFront(const Elem& e);
void addBack(const Elem& e);
void removeFront(); //hapus node depan
void removeBack(); //hapus node blkg
private:
DNode* header; //node sentinel
DNode* trailer;
protected:
void add(DNode* v, const Elem& e );//sisip sebelum
v
void remove(DNode* v); //hapus node v
Implementasi (3)
● Konstruktor destruktor
Implementasi (4)
● Fungsi mengakses isi node dan cek kosong
Implementasi (5)
● Menambah elemen ( node baru )
V
P

U
Implementasi (6)
● Menghapus node v
U V W
List Circular
● Elemen yang diujung (tail) menunjuk ke head
(awal). Sehingga tidak ada konsep head dan tail

● Operasi pada list circular hampir sama dengan list


berkait tunggal
● Adanya konsep cursor: elemen yg saat ini ditunjuk
Implementasi List Circular
● Node pada List Circular tidak beda dengan
single linked list
Implementasi (2)
● Desain class CircleList
Implementasi Circular list (3)
● Menambah elemen didepan cursor
Cursor next

V
Implementasi Circular list (4)
● Menghapus node di depan cursor
cursor next
Algoritma Rekursif
Recurrence Relation
● Recurrence : berulang, relation: hubungan
● Rekursif : algoritma yang memanggil dirinya sendiri
● Syarat algoritma rekursif diterima :
– Algoritma harus terminate ( berhenti )
– Menghasilkan progress komputasi, bekerja dg baik
● Contoh algoritma menghitung nilai faktorial :
n! = n*(n-1)*(n-2)*….*3*2*1 kita eksplor 2 relasi
yaitu 1! = 1 dan n! = n*(n-1)! Untuk n > 1
Faktorial (2)
● Faktorial sebagai fungsi matematik :

● Contoh : 5! = 5*4*3*2*1 = 120


● Definisi rekursif : definisi fungsi lewat dirinya sendiri

● Kasus basis : yang memberi nilai fix dari fungsi


● Kasus rekursif : membuat definisi fungsi dari dirinya
sendiri
Algoritma rekursif
● Desain algoritma yg didalamnya mengurangi
ukuran masalah dengan memanggil prosedur
dari algoritma itu sendiri dalam sub masalah
● Ciri: ada nya basis => sub masalah yang final
( diketahui solusinya, tidak mungkin dikurangi
lagi )
● Recurrence : pemanggilan algoritma berulang
pada sub masalah
● Perhitungan faktorial merupakan contoh rekursif
Implementasi faktorial

Recursion trace dari fungsi


recursiveFactorial
Contoh rekursif (2)
● Menjumlah isi array tanpa looping
● Dengan rekursif kita akan menjumlah isi array
( asumsi array integer/bilangan )

● Tiap kali rekursif ukuran yang dijumlah berkurang


Recursion Trace contoh 2
● Menjumlah isi array dengan rekursif
● Misal array input A={ 4,3,6,2,5 } n=5, berikut
recursion trace dari LinearSum( A, n )
Contoh rekursif (3)
● Reverse array ( membalik isi array ): bekerja
dengan menukar posisi ujung dengan ujung (0
vs n-1) , lalu ( 1 vs n-2 ), dst
● Pseudocode membalik array dengan rekursif
Contoh problem lain
dg sifat rekusif
● Membuat penanda pada penggaris
● Major tick : bagian penanda yang paling
panjang

Major tick length=3


Panjang 3

Major tick length=4


Panjang 2

Major tick length=5


Panjang 1
Menggambar penggaris
secara rekursif
● drawTicks :skema rekursif, drawOneTick: fungsi
menggambar garis strip-nya
Implementasi rekursif
Terima kasih

Anda mungkin juga menyukai