diktat kuliah algoritma dan struktur data 2

102
1 BAB I ALGORITMA DAN STRUKTUR DATA 1.1 Pendahuluan Deskripsi singkat : Bab ini menjelaskan tentang konsep dasar algoritma dan struktur data meliputi: definisi algoritma dan struktur data, struktur data statis dan dinamis serta tipe data abstrak. Manfaat : Mahasiswa mampu memahami tentang konsep dasar algoritma dan struktur data serta implementasinya. Relevansi : Konsep dasar algoritma merupakan dasar yang penting untuk materi materi selanjutnya. Learning Outcomes : Mahasiswa Memiliki pengetahuan mengenai teori dan konsep dasar algoritma dan struktur data. Alokasi dan waktu : Bahan yang ada pada bab ini membutuhkan alokasi waktu kurang lebih 150 menit, dan disampaikan pada minggu pertama perkuliahan. Definisi : Algoritma dan Struktur Data Algoritma adalah urutan logis langkah-langkah untuk menyelesaikan masalah. Algoritma memiliki lima ciri penting : 1. Algoritma harus berhenti setelah mengerjakan sejumlah langkah terbatas. 2. Setiap langkah harus didefinisikan dengan tepat dan tidak ambigu (definite). 3. Algoritma memiliki nol atau lebih masukan. 4. Algoritma memiliki satu atau lebih keluaran. 5. Algoritma harus efektif. Struktur data: susunan atau cara merepresentasikan data agar efisien dalam penyimpanan (RAM) dan pengolahannya. Struktur data seharusnya dapat diterapkan pada algoritma yang didesain secara efisien Jadi mata kuliah Algoritma & Struktur Data adalah suatu disiplin ilmu yang mempelajari bagaimana merepresentasikan data secara efisien dan desain pengolahannya secara efisien pula.

Upload: abdul-malik

Post on 06-Nov-2015

22 views

Category:

Documents


5 download

DESCRIPTION

Diktat Kuliah Algoritma Dan Struktur Data 2

