JURUSAN ILMU KOMPUTER FAKULTAS MATEMATIKA DAN ILMU PENGETAHUAN ALAM UNIVERSITAS UDAYANA 2012
PENDAHULUAN
A.
Pengertian Linked List Linked list atau yang biasa disebut senarai berkait merupakan struktur data yang terdiri dari beberapa simpul (node) dimana setiap simpulnya saling terhubung (linked). Simpul berupa struct, sedangkan link berupa komponen simpul yang bertipe pointer ke simpul. Bersifat dinamis dan memakai perintah malloc() dan free(). Umumnya memiliki pointer head untuk menunjukkan alamat simpul terdepan dan pointer tail untuk menunjukkan simpul terakhir. Operasi penambahan/ penghapusan sebuah simpul akan meng-update nilai pointer link-nya. Pointer link simpul terakhir diberi nilai NULL (kecuali untuk circular linked list).
B.
Kelebihan Linked List Adapun kelebihan dari Linked List, yaitu: 1. Mudah untuk melakukan penambahan dan penghapusan elemen (jika dibandingkan pada array tidak mungkin menambahkan elemen, karena banyaknya elemen sudah ditentukan dari awal) 2. Panjang list bisa diubah dengan bebas (panjang array telah ditentukan dari awal dan tidak dapat dirubah) 3. Mudah untuk menyambungkan beberapa list, maupun memutuskannya (jika dibandingkan pada array, array tidak bisa menyambung ataupun memutuskan elemen yang telah ada)
C.
Jenis-jenis Linked List Adapun jenis-jenis linked list adalah sebagai berikut: 1. Single Linked List 2. Double Linked List 3. Circular Linked List a. Single Circular Linked List b. Double Circular Linked List Penjelasan masing-masing jenis linked list akan dibahas pada BAB I, BAB II, dan BAB III.
1.1. Pengertian Single Linked List Senarai berkait tunggal (Single Linked List) yang selanjutnya akan disingkat dengan SLL adalah senarai berkait yang setiap simpulnya mengacu satu simpul lain dan diacu satu simpul lain dengan pengecualian pada simpul terakhir mengacu pada NULL dan simpu; pertama tidak diacu simpul lain. Simpul SLL mempunyai satu field bertipe pointer.
Pada Gambar 1.1. mengilustrasikan sebuah SLL yang simpulnya terdiri atas dua field. Field dengan kotak yang ukurannya lebih besar adalah field data, sedangkan yang ukurannya lebih kecil adalah pointer. Simpul-simpul SLL berada di memori heap dialokasikan secara dinamik dengan menggunakan instruksi malloc(), sedangkan pointer head berada di memori lokal (local stack memory). Pointer head mengacu atau menunjuk simpul pertama SLL (simpul paling kiri). Field pointer pada simpul terakhir diberikan nilai NULL, untuk menandai bahwa simpul tersebuttidak menunjuk simpul lain.
Dalam pembuatan Single Linked List dapat menggunakan 2 Metoda : LIFO ( Last In First Out ), aplikasinya : Stack (Tumpukan) FIFO ( First In First Out ), aplikasinya : Queue (Antrian)
LIFO (Last In First Out) LIFO adalah suatu metoda pembuatan Linked List dimana data yang masuk paling akhir adalah data yang keluar paling awal. Hal ini dapat dianalogikan dengan menumpukan barang pada kehidupan seharihari. Pembuatan simpul pada suatu linked list disebut dengan istilah INSERT. Jika linked list dibuat dengan Metoda LIFO maka penambahan/insert simpul dilakukan di BELAKANG.
FIFO (First In First Out) FIFO adalah suatu metoda pembuatan Linked List dimana data yang masuk paling awal adalah data yang keluar paling awal juga. Jika linked list dibuat dengan menggunakan FIFO, maka terjadi penambahan / Insert simpul di depan.
1.2. Deklarasi Tipe Data Simpul Single Linked List Pada umumnya, deklarasi tipe data simpul Single Linked List adalah sebagai berikut:
Simpul SLL berupa structure (record) yang terdiri atas beberapa field yang salah satunya bertipe pointer. Field pointer ini biasanya diberi nama next. Karena field pointer ini berfungsi untuk mengacu simpul yang lain yang sejenis maka deklarasi field pointer ini dilakukan secara rekursif. Pada contoh diatas tnode adalah tipe simpul yang terdiri atas dua field: sebuah integer dan sebuah pointer.
Deklarasi ini digunakan untuk mengakses field data dari simpul yang diacu pointer head adalah head->data.
Beberapa fungsi yang harus ada dalam membuat sebuah program Linked List adalah: 1. Deklarasi Tipe Data Simpul SLL: 2. Deklarasi Pointer Penunjuk Head SLL 3. Deklarasi awal()
void awal() { head = NULL; }
Fungsi awal() akan dipanggil di awal program. Artinya pada saat kita mulai menjalankan program belum terdapat list, sehingga head di-set kosong (NULL). 4. Deklarasi isEmpty()
int isEmpty() { if (head==NULL) return 1; else return 0; } Algoritma Dan Stuktur Data - Resume Linked List 5
Fungsi isEmpty() akan dipanggil pada saat pengecekan kosong/ tidaknya list. Saat (head==NULL) atau list sedang kosong maka isEmpty() akan memberikan nilai 1 ke fungsi yang memanggilnya. Sedangkan jika tidak kosong maka isEmpty() akan memberikan nilai 0 ke fungsi yang memanggilnya.
Operasi Single Linked List: Operasi-operasi yang ada di SLL adalah: 1. Pembentukan Simpul Baru (Node) Terdapat 2 kondisi saat pembentukan simpul baru, yaitu saat list masih kosong (head==NULL) dan list tidak kosong. Saat (head==NULL) Langkah-langkah: a. Memesan sebuah simpul baru dengan menggunakan intruksi malloc() b. Memasukkan data/ nilai ke dalam simpul c. Memberikan nilai NULL kepada field pointer next d. Mengubah pointer head sehingga menunjuk pointer tersebut Ilustrasi:
Source code:
printf("masukkan bilangan : "); scanf("%d",&bil); node = (tnode*) malloc(sizeof(tnode)); //a node->data=bil; //b if (isEmpty()){ node->next=NULL; //c head=node; //d }
Saat (head!=NULL) Saat (head!=NULL) merupakan penambahan simpul baru dimana sudah terdapat simpul-simpul yang saling berkaitan. Hal ini juga disebut penambahan simpul di awal (sebelah kiri). Langkah-langkah: a. Memesan sebuah simpul baru dengan menggunakan intruksi malloc() b. Memasukkan data/ nilai ke dalam simpul c. Mengkaitkan field pointer next pada simpul baru ke simpul yang ditunjuk head (hal ini menyebabkan simpul baru ini terhubung ke SLL dan menjadi simpul pertama. d. Mengubah pointer head sehingga menunjuk ke simpul baru ini. Ilustrasi:
Source code:
printf("Masukkan bilangan : "); scanf("%d",&bil); node = (tnode*) malloc(sizeof(tnode)); //a node->data=bil; //b if(!isEmpty()){ node->next=head; //c head=node; //d }
2. Penambahan Simpul (Node) a. Penambahan Simpul dari depan (sebelah kiri) Untuk penambahan simpul dari depan (sebelah kiri) telah dibahas sebelumnya pada pembuatan simpul baru saat (head!=NULL). b. Penambahan Simpul dari belakang (sebelah kanan) Ilustrasi:
30
30
30
30
Source Code:
void insertKanan() { if(isEmpty()) { head=N; } else { node *temp; temp=head; while(temp->next!=NULL) temp=temp->next; temp->next=N; } }
3. Penghapusan Simpul (Node) a. Penghapusan Simpul dari depan (Sebelah Kiri) Ilustrasi:
10
11
Source Code:
void hapusKanan() { if(!isEmpty()) { node *temp=head; printf("%d ", temp->data); if(temp->next!=NULL) { while(temp->next->next!=NULL) { temp=temp->next; } free(temp->next); temp->next=NULL; } else { free(temp); awal(); } } else printf("Data sudah habis"); }
12
Ilustrasi:
13
void insertKanan() { if(isEmpty()) { head=N; } else { node *temp; temp=head; while(temp->next!=NULL) temp=temp->next; temp->next=N; } } void showList() { node *temp=head; if (!isEmpty()) { while(temp->next!=NULL) { printf("%d ",temp->data); temp=temp->next; } printf("%d ",temp->data); } else printf("Data sudah tidak ada"); } void hapusKiri() { if(!isEmpty()) { node *temp; temp=head; head=head->next; free(temp); printf("Data terhapus!"); } else printf("Data sudah habis"); }
15
void hapusKanan() { if(!isEmpty()) { node *temp=head; printf("%d ", temp->data); if(temp->next!=NULL) { while(temp->next->next!=NULL) { temp=temp->next; } free(temp->next); temp->next=NULL; printf("Data terhapus!"); } else { free(temp); awal(); printf("Data terhapus!"); } } else printf("Data sudah habis"); } void main() { awal(); int pil, angka, bil; printf("\t\t\t==========================\n"); printf("\t\t\tProgram Single Linked List\n"); printf("\t\t\t==========================\n\n"); do { printf ("\n\nMENU\n"); printf ("1. Tambah Kiri\n"); printf ("2. Tambah Kanan\n"); printf ("3. Show Data\n"); printf ("4. Hapus Kiri\n"); printf ("5. Hapus Kanan\n"); printf ("0. Exit\n"); printf("Masukkan pilihan : "); scanf("%d",&pil); Algoritma Dan Stuktur Data - Resume Linked List 16
switch(pil) { case 1: printf ("\n\nTambah Kiri\n"); printf ("-----------\n"); printf("Masukkan data : ");scanf("%d",&angka); newNode(angka); insertKiri(); break; case 2: printf ("\n\nTambah Kanan\n"); printf ("-----------\n\n"); printf("Masukkan data : ");scanf("%d",&angka); newNode(angka); insertKanan(); break; case 3: printf ("\n\nShow List\n"); printf ("-----------\n\n"); showList(); getch(); break; case 4: printf ("\n\nHapus Kiri\n"); printf ("-----------\n\n"); hapusKiri(); getch(); break; case 5: printf ("\n\nHapus Kanan\n"); printf ("-----------\n\n"); hapusKanan(); getch(); break; case 0: exit(0); getch(); default : printf("Input salah"); getch(); } }while (pil!=0); } Algoritma Dan Stuktur Data - Resume Linked List 17
18
19
20
21
22
2.1
Pengertian Double Linked List Senarai berkait ganda atau Double Linked List disingkay DLL, adalah senarai berkait yang setiap simpulnya mengacu dua simpul lain dan diacu dua simpul lain. Dengan pengecualian pada simpul pertama dan terakhir yang masing-masing mengacu satu simpul lain dan diacu satu simpul lain. Simpul DLL mempunyai dua field pointer yang biasanya diberi nama prev dan next. Pointer prev digunakan untuk mengacu simpul sebelumnya dan pointer next digunakan untuk mengacu simpul berikutnya. Pada gambar 2.1 pointer next berada di bagian kanan dan pointer prev berada pada bagian kiri simpul.
2.2
Deklarasi Tipe Data Double Linked List Pada umumnya, deklarasi tipe data simpul Double Linked List adalah sebagai berikut:
struct tnode { int data; struct tnode *next, *prev; };
Simpul SLL berupa structure (record) yang terdiri atas beberapa field. Dua diantara field tersebut, harus berupa pointer yang digunakan untuk menunjuk ke simpul sebelumnya (prev) dan simpul berikutnya (next). Jadi prev dan next menunjuk simpul lain yang tipenya sama dengan tipe simpul tempat prev dan next berada.
Sebuah DLL biasanya diacu dua buah pointer, satu untuk menunjuk simpul pertama (biasanya diberi nama head) dan satu lagi untuk menunjuk simpul terakhir (biasanya
Algoritma Dan Stuktur Data - Resume Linked List 23
diberi nama tail). Pada saat DLL masih kosong (belum ada simpul), head dan tail diberi nilai NULL. Pointer lainnnya dideklarasikan sesuai kebutuhan.
struct tnode node; node *head, *N;
Beberapa fungsi yang harus ada dalam membuat sebuah program Linked List adalah: 1. Deklarasi Tipe Data Simpul DLL: 2. Deklarasi Pointer Penunjuk Head DLL 3. Deklarasi awal()
void awal() { head = NULL; tail = NULL; }
Fungsi awal() akan dipanggil di awal program. Artinya pada saat kita mulai menjalankan program belum terdapat list, sehingga head dan tail di-set kosong (NULL). 4. Deklarasi isEmpty()
int isEmpty() { if (head==NULL) return 1; else return 0; }
Fungsi isEmpty() akan dipanggil pada saat pengecekan kosong/ tidaknya list. Saat (head==NULL) atau list sedang kosong maka isEmpty() akan memberikan nilai 1 ke fungsi yang memanggilnya. Sedangkan jika tidak kosong maka isEmpty() akan memberikan nilai 0 ke fungsi yang memanggilnya.
24
Operasi Double Linked List: Operasi-operasi yang ada di DLL adalah: 1. Pembentukan Simpul Baru (Node) Terdapat 2 kondisi saat pembentukan simpul baru, yaitu saat list masih kosong (head dan tail==NULL) dan list tidak kosong. Saat (head dan tail==NULL) Langkah-langkah: a. Memesan sebuah simpul baru dan memasukkan data/ nilai ke dalam simpul b. Memberikan nilai NULL kepada field pointer next dan prev c. Mengubah pointer head sehingga menunjuk simpul ini d. Mengubah pointer tail sehingga menunjuk simpul ini Ilustrasi:
25
scanf("%d",&bil); node=(tnode*) malloc (sizeof(tnode)); node->data=bil; //a node->prev=NULL //b node->next=NULL //b if(head==NULL){ head=node; //c tail=node; //d }
Saat (head dan tail!=NULL) Saat (head dan tail!=NULL merupakan penambahan simpul baru dimana sudah terdapat simpul-simpul yang saling berkaitan. Hal ini juga disebut penambahan simpul di awal (sebelah kiri). Langkah-langkah: a. Memesan sebuah simpul baru dan memasukkan data/ nilai ke dalam simpul b. Memberikan nilai NULL kepada field pointer prev simpul baru c. Mengubah pointer prev dari simpul yang ditunjuk pointer head agar menunjuk simpul baru d. Mengubah pointer next dari simpul baru agar menunjuk simpul yang ditunjuk pointer head e. Mengubah pointer head sehingga menunjuk simpul baru Ilustrasi:
26
27
Untuk penambahan simpul dari depan (sebelah kiri) telah dibahas sebelumnya pada pembuatan simpul baru saat (head dan tail !=NULL). b. Penambahan Simpul dari belakang (sebelah kanan) Langkah-langkah: a. Memesan sebuah simpul baru, memasukkan data/ nilai ke dalam simpul, dan memberikan nilai NULL kepada pointer next b. Mengubah pointer next dari simpul yang ditunjuk pointer tail agar menunjuk simpul baru c. Mengubah pointer prev dari simpul baru agar menunjuk simpul yang ditunjuk pointer tail d. Mengubah pointer tail sehingga menunjuk simpul baru
Ilustrasi:
Source Code:
28
void tambah_akhir (struct tnode **h, struct tnode **t, int bil) { struct tnode *node; node=(struct tnode*) malloc (sizeof(struct tnode)); node->data=bil; //a node->next=NULL; //a if (*h==NULL) { *h=node; node->prev=NULL; } else { (*t)->next=node; //b node->prev=*t; //c } *t=node; //d }
3. Penghapusan Simpul Tertentu Menghapus simpul yang berada diantara simpul lain tidaklah sulit. Gambar 2.5 mengilustrasikan mekanisme penghapusan simpul bernilai 40 yang berada diantara simpul-simpul lain. Langkah-langkah: a. Pindahkan pointer node ke posisi simpul yang akan dihapus, dan pointer lainnya (current) dipindahkan ke posisi di sebelah kiri simpul yang akan di hapus
node = head; while (node->data != nilai_hapus) { current = node; node = node-> next; }
b. Ubah pointer next dari simpul yang ditunjuk pointer current agar menunjuk ke simpul yang berada di sebelah kanan simpul yang ditunjuk pointer node
curent->next = node->next;
29
c. Ubah pointer prev dari simpul yang berada di sebelah kanan simpul yang ditunjuk pointer node agar menunjuk ke simpul yang ditunjuk pointer current
node->next->prev = current;
Ilustrasi:
4. Mencetak Linked List Sama halnya dengan mencetak Single Linked List, saat mencetak Double Linked List juga melakukan operasi menggunakan pointer (head dan tail). Terdapat dua buah operasi pencetakan yaitu dari head ke tail, dan dari tail ke head.
Source Code:
//head to tail void cetak_ht (struct tnode *h) { while (h != NULL) { printf("%d ",h->data); h=h->next; } } //tail to head void cetak_th (struct tnode *t) { while (t != NULL) { printf("%d ",t->data); t=t->prev; } }
31
2.3
Contoh Program
#include <stdio.h> #include <stdlib.h> struct tnode{ int data; struct tnode *prev, *next; }; void tambahAwal(struct tnode **h, struct tnode **t, int bil) { struct tnode *node; node=(struct tnode*)malloc(sizeof(struct tnode)); node->data=bil; node->prev=NULL; if(*h==NULL) *t=node; else (*h)->prev=node; node->next=*h; *h=node; } void tambahAkhir (struct tnode **h, struct tnode **t, int bil) { struct tnode *node; node=(struct tnode*) malloc (sizeof(struct tnode)); node->data=bil; node->next=NULL; if (*h==NULL) { *h=node; node->prev=NULL; } else { (*t)->next=node; node->prev=*t; } *t=node; } //head to tail void cetak_ht (struct tnode *h) { while(h != NULL) { printf("%d ",h->data); h=h->next; } }
32
//tail to head void cetak_th (struct tnode *t) { while (t != NULL) { printf("%d ",t->data); t=t->prev; } } void hapus (struct tnode **h, struct tnode **t) { struct tnode *node; while (*h!=NULL) { node=*h; *h=(*h)->next; free(node); } *t=NULL; } int main() { struct tnode *head, *tail; int bil; head=tail=NULL; printf("\t\t\t==========================\n"); printf("\t\t\tProgram Single Linked List\n"); printf("\t\t\t==========================\n\n"); printf("Ketik Deretan Bilangan: "); do{ if(scanf("%d",&bil) != 1) break; tambahAwal(&head,&tail,bil); }while (1); printf("\n\nHead to Tail: "); cetak_ht(head); printf("\nTail to Head: "); cetak_th(tail); hapus(&head,&tail); return 0; }
33
34
35
3.1. Pengertian Circular Linked List Circular Singly-Linked List adalah senarai berkait tunggal yang simpul terakhirnya mengacu simpul pertama. Circular Doubly-Linked List adalah senarai berkait ganda yang simpul terakhirnya selain mengacu simpul sebelumnya juga mengacu simpul pertama, dan simpul pertamanya selain mengacu simpul kedua juga mengacu simpul terakhir.
Selain mengacu atau mengaitkan simpul terakhir ke simpu pertama dan sebaliknya, hal lain yang harus diingat jika membentuk circular linked list adalah untuk menandai simpul terakhir walaupun secara konsep linked list tersebut tidak berujung karena bentuknya melingkar. Penandaan simpul terakhir ini bermanfaat waktu menghapus simpul untuk mengembalikan memori yang dipakai kepada memori heap.
36
3.2. Bentuk Umum Circular Linked List Bentuk Umum dari Circular Singly-Linked List maupun Circular Doubly-Linked List hampir menyerupai bentuk umum dari Single Linked List dan Double Linked List, namun yang membedakan adalah pada circular linked list terdapat code yang digunakan untuk membuat linkes list itu memutar. Berikut ini adalah code nya: (*t)->next=*h
Code ini ditambahkan pada saat penambahan data (insert data). Dan diletakkan di bagian akhir dari fungsi insert data.
37
void isiData(tnode **h, tnode **t) { tnode *c; int bil; *h=NULL; printf("\nKetik Sejumlah bilangan: \n"); while (scanf("%d",&bil) == 1) { c=(tnode*)malloc(sizeof(tnode)); c->data=bil; c->next=NULL; if (*h==NULL) *h = c; else (*t)->next=c; *t=c; } (*t)->next=*h; } void tampil_data(tnode *h) { int n=6; printf("Ingin tampilkan berapa data? "); scanf("%d", &n); while(n) { printf("%d ", h->data); h=h->next; n--; } } oid hapus(tnode **h, tnode **t) { struct tnode *c; while (*h != *t) { c=*h; *h=(*h)->next; free(c); } free(*t); *h=*t=NULL; }
38
int main() { tnode *head, *tail; isiData(&head, &tail); tampil_data(head); hapus(&head,&tail); return 0; }
39
40