TRANSCRIPT

  • 1

    BAB I

    ALGORITMA DAN STRUKTUR DATA

    1.1 Pendahuluan

    Deskripsi singkat : Bab ini menjelaskan tentang konsep dasar algoritma dan struktur

    data meliputi: definisi algoritma dan struktur data, struktur data statis dan dinamis serta tipe

    data abstrak.

    Manfaat : Mahasiswa mampu memahami tentang konsep dasar algoritma dan struktur

    data serta implementasinya.

    Relevansi : Konsep dasar algoritma merupakan dasar yang penting untuk materi

    materi selanjutnya.

    Learning Outcomes : Mahasiswa Memiliki pengetahuan mengenai teori dan konsep

    dasar algoritma dan struktur data.

    Alokasi dan waktu : Bahan yang ada pada bab ini membutuhkan alokasi waktu

    kurang lebih 150 menit, dan disampaikan pada minggu pertama perkuliahan.

    Definisi : Algoritma dan Struktur Data

    Algoritma adalah urutan logis langkah-langkah untuk menyelesaikan masalah.

    Algoritma memiliki lima ciri penting :

    1. Algoritma harus berhenti setelah mengerjakan sejumlah langkah terbatas.

    2. Setiap langkah harus didefinisikan dengan tepat dan tidak ambigu (definite).

    3. Algoritma memiliki nol atau lebih masukan.

    4. Algoritma memiliki satu atau lebih keluaran.

    5. Algoritma harus efektif.

    Struktur data: susunan atau cara merepresentasikan data agar efisien dalam

    penyimpanan (RAM) dan pengolahannya. Struktur data seharusnya dapat diterapkan pada

    algoritma yang didesain secara efisien

    Jadi mata kuliah Algoritma & Struktur Data adalah suatu disiplin ilmu yang

    mempelajari bagaimana merepresentasikan data secara efisien dan desain pengolahannya

    secara efisien pula.

  • 2

    Ide pemrograman terstruktur pertama kali disampaikan oleh Profesor Edsger Djikstra

    dari Universitas Eidenhower sekitar tahun 1965. Djikstra mengusulkan tidak dipergunakannya

    pernyataan GOTO yang dapat menyebabkan timbulnya spaghetti logic, yang akan

    menjadikan sulitnya dilakukan perbaikan ataupun pengembangan program. Kemudian HD

    Millis menanggapi dengan mengemukakan bahwa pemrograman terstruktur tidak hanya

    dihubungkan dengan tidak digunakannya pernyataan GOTO, akan tetapi juga dengan struktur

    dari program. Struktur program yang akan menentukan program yang terstruktur

    menggunakan pernyataan GOTO atau tidak.

    Prinsip utama dari pemrograman terstruktur ialah bahwa jika suatu proses telah sampai

    pada suatu titik tertentu, maka proses selanjutnya tidak boleh melompat ke baris sebelumnya,

    kecuali untuk proses berulang. Pemrograman terstruktur dimaksud untuk mendapatkan

    program yang didefinikan dengan baik, jelas, mudah dipahami, mudah ditelusuri, dan mudah

    dimodifikasi.

    Langkah-langkah penyelesaian masalah dengan algoritma dan pemrograman adalah

    sebagai berikut :

    1. Analisis masalah

    2. Desain algoritma, meliputi :

    Deskripsi (cara penulisan):

    o natural language

    o pseudo-code

    o diagram (seperti flowchart)

    Kriteria algoritma:

    o Input: nol atau lebih

    o Output: satu atau lebih

    o Definisi/terjemahan/interprestasi: jelas, tepat untuk tiap instruksi

    o Batasan: sebuah algoritma harus berhenti setelah sejumlah langkah, walaupun

    jumlah langkah boleh banyak tapi harus terbatas

    Efektifitas: tiap instruksi harus berupa perintah dasar bukan merupakan bentukan dari

    beberapa perintah

    3. Analisis Algoritma

  • 3

    Space complexity

    o Berapa banyak space yang dibutuhkan

    Time complexity

    o Berapa lama waktu running algoritma

    4. Implementasi

    Pemutusan bahasa pemrograman yang akan digunakan

    o C, C++, Lisp, Java, Perl, Prolog, assembly, dll.

    Penulisan koding harus terdokumentasi dengan baik dan jelas.

    5. Ujicoba

    Mengintegrasikan feedback dari user, perbaiki bug, penjaminan kompatibelitas pada

    berbagai platform

    6. Pemeliharaan

    1.2 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.

    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.

  • 4

    Nama peubah yang kita gunakan untuk mewakili suatu nilai data sebenarnya

    merupakan / menunjukkan suatu lokasi tertentu dalam RAM di mana data yang diwakili oleh

    tipe data tersebut disimpan. Pada saat sebuah program dikompilasi maka 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 pascal 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

  • 5

    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.

    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

    using namespace std;

    main(){

    int a,*b;

    a=10;

    b=&a;

    c=new int;

    *c=25;

    cout

  • 6

    1.3 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 sematik 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 himpunan seperti

    penggabungan (UNION), irisan (INTERSECTION), dan selisih antar-himpunan (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

  • 7

    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 operasi-operasi

    yang dapat dilakukan pada struktur data tersebut. Dengan demikian, definisi umum tentang

    ADT di atas dapat diperluas sebagai berikut :

    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

  • 8

    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

    1.4 Latihan Soal

    1. Tulislah output dari cuplikan program berikut :

    #include

    using namespace std;

    main(){

    int a,*b, *c;

    a=10;

    b=&a;

    cout

  • 10

    BAB II

    STRUKTUR DATA LINEAR

    2.1 Pendahuluan

    Deskripsi singkat : Bab ini menjelaskan tentang struktur data linear yang meliputi:

    larikan, single linked list, doubly linked list serta stack dan queue.

    Manfaat : Mahasiswa memahami tentang berbagai macam struktur data linear dan

    dapat mengimplementasikan pada beberapa permasalahan.

    Relevansi : Struktur data linear paling banyak digunakan dalam menyelesaikan

    masalah pemrograman dan akan merupakan dasar dari struktur data yang lebih kompleks.

    Learning Outcomes : Mahasiswa Dapat menganalisis, merancang dan

    mengimplementasikan struktur data linear seperti linked list, stack dan queue.

    Alokasi dan waktu : Bahan yang ada pada bab ini membutuhkan alokasi waktu

    kurang lebih 600 menit, dan disampaikan pada minggu kedua sampai minggu kelima

    perkuliahan.

    Definisi : Struktur data linear adalah kumpulan komponen-komponen yang tersusun

    membentuk satu garis linear. Bila komponen-komponen ditambahkan (atau dikurangi), maka

    struktur-struktur 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 adalah Larikan, yaitu menggunakan array 1

    dimensi, linear linked list serta stack dan queue.

    2.2 Larikan, Array Satu Dimensi

    Array adalah suatu struktur 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

    data yang sama, tetapi isi dari elemen tersebut bisa berbeda.

  • 11

    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

    #include

    #include

    using namespace std;

    main() {

    int i, n, max, min, x[100];

    coutn;

    srand((unsigned)time(NULL));

    for (i=1;i

  • 12

    jika Anda hanya menggunakan satu variabel pointer saja untuk menyimpan banyak data

    dengan metode yang kita sebut Linked List. Linked list adalah sekumpulan elemen bertipe

    sama, yang mempunyai keterurutan tertentu, yang setiap elemennya terdiri dari dua bagian.

    Untuk dapat menyimpan data yang banyak dan untuk menunjukan sifat dinamisnya,

    maka variabel pointer harus dikombinasikan dengan tipe data struct, yaitu membentuk struktur

    data linked list (senarai berantai), berikut contoh deklarasi dan subprogram untuk membentuk

    linked list dari data random dengan menggunakan metode insert di depan, sebagai berikut :

    typedef struct node

    { int data;

    struct node *next;

    } *list;

    list L;

    void buatD(list &l)

    {

    int i,n;

    list b;

    coutn;

    srand((unsigned)time(NULL));

    for (i=1;inext=NULL;

    b->data=rand()%100+1;

    cout

  • 13

    buatD(p);

    cetakdata(p);

    getch();

    return 0;

    }

    Pembuatan Linear Linked List dapat menggunakan beberapa cara yaitu :

    1. Insert depan, yaitu data yang baru masuk menjadi data atau node paling depan

    2. Insert Belakang, yaitu data yang baru masuk menjadi data atau node paling belakang.

    3. Insert Terurut, yaitu data yang baru masuk disisipkan pada tempatnya sehingga

    keseluruhan data dijaga selalu terurut.

    Linear linked list dari banyaknya linked ada 2 macam, yaitu single linked list dan double

    linked list.

    1. Single Linked List

    Pada gambar di atas adalah contoh gambaran tentang single linked list L, setiap node memiliki

    pointer yang menunjuk ke simpul berikutnya sehingga terbentuk satu untaian, dengan

    demikian hanya diperlukan sebuah variabel pointer. Susunan berupa untaian semacam ini

    disebut Single Linked List, NULL memilik nilai khusus yang artinya tidak menunjuk ke

    mana-mana. Biasanya Linked List pada titik akhirnya akan menunjuk ke NULL.

    2. Double Linked List

    Salah satu kelemahan single linked list adalah pointer (penunjuk) hanya dapat bergerak satu

    arah saja, maju/ mundur, atau kanan/kiri sehingga pencarian data pada single linked list hanya

    dapat bergerak dalam satu arah saja. Untuk mengatasi kelemahan tersebut, anda dapat

    menggunakan metode double linked list. Linked list ini dikenal dengan nama Linked list

    berpointer Ganda atau Double Linked List, sehingga dalam mengaksesnya bisa bergerak 2

    arah (maju atau mundur), berikut adalah gambaran double linked list

  • 14

    Operasi-Operasi yang ada pada Linked List antara lain adalah sebagai berikut :

    Insert

    Istilah Insert berarti menambahkan sebuah simpul baru ke dalam suatu linked list.

    IsEmpty

    Fungsi ini menentukan apakah linked list kosong atau tidak.

    Find First

    Fungsi ini mencari elemen pertama dari linked list.

    Update

    Fungsi ini mengubah elemen yang ditunjuk oleh now dengan isi dari sesuatu.

    Delete Now

    Fungsi ini menghapus elemen yang ditunjuk oleh now. Jika yang dihapus adalah elemen

    pertama dari linked list (head), head akan berpindah ke elemen berikut.

    Delete Head

    Fungsi ini menghapus elemen yang ditunjuk head. Head berpindah ke elemen sesudahnya.

    2.4 Stack dan Queue.

    1. Stack

    Stack atau tumpukan adalah struktur data yang berbentuk linear list dengan menggunakan

    konsep utamanya adalah LIFO (Last In First Out), data yang terakhir masuk dalam stack akan

    menjadi data pertama yang dikeluarkan dari stack (TOP). Stack ini sering disebut dengan list

    dengan satu pintu akses. Berikut adalah gambaran tentang Stack.

  • 15

    Setidaknya stack haruslah memiliki operasi-operasi sebagai berikut.

    Push Untuk menambahkan item pada tumpukan paling atas

    Pop Untuk mengambil item teratas

    InitStack Untuk memulai atau mengosongkan stack

    IsEmpty Untuk memeriksa apakah stack kosong

    IsFull Untuk memeriksa apakah stack sudah penuh

    Implementasi stack dalam program dapat digunakan dua cara, yakni dengan array dan linked

    list.

    a. Stack dengan Array

    Sesuai dengan sifat stack, pengambilan / penghapusan di elemen dalam stack harus dimulai

    dari elemen teratas. Berikut contoh program tentang stack dengan array.

    #include

    #include

    #include

    using namespace std;

    const int maxs = 5;

    typedef struct

    { char isi[maxs+1];

    int top;

    } stack;

    void initstack(stack &S)

    { S.top = 0;

    }

  • 16

    void push(stack &S,char x)

    {

    if (S.top

  • 17

    b. Stack dengan Single Linked List

    Selain implementasi stack dengan array seperti telah dijelasnkan sebelumnya, ada cara lain

    untuk mengimplementasi stack dalam C++, yakni dengan single linked list. Keunggulannya

    dibandingkan array tentu saja adalah penggunaan alokasi memori yang dinamis sehingga

    menghindari pemborosan memori. Misalnya saja pada stack dengan array disediakan tempat

    untuk stack berisi 150 elemen, sementara ketika dipakai oleh user stack hanya diisi 50 elemen,

    maka telah terjadi pemborosan memori untuk sisa 100 elemen, yang tak terpakai. Dengan

    penggunaan linked list maka tempat yang disediakan akan sesuai dengan banyaknya elemen

    yang mengisi stack. Oleh karena itu pula dalam stack dengan linked list tidak ada istilah full,

    sebab biasanya program tidak menentukan jumlah elemen stack yang mungkin ada (kecuali

    jika sudah dibatasi oleh pembuatnya). Namun demikian sebenarnya stack ini pun memiliki

    batas kapasitas, yakni dibatasi oleh jumlah memori yang tersedia.

    Berikut contoh Program Stack dengan linked list:

    #include

    #include

    #include

    using namespace std;

    typedef struct node

    { char data;

    struct node *next;

    } *stack;

    void initstack(stack &S)

    { S = NULL;

    }

    void push(stack &S,char x)

    { stack b;

    b=new node;

    b->next=NULL;

    b->data=x;

    if (S==NULL) S=b;

    else {b->next=S;

    S=b;}

    }

  • 18

    void pop(stack &S,char &x)

    {stack t;

    if (S!=NULL) {

    x=S->data;

    t=S;

    S=t->next;

    free(t);

    } else cout

  • 19

    i++;

    }

    if ((S=NULL)||(cek==0)) cout

  • 20

    a. Implementasi Queue dengan Linear Array

    Linear array adalah suatu array yang dibuat seakan-akan merupakan suatu garis lurus dengan

    satu pintu masuk dan satu pintu keluar. Berikut ini diberikan deklarasi kelas Queue Linear

    sebagai implementasi dari Queue menggunakan linear array. Dalam prakteknya, anda dapat

    menggantinya sesuai dengan kebutuhan Anda. Data diakses dengan field data, sedangkan

    indeks item pertama dan terakhir disimpan dalam field, berikut contoh program tentang queue

    dengan linear array.

    #include

    #include

    #include

    using namespace std;

    const int maxq = 5;

    typedef struct

    { char isi[maxq+1];

    int front, rear

    } queue;

    void initqueue(queue &Q){

    Q.front =1 ;Q.rear =0 ;

    }

    void enqueue(queue &Q,char x)

    { if(Q.rear < maxq) {

    Q.rear++;

    Q.isi[Q.rear]=x ; } else cout

  • 21

    main(){

    queue Q; int i,n; char x;

    coutn;

    initqueue(Q);

    for (i=1;i

  • 22

    main() {

    queue Q;int i,n;

    char x,y[5]={'U','J','I','A','N'};

    initqueue(Q);

    for (i=0;i

  • 23

    if (Q.front!=NULL) {

    t=Q.front;

    while(t!=NULL) {

    cout

  • 24

    2. Dengan menggunakan stack buatlah subprogram untuk melakukan konversi notasi infix ke

    notasi postfix, sebagai gambaran :

    Input berupa ekspresi aritmatika dalam notasi infix sebagai berikut :

    ((A * B) + C / D E^F) * G ( dengan prioritas operasi : ^ , * atau / , + atau - )

    Output yg dihasilkan ekspresi aritmatika dalam notasi postfix:

    AB*CD/+EF^G*

    (Saudara boleh langsung menggunakan subprogram standar pada stack)

    3. Berikut adalah subprogram untuk menghapus node-node dimulai dari node dengan data = x

    hingga node terakhir pada doubly linked list, lengkapilah subprogram tersebut dengan

    mengisi statemen/variable yang sesuai pada ..........

    void DeleteNode(Dlist &L)

    { int x;

    Dlist t,r;

    coutx;

    if ( L->data == x ) {

    while ( L != NULL ) {

    r = L ; L = L->next ; delete r ; }

    } else {

    t = L;

    while ( t != NULL && t->data != x ) t = t->next ;

    if ( t == NULL) cout

  • 25

    BAB III

    STRUKTUR DATA NON LINEAR

    3.1 Pendahuluan

    Deskripsi singkat : Bab ini menjelaskan tentang struktur data non linear yang

    meliputi: matriks, multiple linked list, tree (BST dan AVL Tree) dan graf.

    Manfaat : Mahasiswa memahami tentang berbagai macam struktur data non linear

    dan dapat mengimplementasikan pada beberapa permasalahan yang sesuai.

    Relevansi : Struktur data non linear banyak digunakan dalam menyelesaikan masalah

    pemrograman yang lebih kompleks dan akan merupakan dasar dari struktur data lanjut.

    Learning Outcomes : Mahasiswa Dapat menganalisis, merancang dan meng-

    implementasikan struktur data non linear seperti matriks, multiple linked list, tree dan graf.

    Alokasi dan waktu : Bahan yang ada pada bab ini membutuhkan alokasi waktu

    kurang lebih 450 menit, dan disampaikan pada minggu keenam sampai minggu kedelapan

    perkuliahan.

    Definisi : 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, multiple

    linked list dan struktur data Tree atau pohon terutama pohon biner.

    3.2 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:

    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

  • 26

    Bentuk umum:

    NamaArray [m][n];

    Atau

    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

    #include

    #include

    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

  • 27

    for(j=1;j

  • 28

    3.3 Multipe Linked list

    Multiple linked list adalah linked list dengan linked field lebih dari satu dan bentuknya

    tidak linear. Sebagai ilustrasi dari multiple linked list dapat dilihat pada gambar berikut.

    Berikut contoh program tentang multiple linked list, yaitu untuk menyimpan data peserta

    pelatihan dimana banyak pelatihan dan pesertanya bisa dinamis.

    #include

    #include

    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;

    coutn;

    for (i=1;inext=NULL;b->down=NULL;

    coutb->pelatihan;

    if (l==NULL) l=b;

    else {b->next=l;

    l=b;}

    }

    }

  • 29

    void cetakdata(list l)

    {list p;peserta q;

    if (l!=NULL) {

    p=l;cout

  • 30

    else if(strcmp(p->pelatihan,namapelatihan)==0) {

    b=p->down;

    if(b==NULL)coutdown;p->down=c->next;free(c);}

    else {

    while(b->next!=NULL&&strcmp(b->next->nama,namapeserta)!=0) b=b->next;

    if (b->next==NULL) coutnama,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();

    }

    3.4 Struktur Data Tree

    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.

  • 31

    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).

    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

  • 32

    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

    Berikut contoh implementasi program tentang Pohon Biner.

    #include

    #include

    #include

    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(xdata) BST(&(*T)->kiri,x);

    else BST(&(*T)->kanan,x);

    }

    void PRE(tree T)

    {

    if (T!=NULL) {

    cout

  • 33

    void IN(tree T)

    {

    if (T!=NULL) {

    IN(T->kiri);

    coutkanan);

    cout

  • 34

    Operasi penambahan node/insert pada BST :

    BST sebelum dilakukan Insert BST setelah dilakukan Insert node 120

    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. Adelson-Velskii dan E.M. Landis. Oleh karena itu Binary

    Search Tree ini disebut AVLtree yang diambil dari nama kedua matematikawan Russia

  • 35

    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).

    Proses balancing pada AVL-Tree dilakukan dengan cara :

    Single Rotation (kiri dan kanan)

    Double Rotation (kiri dan kanan)

    Berikut contoh kedua proses tersebut :

    BST sebelum dilakukan insert 20 BST setelah insert 20 dan single rotation kanan

  • 36

    BST sebelum dilakukan insert 95 BST setelah insert 95 dan double rotation kanan

    Aplikasi dari struktur data pohon, antara lain yaitu untuk kompresi data string

    menggunakan huffman tree yaitu pohon biner yang disusun berdasarkan frekuensi

    kemunculan huruf pada string, aplikasi yang lain adalah konversi dari notasi infix ke notasi

    prefix atau postfix dan aplikasi pada pengurutan data dengan algoritma heapsort yang akan

    dibahas pada Bab IV.

    3.5 Struktur Data Graf

    Graf banyak digunakan untuk merepresentasikan suatu permasalahan, sehingga perlu dibahas

    bagaimana menyimpan graf di RAM, yaitu struktur data graf. Graf adalah kumpulan dari

    simpul atau vertex dan busur atau edge yang secara matematis dinyatakan sebagai :

    G = (V, E)

    Dimana

    G = Graph

    V = Simpul, atau Vertex, atau Node, atau Titik

    E = Busur, atau garis, atau Edge, atau arc

    Contoh graf :

  • 37

    Graph Berarah dan Graph Tak Berarah :

    B

    A C

    D E

    B

    A C

    D E

    Directed graph Undirected graph

    e1 e3

    e4

    e7e5e2

    e6

    v1

    v2

    v4 v5

    v3v1

    v2

    v3

    v5v4

    e1

    e2

    e3

    e4

    e5

    e6

    e7

    e8 e9

    e10

    Dapat dilihat dari bentuk busur yang artinya urutan

    penyebutan pasangan 2 simpul.

    Graph tak berarah (undirected graph atau non-directed graph) :

    Urutan simpul dalam sebuah busur tidak dipentingkan. Mis busur e1 dapat

    disebut busur AB atau BA

    Graph berarah (directed graph) :

    Urutan simpul mempunyai arti. Mis busur AB adalah e1 sedangkan busur BA

    adalah e8.

    Graph Berbobot (Weighted Graph)

    Jika setiap busur mempunyai nilai yang menyatakan hubungan antara 2 buah

    simpul, maka busur tersebut dinyatakan memiliki bobot.

    Bobot sebuah busur dapat menyatakan panjang sebuah jalan dari 2 buah titik,

    jumlah rata-rata kendaraan perhari yang melalui sebuah jalan, dll.

    Graph Berbobot :

    B

    A C

    D E

    B

    A C

    D E

    Directed graph Undirected graph

    5 3

    12

    684

    3

    v1

    v2

    v4 v5

    v3v1

    v2

    v3

    v5v4

    5

    e2

    3

    12

    8

    3

    6

    4 7

    10

    Panjang busur (atau bobot) mungkin tidak digambarkan secara

    panjang yang proposional dengan bobotnya. Misal bobot 5

    digambarkan lebih panjang dari 7.

  • 38

    Representasi Graph dalam bentukmatrix

    Adjacency Matrix Graph tak berarah

    0 1 0 1 0

    1 0 1 0 1

    0 1 0 1 1

    1 0 1 0 1

    0 1 1 1 0

    B

    A C

    D E

    Graph

    A B

    A

    0

    B

    C

    1 2 43

    C D E

    D

    E

    0

    1

    2

    4

    3

    Urut abjad

    Degree simpul : 3

    Representasi Graph dalam bentuk matrix

    Adjacency Matrix Graph berarah

    0 1 0 1 0

    1 0 1 0 1

    0 1 0 1 1

    0 0 1 0 1

    0 0 0 0 0Graph

    A B

    A

    0

    B

    C

    1 2 43

    C D E

    D

    E

    0

    1

    2

    4

    3

    B

    A C

    D E

    ke

    dari

    out

    in

  • 39

    Graph berarah dan berbobot

    B

    A C

    D E

    53

    2

    14

    12

    6

    7

    12

    0 5 0 2 0

    6 0 3 0 0

    0 0 0 0 9

    0 0 12 0 7

    0 14 0 0 0

    A

    A

    0

    B

    C

    1 2 43

    D

    E

    0

    1

    2

    4

    3

    B C D E

    Perhatikan pemilihan nilai 0.

    Representasi Graph dalam bentuk Linked List

    Adjency List graph tak berarah

    Digambarkan sebagai sebuah simpul yang memiliki 2 pointer.

    Simpul vertex : Simpul edge :

    info info

    Menunjuk ke simpul

    vertex berikutnya,

    dalam untaian simpul

    yang ada.

    Menunjuk ke simpul

    edge pertama Menunjuk ke

    simpul edge

    berikutnya, bila

    masih ada.Menunjuk ke simpul

    vertex tujuan yang

    berhubungan dengan

    simpul vertex asal.

    left right left right

  • 40

    Contoh : untuk vertex A, memiliki 2 edge yang terhubung yaitu e1 dan e2.

    A

    C

    D

    B

    E

    e2

    Graph

    e1B

    A C

    D E

    e1e3

    e4

    e7e5e2

    e6

    Urut abjad

    Algoritma Minimum Spanning Tree Problem

    Tree sebenarnya adalah suatu graf terhubung tanpa cycle.

    Spanning tree dari suatu graf G adalah tree yang memuat semua vertek dari G.

    Contoh :

    1 6 2

    Graf G :

    4 3 5

    3 2 4

    Maka minimum spanning tree dari G adalah :

  • 41

    Spanning tree yang total costnya minimum (10) adalah :

    1 2

    3 5

    3 2 4

    Suatu contoh aplikasi dari masalah minimum spanning tree adalah misalkan titik dari

    graf G adalah kota dan cost dari suatu garis (u,v) adalah biaya pemasangan telephone line dari

    kota u ke v. Maka minimum spanning tree dari G adalah merepresentasikan biaya total

    minimal untuk memasang telephone line n kota.

    Problem : Bagaimana menentukan spanning tre dari suatu graf (terhubung) yang total

    costnya minimum?.

    Catatan : Spanning tree dari suatu graf G dengan n titik mempunyai tepat n-1 garis.

    Ada 2 algoritma untuk menentukan minimum spanning tree yaitu Prim dan Kruskal.

    Prim bekerja berdasarkan titik, Sedangkan Kruskal bekerjannya berdasar garis.

  • 42

    PRIM

    Input : Graf G(V,E), V: himpunan titik dan E himpunan garis.

    Output: Minimum spanning tree T : himpunan garis.

    (himpunan B untuk mencatat titik yang sudah didapat)

    Algoritma :

    Begin

    T = {}

    B = { sembarang titik dari G, misalkan titik 1 }

    While B V do begin

    Tentukan garis e =(u,v) dengan cost minimum dimana u B dan v V-B

    T = T {e}

    B = B {v}

    End

    End

    KRUSKAL

    Input : Graf G(V,E), V: himpunan titik dan E himpunan garis.

    Output : Minimum spanning tree T : himpunan garis.

    (sebagai bantuan digunakan himpunan C1,C2, ,Cn yang berisi titik)

    Algoritma :

    Begin

    SORT hinpunan E secara acending.

    T = {};C1 = {1}, C2 ={2}, ,Cn ={n}.

    Repeat

    e =(u,v) tanpa menentukan yang costnya minimum karena E sudah sorted.

    Cari himpunan C yang memuat u Cu

    Cari himpunan C yang memuat v Cv

    If Cu Cv then begin

    Gabung Cu dan Cv menjadi satu himpunan.

    T = T {e}

    End

    Until T memuat n-1 garis

    End

  • 43

    Untuk lebih jelasnya diberikan contoh sebagai berikut:

    Perhatikan graf G di atas :

    1 6 2

    Graf G :

    4 3 5

    3 2 4

    Maka proses mendapatkan minimum spanning tree sebagai berikut :

    PRIM KRUSKAL

    (problem size n ) (problem size m (banyak garis))

    Step (u,v) B Step e=(u,v) Himpunan C

    Awal -- {1} Awal -- {1},{2},{3},{4}

    1 (1,4) {1,4} 1 (3,4) {1},{2},{3,4}

    2 (3,4) {1,4,3} 2 (1,4) {1,3,4},{2}

    3 (2,4) {1,4,3,2} 3 (1,3) ditolak (Cu=Cv)

    4 (2,4) {1,2,3,4}

    T={ (1,4), (3,4), (2,4) } T={ (3,4), (1,4), (2,4) }

    3.6 Latihan Soal

    1. Mengapa implementasi Tree dengan array kurang efisien sehingga harus menggunakan

    pointer, kemudian untuk menyimpan data menu (menu utama, submenu, subsubmenu)

    suatu aplikasi mengapa sebaiknya menggunakan multiple linked list?

    2. Berikut adalah subprogram untuk melakukan find and replace dari suatu BST, dimana data

    x diganti dengan data y dengan syarat setelah diganti harus tetap BST, lengkapilah

    subprogram tersebut dengan mengisi statemen yang seharusnya pada .........

  • 44

    void FindReplace(tree &T,char x,char y)

    {tree p,q;

    if(T!=NULL) {

    q=T; p=q;

    while (q!=NULL && x!=q->data) {

    p=q;

    if (xdata) {q=p->kiri;} else {q=p->kanan;}

    }

    if (x == q->data)

    if (.....) {q->data=y; cout

  • 45

    BAB IV

    ALGORITMA SORTING

    4.1 Pendahuluan

    Deskripsi singkat : Bab ini menjelaskan tentang algoritma sorting yang optimal baik

    sorting internal maupun sorting eksternal yang meliputi: QuickSort, MergeSort, HeapSort,

    Hybrid Mergesort quicksort dan Multiway Mergesort.

    Manfaat : Mahasiswa memahami tentang berbagai algoritma sorting yang optimal

    baik sorting internal (RAM) maupun sorting eksternal (File).

    Relevansi : Algoritma sorting sering digunakan dalam penyelesaian masalah

    pemrograman dan biasanya melibatkan data yang cukup besar.

    Learning Outcomes : Mahasiswa memiliki pengetahuan mengenai sorting serta dapat

    mengimplementasikan dalam program komputer.

    Alokasi dan waktu : Bahan yang ada pada bab ini membutuhkan alokasi waktu

    kurang lebih 300 menit, dan disampaikan pada minggu kesembilan dan kesepuluh

    perkuliahan.

    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).

    4.2 Algoritma Quick Sort dan Merge Sort

    Algoritma Quick Sort dan algoritma Merge Sort dirancang dengan teknik devide and

    conquer, merupakan algoritma sorting yang optimal dan sangat efisien.

    Quick Sort adalah algoritma yang proses pembagian data dengan cara partisi, sehingga

    diharapkan lebih menghemat memory. Teknik devide and conquer yang digunakan yaitu

    dengan mempartisi data yang disimpan di array X menjadi 2 subarray, yaitu subarray1 berisi

    data yang bound dan subarray2 berisi data yang bound, dimana bound (pivot) adalah

    suatu elemen yang diharapkan bisa membagi X menjadi 2 subarray yang banyak datanya

  • 46

    seimbang, kemudian terhadap masing-masing subarray dilakukan dengan cara yang sama

    secara rekursif. Algoritma QuickSort secara rekursif dapat dinyatakan sebagai berikut :

    Subprogram QuickSort (X[ ], n) {

    If ( n>1) then {

    Pilih bound;

    Partisi (X, bound);

    QuickSort(subarray1, j-1);

    QuickSort(subarray2, j+1);

    }

    }

    Sedangkan subprogram Partisi adalah sebagai berikut :

    Subprogram Partisi (X[ ], first, last ) {

    bound = X[first];

    i = first +1; j=last;

    while ( i bound ) j = j 1;

    if ( i < j ) Swap(X[ i ], X[ j ]);

    }

    Swap( X[ first ], X[ j ]);

    }

    Algoritma QuickSort mempunyai kelemahan yaitu untuk keadaan worstcase, salah

    satu subarray selalu kosong, kompleksitas waktunya O(n2), hal ini karena sangat sulit untuk

    mengontrol proses partisi. Algoritma MergeSort membagi data yang disimpan di larik X

    menjadi 2 subarray yang berukuran sama dan mengurutkan masing-masing subarray dengan

    cara rekursif kemudian melakukan merge kedua subarray yang sudah terurut tersebut.

  • 47

    Implementasi dari algoritma merge sort memakai tiga buah tabel, dua untuk

    menyimpan elemen dari tabel yang telah di bagi dua dan satu untuk menyimpan elemen yang

    telah terurut. Namun algoritma ini dapat juga dilakukan langsung pada dua tabel, sehingga

    menghemat ruang atau memori yang dibutuhkan.

    Subprogram MergeSort secara rekursif adalah sebagai berikut :

    Subprogram MergeSort (X[ ], first, last) {

    If ( first < last) then {

    mid = ( first + last ) / 2 ;

    MergeSort(X[ ], first, mid);

    MergeSort(X[ ], mid + 1, last);

    Merge(X[ ], first, mid, last);

    }

    }

    Sedangkan subprogram Merge adalah sebagai berikut :

    Subprogram Merge (X[ ], first, mid, last ) {

    I = first; j = mid + 1;k = 0;

    while ( i mid or j last ) {

    if ( X[ i ] < X[ j ] ) {Temp[k] = X[ i ]; i = i + 1;}

    else {Temp[k] = X[ j ]; j = j + 1;}

    }

    Masukkan data yang tersisa ke dalam Temp;

    Copy Temp ke array X;

    }

    Berikut adalah program tentang Merge Sort dan Quick Sort.

    #include

    #include

    #include

    using namespace std;

    typedef int larik[250001];

    long long c=0;

  • 48

    int n,cc=0;

    void cetakdata(larik x,int n)

    {int i;

    for (i=1;i

  • 49

    void mergesort(larik x,int aw,int ak)

    {int mid;

    if(aw

  • 50

    Subprogram MergeQuick (X[ ], first, last) {

    If ( last-first < 1000) then Quicksort(X[ ], first, last)

    else {

    mid = ( first + last ) / 2 ;

    MergeSort(X[ ], first, mid);

    MergeSort(X[ ], mid + 1, last);

    Merge(X[ ], first, mid, last);

    }

    }

    Dimana subprogram Quicksort dan subprogram Merge sama persis dengan yang sudah

    dibahas pada sebelumnya.

    Berikut hasil perbandingan antara algoritma MergeQuick dengan algoritma Mergesort

    dan Quicksort untuk jumlah data 1 juta, 2 juta hingga 5 juta, selengkapnya dapat dilihat

    pada Tabel 4.1.

    Tabel 4.1 Perbandingan Waktu Proses MergeQuick dengan Mergesort dan

    Quicksort

    Banyak

    data

    Waktu Proses (dalam detik)

    MergeQuick MergeSort QuickSort

    N=1 juta 0,354 0,419 0,464

    N=2 juta 0,743 0,88 1,346

    N=3 juta 1,137 1,348 2,684

    N=4 juta 1,536 1,815 4,380

    N=5 juta 1,957 2,342 6,584

  • 51

    Dari Tabel 4.1 menunjukkan bahwa algoritma MergeQuick lebih cepat dibanding

    dengan algoritma Mergesort dan Quicksort, sehingga pada penelitian ini akan digunakan

    algoritma MergeQuick untuk pengurutan internalnya.

    4.4 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.

    Heap

    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.

  • 52

    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.

    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.

  • 53

    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

    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.

  • 54

    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 faktor-

    faktor 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

    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.

    4.5 Pengurutan Eksternal

    Pengurutan eksternal (External sorting) adalah pengurutan yang dapat menangani data

    dalam jumlah besar. Pengurutan Eksternal diperlukan ketika data yang diurutkan tidak

    dapat masuk ke dalam memori utama dari komputer / RAM, sementara kalau diurutkan

    langsung pada memori eksternal (hardisk) lebih lambat. Pengurutan eksternal biasanya

    menggunakan strategi hybrid. Dalam tahap pengurutan, potongan data cukup kecil yang

    dapat dimuat di memori utama dibaca dan diurutkan, kemudian ditulis ke subfile atau file

    sementara. Pada tahap penggabungan, semua subfile yang sudah terurut digabungkan

    menjadi sebuah file tunggal yang lebih besar dan juga terurut.

    Salah satu algoritma pengurutan eksternal adalah algoritma mergesort eksternal,

    dimana potongan data yang masing-masing masuk dalam RAM diurutkan kemudian

    digabungkan bersama-sama, Sebagai contoh, untuk mengurutkan 900 MB data

  • 55

    menggunakan RAM dengan ukuran 100 MB, langkah-langkahnya adalah sebagai berikut :

    1. Dibaca 100 MB data masukkan dalam memori utama dan diurutkan menggunakan

    metode pengurutan konvensional, antara lain quicksort.

    2. Menuliskan data hasil pengurutan ke disk (file) .

    3. Ulangi langkah 1 dan 2 sampai semua data diurutkan dalam bentuk potongan data 100

    MB ( ada 900MB / 100MB = 9 potongan )

    4. Langkah selanjutnya adalah penggabungan Ke 9 potongan file tersebut menjadi satu file

    output tunggal dengan menggunakan strategi tertentu agar proses pengurutan secara

    keseluruhan efisien.

    ada beberapa algoritma untuk mengurutkan data yang tersimpan pada variabel RAM,

    antara lain QuickSort dan MergeSort.

    Pengurutan Eksternal diperlukan ketika data yang diurutkan cukup besar dan tidak

    dapat masuk ke dalam memori utama dari komputer, sementara jika diurutkan langsung

    pada memori eksternal (hardisk) akan sangat lambat.

    Misalkan banyak data yang akan diurutkan adalah n, banyak data yang dapat diurutkan

    di RAM misalkan M, sehingga terdapat s=n/M subfile yang masing-masing bisa diurutkan

    dengan pengurutan internal (QuickSort), permasalahannya adalah bagaimana

    menggabungkan s subfile terurut menjadi satu file terurut. Cara penggabungan yang sering

    dilakukan adalah dengan metode Multiway MergeSort dan sample sort.

    a. Multiway Mergesort

    Secara umum, k-way mergesort menggabungkan s subfile dengan cara merge secara

    bertahap sebanyak k blok dari subfile, sebagai contoh misalkan akan diurutkan data

    sebanyak n=4.000.000 sehingga akan terdapat 16 subfile berukuran 250.000 data dan

    digunakan 4-way mergesort maka 16 subfile akan digabung secara bertahap per 4 blok

    subfile berukuran 25.000 data, sehingga setiap iterasi akan terjadi 4 kali proses merge yang

    menghasilkan 4 subarray masing-masing 100.000 data, kemudian dilakukan merge sekali

  • 56

    lagi sehingga didapat subarray berukuran 400.000, iterasinya akan dilakukan 10 kali

    sehingga terakhir akan didapat satu file berukuran 4.000.000 data yang sudah terurut.

    b. Sample Sort

    Algoritma pengurutan internal yang lebih populer adalah algoritma Quicksort bukan

    Mergesort. Jadi adalah wajar untuk merancang algoritma pengurutan eksternal berdasarkan

    quicksort bukan mergesort, algoritma pengurutan eksternal ini disebut sample sort, yang

    mempunyai kinerja yang sama seperti multiway mergesort untuk kasus rata-rata dan bukan

    untuk kasus terburuk.

    Quicksort biasanya menggunakan satu elemen pivot sebagai dasar untuk melakukan

    partisi, pada simple sort ini, digunakan k-1 pivot untuk mempartisi menjadi k bucket.

    selanjutnya k bucket diurutkan secara rekursif menghasilkan k subfile yang proses

    penggabungannya sangat sederhana.

    Proses pada pengurutan eksternal, dapat dikelompokan menjadi 2 tahap, yaitu :

    1. Tahap internal, yaitu tahapan pembacaan data di file data (eksternal memory) ,

    mengurutkan secara internal menggunakan MergeQuick, kemudian menuliskan

    dalam subfile-subfile.

    2. Tahap Mergefile, yaitu tahapan penggabungan subfile-subfile menjadi satu file data

    yang terurut menggunakan multiway Mergesort.

    a. Tahap Internal

    Pada tahap ini, misalkan akan diurutkan data yang disimpan pada file data text

    berisi 5 juta data bilangan bulat dengan nama file data5juta.txt dan misalkan

    kemampuan maksimum yang dapat diurutkan secara internal di RAM adalah M =

    250.000, maka tahap internal dapat dinyatakan dengan algoritma berikut :

    Subprogram Internal() {

    openfile(f, "data5juta.txt");

    M=250000;

    while (not(eof(f))) {

    larik x = {0};

    i=0;

  • 57

    while(i

  • 58

    digunakan 2-way Mergesort, dimana proses merge dilakukan bertahap setiap 2 subfile,

    tahap Mergefile untuk jumlah data 5 juta (20 subfile) dapat dinyatakan dengan algoritma

    berikut :

    Subprogram Mergefile()

    { larik x[ ], y[ ], z[ ];int k,i,j,kk=1;

    for (i=1;i

  • 59

    Subprogram merge4way(int *x1,int *x2, int *x3, int *x4, int *z,int n)

    {

    int i=0,j=0,k=0,l=0,ii=0,id,min;

    do {

    min=x1[i];id=1;

    if (x2[j]

  • 60

    BAB V

    ALGORITMA SEARCHING

    5.1 Pendahuluan

    Deskripsi singkat : Bab ini menjelaskan tentang algoritma pencarian data (searching)

    yang meliputi: pencarian sekuensial, pencarian biner (review) dan searching dengan

    menggunakan fungsi hashing.

    Manfaat : Mahasiswa memahami berbagai macam algoritma searching dan sehingga

    diharapkan dapat memilih algoritma searching mana yang paling cocok untuk digunakan.

    Relevansi : Searching secara umum, termasuk searching dengan fungsi hashing,

    adalah suatu konsekuensi dari penyimpanan data secara terstruktur dimana proses pencarian

    kembalinya juga harus efisien.

    Learning Outcomes : Mahasiswa memiliki pengetahuan mengenai berbagai algoritma

    searching serta dapat mengimplementasikan dalam program komputer.

    Alokasi dan waktu : Bahan yang ada pada bab ini membutuhkan alokasi waktu

    kurang lebih 300 menit, dan disampaikan pada minggu kesebelas dan keduabelas perkuliahan.

    Pada Bab ini, 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 yang sangat efisien yaitu searching dengan fungsi

    hashing.

    5.2 Pencarian Sekuensial

    Pada pencarian sekuensial, data yang dicari, dibandingkan satu per satu dengan data

    pada suatu larik data.

    Algoritma globalnya adalah sebagai berikut :

    Misalkan dimiliki N data integer yang disimpan pada larik X, dan data yang dicari adalah a.

  • 61

    1. Ketemu = 0, indeks = 1.

    2. Selama data belum ketemu (ketemu = 0) dan indeks N :

    a. Jika X[indeks] = a, maka data ketemu, lalu nilai ketemu =1.

    b. Jika X[indeks] , maka indeks = indeks +1

    Kode programnya sebagai berikut :

    while ((ketemu == 0) && (indeks X[tengah], maka awal =tengah+1

    Kode programnya sebagai berikut :

    awal =1; akhir = N

    while ((ketemu == 0) && (awal akhir){

  • 62

    tengah = (awal + akhir) /2;

    if (X[tengah]=a){

    ketemu=1;}

    else if (a < X[tengah]){

    akhir = tengah-1;}

    else awal = tengah +1;

    }

    5.4 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 bisa ditemukan 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

  • 63

    alamiah, tidak ada garansi yang memungkinkan bahwa aspek kedua bisa dipenuhi tanpa

    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

  • 64

    akan menghasilkan alamat yang benar. Dengan menggunakan contoh yang sama dengan

    diatas, maka alamat dari masing-masing nomor mahasiswa diatas adalah :

    k : 10347 87492 34212 88688

    k2 : 107060409 76548500564 1170460944 7865561344

    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 digit-digit

    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, kemungkinan 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

  • 65

    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

    a. Pengalamatan Terbuka (closed hashing)

    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 untuks uatu 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.

  • 66

    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

    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 (open hashing)

    Penggandengan (Separate 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, kita melihat pada sebuah

    alamat hash lengkap dan senarai yang menyimpan rekaman rekaman yang mempunyai alamat

    hash yang sama, maka kita akan melihat adanya sebuah senarai berantai tunggal berkepala

    denga kepalanya adalah alamat hash.

  • 67

    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 :

    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.

    3. Fungsi Hashing untuk Data String

    Fungsi hash untuk data yang berupa string diperlukan nilai dari suatu karakter, yang

    biasanya digunakan berdasar kode ASCII. ASCII singkatan dari American Standard Code for

    Information Interchange. Komputer hanya dapat memahami bilangan, sehingga kode ASCII

    adalah representasi numerik dari karakter seperti 'a' atau '@' atau beberapa macam tindakan.

    Di bawah ini adalah tabel karakter ASCII dan ini termasuk deskripsi dari 32 karakter pertama

    non-cetak. Tabel ASCII selengkapnya dapat dilihat pada Tabel 5.1

    Ada berbagai cara untuk mengkonversi suatu string menjadi suatu bilangan bulat, fungsi

    hash untuk data string memerlukan konversi tersebut. Misalkan metode hash yang dipilih

    adalah metode pembagian (modulo atau mod) dengan menggunakan beberapa rumus fungsi

    hash dari suatu data string, secara umum fungsi hashnya dinyatakan dalam bentuk :

    H(string) = nilai_hash mod P + 1

    dengan

    nilai_hash adalah bilangan bulat positif yang ditentukan berdasar stringnya.

    P adalah ukuran tabel hash yaitu bilangan prima banyak data key.

  • 68

    Tabel 5.1 Tabel ASCII (http://www.asciitable.com)

    Nilai_hash di atas dapat ditentukan dengan berbagai rumus, pada penelitian ini

    digunakan 3 rumus penentuan nilai_hashnya, yaitu antara lain :

    a. Fungsi Hash H1

    Fungsi hash H1 dihitung berdasarkan rumus berikut :

    Nilai_hash = (nilai_string[0] + nilai_string[1] + ... + nilai_string[n-1])

    dengan n adalah panjang dari string, nilai_string[i] ditentukan dengan menggunakan Tabel

    5.1 Tabel ASCII

    Sebagai gambaran :

    Jika string = byte maka nilai_hash = 98 + 121 + 116 + 101 = 436

    Jika string = RAM maka nilai_hash = 82 + 65 + 77 = 224

    b. Fungsi Hash H2

    Fungsi hash H2 dihitung berdasarkan rumus berikut :

    Nilai_hash = (((nilai_string[0] + nilai_string[n-1])/2) * n)

    dengan n adalah panjang dari string, nilai_string[i] ditentukan dengan menggunakan Tabel

    5.1 Tabel ASCII.

  • 69

    Sebagai gambaran :

    Jika string = byte maka nilai_hash = ((98 + 101)/2 ) * 4 = 398

    Jika string = RAM maka nilai_hash = ((82 + 77 )/2) * 3) = 238

    c. Fungsi Hash H3

    Fungsi hash H3 dihitung berdasarkan rumus iterasi sebagai berikut :

    nilai_hash = 0;

    for i = 0 to n-1 do nilai_hash = (nilai_hash *3 + nilai_string[i]) mod P;

    dengan n adalah panjang dari string, P adalah ukuran tabel hash yaitu bilangan prima

    banyak data key, nilai_string[i] ditentukan dengan menggunakan Tabel 5.1 Tabel ASCII

    Sebagai gambaran :

    Dengan nilai P = 239,

    Jika string = byte maka nilai_hash = 121

    Jika string = RAM maka nilai_hash = 54

    Tujuan dari pemilihan fungsi hash adalah untuk menempatkan rekaman pada alamat

    tertentu, sehingga bisa dihindari terjadinya tabrakan (collision resolution), yaitu suatu keadaan

    dimana dua buah atau lebih rekaman yang mempunyai data kunci yang berbeda mampunyai

    alamat hash yang sama. Meskipun demikian, kemungkinan adanya tabrakan selalu tetap saja

    terjadi, meskipun fungsi hashnya sudah dipilih yang cukup baik. Dengan demikian,

    diperlukan satu cara untuk mengatasi tabrakan yang mungkin terjadi.

    Terdapat 2 metode atau cara untuk mengatasi tabrakan, dimana kedua cara tersebut

    mempunyai kelebihan dan kekurangan, yaitu antara lain :

    a. Closed hashing (Open Addressing)

    Metode Open adressing baik yang Linear Probing, Quadratic Probing maupun

    Double hashing mempunyai kelebihan yaitu penggunaan memorynya lebih sedikit, akan tetapi

    kelemahannya adalah waktu pencariannya lebih lambat

    b. Open hashing (Separate Chaining)

    Metode Separate Chaining atau linked mempunyai kelebihan yaitu waktu

    pencariannya lebih cepat, sedangkan kekurangannya penggunaan memorynya lebih banyak.

    Misalkan digunakan metode Separate Chaining, yaitu dengan membuat struktur data untuk

    tabel hash menggunakan linked list (pointer), yang dapat digambarkan sebagai berikut :

  • 70

    Gambar 5.1 Struktur Data untuk Tabel Hash

    Pada studi kasus data kamus, untuk menyimpan ke dalam tabel hash diperlukan

    langkah-langkah sebagai berikut :

    1. Menentukan ukuran tabel hash, yaitu nilai P merupakan bilangan prima yang lebih besar

    atau sama dengan banyaknya data key.

    2. Untuk setiap data key X[i].key

    Hitung nilai indeks IH, yaitu nilai fungsi hash H untuk data key X[i].key

    Tempatkan data key X[i].key pada tabel hash H[i].data.key

    Jika terjadi tabrakan tempatkan pada linkednya yang masih kosong.

    Kode program untuk menyimpan data kamus pada tabel hash adalah sebagai berikut :

    // Menentukan bilangan prima P, ukuran tabel hashnya

    long prima(int N)

    {long p; bool prima;

    do {

    if ((N==2)||(N==3)) prima=true;

    else if ((N%2==0)||(N

  • 71

    else

    { p=3;prima=true;

    do {

    if ((N%p)==0) prima=false; else p=p+2; }

    while ( prima && p

  • 72

    strcpy(H[i].data.key,"");H[i].next=NULL;

    }

    for(int i=1;idata=X[i];b->next=NULL;

    if (H[IH].next==NULL) H[IH].next=b;

    else {

    Q=H[IH].next;

    while (Q->next!=NULL) Q=Q->next;

    Q->next=b;

    }

    }

    }

    }

    Sedangkan cuplikan program untuk menampilkan isi tabel hash sekaligus menghitung

    rerata probe adalah sebagai berikut :

    cout

  • 73

    Untuk mencari data kamus tertentu pada tabel hash diperlukan langkah-langkah

    sebagai berikut :

    1. Membaca data key tertentu, misalkan a

    2. Menghitung nilai indeks IH dari data key a, kemudian mencari data key a di tabel hash

    dengan indeks IH.

    Kode program untuk mencari data kamus pada tabel hash adalah sebagai berikut :

    void cari(larik H,int p)

    {int lokasi,i,k=1;list q;bool ada;strg a="";

    cout

  • 74

    5.5 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. Jika diketahui data key adalah :

    70, 89, 92, 17, 71, 86, 24, 3, 34, 75, 21, 77, 7, 74, 35

    Menggunakan fungsi hash dengan metode sisa pembagian (key mod P1) + 1, tempatkan

    key tersebut pada larik H1, jika terjadi tabrakan gunakan metode linked dan kemudian

    tentukan rata-rata pencariannya. {P1: bilangan prima terkecil yang >= n}

    selanjutnya tempatkan key tersebut pada larik H2, jika terjadi tabrakan gunakan linear

    probing dan kemudian tentukan rata-rata pencariannya.

    4. 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.

    5. 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.

  • 75

    BAB VI

    PENGENALAN OOP

    6.1 Pendahuluan

    Deskripsi singkat : Bab ini menjelaskan tentang pengenalan bahasa pemrograman

    java dan teori serta konsep dasar object oriented programming (OOP).

    Manfaat : Mahasiswa memahami tentang paradigma OOP dan teori serta konsep

    dasar OOP yang semakin banyak digunakan untuk menyelesaikan masalah pemrograman.

    Relevansi : Paradigma pemrograman OOP yang merupakan paradigma pemrograman

    yang dikembangkan dari fasilitas tipe data turunan di dalam pemrograman terstruktur

    Learning Outcomes : Mahasiswa memiliki pengetahuan mengenai teori dan konsep

    Object Oriented Programming.

    Alokasi dan waktu : Bahan yang ada pada bab ini membutuhkan alokasi waktu

    kurang lebih 300 menit, dan disampaikan pada minggu ketigabelas dan keempatbelas

    perkuliahan.

    Pemrograman berorientasi objek (OOP) adalah suatu metode pemrograman yang

    berorientasi kepada objek. Tujuan dari OOP diciptakan adalah untuk mempermudah

    pengembangan program dengan cara mengikuti model yang telah ada di kehidupan sehari-

    hari. Jadi setiap bagian dari suatu permasalahan adalah objek, nah objek itu sendiri merupakan

    gabungan dari beberapa objek yang lebih kecil lagi. Sebagai contoh misalkan Mobil, Mobil

    adalah sebuah objek, yang terbentuk dari beberapa objek yang lebih kecil lagi seperti mesin,

    roda, bodi, kursi, dll. Mobil sebagai objek yang terbentuk dari objek-objek yang lebih kecil

    saling berhubungan, berinteraksi, berkomunikasi dan saling mengirim pesan kepada objek-

    objek yang lainnya. Begitu juga dengan program, sebuah objek yang besar dibentuk dari

    beberapa objek yang lebih kecil, objek-objek itu saling berkomunikasi, dan saling berkirim

    pesan kepada objek yang lain. Sebelum dilanjutkan lebih jauh tentang teori dan konsep dasar

    OOP terlebih dahulu kita bahas tentang bahasa pemrograman Java.

  • 76

    6.2 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 statik di World Wide Web (WWW), Java menjadikan

    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 memperlu