Pointer & stuktur data dinamis


MEMORI DINAMIS & POINTER
ALOKASI MEMORI DINAMIS DAN POINTER  


Pendahuluan

Salah satu kelemahan data bertipe array adalah bahwa variabel tersebut harus dideklarasikan terlebih dahulu dengan menyebutkan ukurannya. Dengan demikian ukuran variabel tersebut tidak dapat kita ubah selama program dijalankan. Lalu bagaimanakah kalau kita akan membuat program untuk menangani data dalam jumlah yang besar? Bagaimana pula kalau jumlah datanya tidak diketahui sebelumnya?.

Pertanyaan pertama mungkin dapat diselesaikan dengan memesan variabel array dengan ukuran sebanyak data yang akan dimasukkan. Tetapi sebenarnya ide ini belum tentu dapat dijalankan (terutama kalau implementasi programnya menggunakan bahasa yang mensyaratkan ukuran maksimum variabel dalam suatu program, seperti Pascal yang membatasi jumlah ukuran semua variabel dalam suatu program tidak boleh melebihi 64 Kb). Sebagai contoh, berikut ini adalah deklarasi dalam Pascal yang akan ditolak:

  1. var banyak : array[1..35000] of integer;
  2. var larikan : array[1..12000] of real;
  3. var larik1 : array[1..30000] of char;
  4. var larik2 : array[1..35000] of byte

Pendeklarasian di atas akan ditolak oleh Pascal karena:

  1. ukuran variabel banyak adalah 35000 x 2 byte = 70000 byte
  2. ukuran variabel larikan adalah 12000 x 6 byte = 72000 byte
  3. ukuran variabel larik1 = 30000 x 1 byte = 30000 byte dan ukuran variabel larik2= 35000 x 1 byte = 35000 byte, sehingga total ukuran kedua variabel adalah 65000 byte

Permasalahan kedua juga menyulitkan pemrograman. Bila kita alokasikan variabel dengan ukuran yang besar sementara nantinya data yang dipakai hanya sedikit maka ini berarti pemborosan memori (memori sudah dipesan tetapi tidak dipergunakan) sedang bila dialokasikan dengan ukuran kecil sementara nantinya data yang digunakan cukup banyak sehingga deklarasi yang dibuat tidak cukup maka tentunya permasalahan tidak akan terselesaikan.

Untuk mengatasi permasalahan di atas maka pada beberapa bahasa pemrograman terstruktur diperkenalkan adanya dua jenis variabel yaitu variabel statis (seperti yang sudah dibicarakan pada bagian sebelumnya) dan variabel dinamis yang akan kita bicarakan pada bagian ini.


Alokasi Memori Dinamis

Alokasi memori dinamis dapat dikatakan merupakan suatu teknik alokasi memori dimana, tidak seperti pada penggunaan array,penggunaan memori tidak sekaligus pada saat variabel dideklarasikan (dipesan) tetapi dengan bertahap. Program berjalan pada awalnya dengan sedikit memori data, kemudian pada suatu saat bila memerlukan ruang/memori lagi (misal datanya bertambah) barulah program meminta memori yang diperlukan untuk keperluan tersebut kepada sistem.

Dengan cara yang sama bila program sudah tidak memerlukan data lagi maka memori yang diperlukan untuk menyimpan data dapat dibebaskan. Memori yang dibebaskan ini selanjutnya mungkin untuk proses yang lain (pada multiprogramming) atau untuk keperluan program yang sama nantinya.


Pointer

Pointer sering disebut juga dengan istilah link atau referensi adalah suatu variabel yang berisi alamat dari suatu variabel yang lain. Sebagai contohnya pada saat kita mengakses record kita tidak tahu dimana record tersebut secara eksak diletakkan di dalam memori, karena dengan menggunakan pointer kita membiarkan sistem komputer mengatur letak record tersebut ketika diperlukan.

Secara umum, dalam pembicaraan tentang pointer, tipe data pointer digambarkan sebagai tanda panah sedang variabel yang ditunjuk digambarkan sebagai kotak.


Variabel Statis dan Variabel Dinamis

Variabel statis adalah variabel yang dideklarasikan dan dinamai pada saat penulisan program. Memori yang dipakai oleh variabel ini akan tetap ada (dianggap terpakai) selama program dimana variabel tersebut dideklarasikan sedang dijalankan.

Variabel dinamis adalah variabel yang dibuat (dan mungkin juga dihapus/dirusak) selama eksekusi progam. Karena variabel dinamis belum nyata ada pada saat program dikompilasi (ia nyata-nyata ada pada saat dibuat yaitu pada saat program dieksekusi), maka variabel seperti ini tidak dapat dinamai pada saat program dibuat/ditulis.

Satu-satunya cara untuk mengakses variabel dinamis adalah dengan menggunakan pointer. Saat suatu variabel dinamis dibuat, ia belum berisi data dan harus memiliki suatu tipe tertentu seperti halnya variabel biasa.

Sebaliknya variabel statis tidak dapat dibuat ataupun dihapus pada saat eksekusi program dan variabel pointer tidak dapat digunakan untuk menunjuk kepada variabel statis. Variabel statis dapat diakses hanya dengan menggunakan namanya dan bila kita ingin menunjuk pada suatu posisi dalam array maka kita dapat melakukannya dengan menggunakan indeks/variabel yang bertipe seperti indeks dari array.



Notasi dalam Pascal

Pointer dalam Pascal dinyatakan dengan menggunakan tanda “^”.
Sintaks secara umum adalah :
type nama_pointer = ^tipe_variabel_yang_ditunjuk
atau
var nama_pointer = ^tipe_variabel_yang_ditunjuk
Keterangan:

  • nama_pointer adalah pengenal untuk tipe data pointer
  • tipe_variabel_yang_ditunjukadalah tipe data variabel dinamis yang ditunjuk oleh pointer
    Tipe variabel ini bisa berupa tipe sederhana (integer, char, boolean, word) atau tipe yang lebih kompleks (real, record,array)

Contoh:

  1. type item = integer;
    pointitem = ^item;
    pointnode= ^integer;
    var ptr_ke_int : pointitem;
  2. var a,b :pointitem;
    c,d : pointnode;

Keterangan :

  1. Pada contoh a)
    • tipe item adalah sama dengan tipe integer
    • tipe pointitem adalah tipe pointer yang menunjuk data bertipe item
    • tipe pointnode adalah tipe pointer yang menunjuk data bertipe integer
  2. Pada contoh b)
    • variabel a dan b bertipe pointitem
    • variabel c dan d bertipe pointnode

Kalau diperhatikan, pada contoh b) di atas keempat variabel (a,b,c dan d) semuanya merupakan variabel pointer yang menunjuk ke variabel bertipe integer. Meskipun demikian karena tipe dasarnya berbeda (variabel a dan b bertipe pointitem sedang variabel c dan d bertipe pointnode) maka dianggap bahwa variabel a dan b memiliki tipe yang sama, demikian pula c dan d, tetapi a tidak dapat disamakan dengan c atau d. Dengan demikian assignment a:= b dan c:= d adalah sah, tetapi a := d adalah ilegal.



Membuat Dan Menghapus/Merusak Variabel Dinamis

Dalam bahasa Pascal, pembuatan variabel dinamis dapat dilakukan dengan prosedur standar NEW. Bila p adalah variabel pointer ke tipe node maka prosedur :
NEW(p) akan menghasilkan suatu variabel dinamis bertipe node dan memberikan alamatnya ke pointer p.

Untuk menghapus, merusak atau mengembalikan memori yang dipakai oleh variabel dinamis dapat digunakan prosedur dasar DISPOSE, misalnya DISPOSE(p) berarti mengembalikan memori yang ditempati oleh variabel dinamis yang ditunjuk oleh pointer p ke sistem.


Pointer Bernilai NIL

Kadang suatu variabel pointer p tidak menunjuk ke suatu variabel dinamis. Ini dapat dilakukan dengan memberikan assignment
p:= nil. Perlu dibedakan pengertian variabel pointer yang bernilai NIL dengan variabel pointer yang tak terdefinisi (tak tentu). Variabel pointer bernilai NIL berarti ia tidak menunjuk ke suatu variabel dinamis, sedang variabel pointer yang bernilai tak tentu berarti ia mungkin mengacu (menunjuk) ke suatu lokasi sembarang di memori. Dengan perintah DISPOSE(p) maka akan berakibat p menjadi tak tentu sehingga disarankan untuk mengassign dengan nilai NIL setiap kali suatu variabel dinamis dibebaskan (misal p :=NIL)


CATATAN

Untuk mempermudah pemahaman tentang variabel pointer, berikut ini adalah cara pengartian tanda “^“, bila diberikan deklarasi p : ^item:

  • p : ^item berarti p menunjuk ke suatu tipe item
  • p^ berarti apa yang ditunjuk oleh p

Dengan demikian bila p dan q adalah dua variabel pointer bertipe sama, maka assignment p:= q dan p^ := q^ adalah legal. Meskipun demikian mereka mempunyai pengertian yang berbeda. p:= q berarti p dan q menunjuk ke lokasi yang sama, sedang p^ := q^ berarti p dan q menunjuk lokasi yang berbeda tetapi isi variabel dinamis yang ditunjuk keduanya sama. Jadi assignment yang kedua dapat diartikan seperti halnya meng-copy-kan isi variabel q ke variabel p sehingga isi keduanya sama.


TUGAS

  1. Bila diberikan deklarasi tipe dalam Pascal :
    type ptr = ^node;
    var p,q,r : ptr;
    var x,y,z : node;
     

    tentukan statemen yang manakah di bawah ini yang legal/benar dan yang manakah yang tidak benar/ilegal? Berikan alasannya masing-masing.

a) NEW(p)
b) NEW(q^)
c) NEW(x)
d) p:=r
e) q := y
f) r := NIL
g) z := p^
h) p := ^x
i) dispose(y)
j) dispose(p^)
k) dispose(r)
l) x := NEW(p)
m) q^ := NIL
n) p^ := x^
o) z := NIL

  1. Diberikan sepenggal program pendek sebagai berikut:
    Program nyoba_pointer;
    uses crt;
    var b : byte; c : char;
    pb : ^byte; pc,pd : ^char;
    BEGIN
b := 100;
c:= ‘S’;
new(pb);
pb^ := b;
new(pc); pc^:= c;
pd :=pc;
writeln(pd^, pc^);
pc^:= ‘M’;
writeln(pd^, pc^);
new(pd);
pd^:= ‘R’;
writeln(pd^,pc^);
  1. END.
Exercise Antrian
Program CONTOH_ANTRIAN;
uses crt; 

const maxelm = 15;
type tipeelemen = record
nama : string[15];
nim : string[10];
lulus: byte;
end;
antrian = record
banyak : 0..maxelm;
elemen : array[1..maxelm] of tipeelemen;
end;
var Q : antrian;
function penuhq(q : antrian):boolean;
begin
if q.banyak = maxelm then penuhq := true
else penuhq:= false
end;
function kosongq(q:antrian):boolean;
begin
if q.banyak = 0 then kosongq := true
else kosongq := false
end;
Procedure addq(var q: antrian;data : tipeelemen);
begin
if not penuhq(q) then
begin
q.banyak := q.banyak + 1;
q.elemen[q.banyak] := data;
end
else
writeln(‘Maaf antrian penuh’);
end;
Procedure deleteq(var data : tipeelemen; var q: antrian);
var i : 0..maxelm;
begin
if not kosongq(q) then
begin
data := q.elemen[q.banyak];
for i:= 2 to q.banyak do
q.elemen[i-1] := q.elemen[i];
q.banyak := q.banyak-1;
end
else
writeln(‘Maaf antrian kosong’);
end;
Procedure bacadata(var q:antrian);
var i,n : integer;
t : tipeelemen;
begin
write(‘Berapa data mau dimasukkan : ‘);readln(n);
for i:= 1 to n do
begin
write(‘Nama mahasiswa : ‘);readln(t.nama);
write(‘NIM : ‘);readln(t.nim);
t.lulus := random(3)+3;
addq(q,t);
end;
end;
Procedure tampil(q : antrian);
var i : 0..maxelm;
t : tipeelemen;
begin
writeln(‘Urutan | Nama | NIM | LULUS’);
for i:= 1 to q.banyak do
begin
t := q.elemen[i];
writeln(i:3,t.nama:20, t.nim:12,t.lulus:5,’ tahun’);
end;
end;
begin
clrscr;
bacadata(q);
tampil(q);
readln
end.

Exercise Tumpukan
Program contoh_tumpukan;
uses crt;
const maxelm = 15;
type tipeelemen = char;
tumpukan = record
banyak : 0..maxelm;
elemen : array[1..maxelm] of tipeelemen;
end; 

var stack : tumpukan;
I: 0..maxelm;
KAL : STRING;
{Function penuhs(s:tumpukan):boolean;
begin
JIKA s.banyak=maxelm MAKA penuhs := TRUE
ELSE penuhs := FALSE
end;
Function kosongs(s : tumpukan):boolean;
begin
JIKA s.banyak = 0 THEN kosongs := TRUE
ELSE kosongs := FALSE
end;
}

Procedure PUSH(var s : tumpukan; data : tipeelemen);
begin
{if not penuhs(s) then }
begin
s.banyak := s.banyak+1;
s.elemen[s.banyak] := data;
end
{else writeln(‘Maaf antrian penuh’)}
end;
Procedure POP(var data : tipeelemen; var s : tumpukan);
begin
{if not kosongs(s) then }
begin
data := s.elemen[s.banyak];
s.banyak := s.banyak -1;
end
{else writeln(‘MAAF ANTRIAN KOSONG’)}
end;
Procedure tampilstack(s:tumpukan);
var i: 0..maxelm;
data : tipeelemen;
begin
writeln(‘Isi stack secara berurutan adalah: ‘);
for i:= 1 to s.banyak do
begin
pop(data,s);
write(data);
end;
end;
BEGIN
CLRSCR;
WRITE(‘MASUKKAN KALIMAT PENDEK : ‘);READLN(KAL);
FOR I:= 1 TO LENGTH(KAL) DO PUSH(STACK,KAL[I]);
tampilstack(stack);
readln;
end.

TUMPUKAN & ANTRIAN (STACK & QUEUE)

STACK (TUMPUKAN)

Stack (tumpukan) sebenarnya secara mudah dapat diartikan sebagai list (urutan) dimana penambahan dan pengambilan elemen hanya dilakukan pada satu sisi yang disebut top (puncak) dari stack.

Dengan melihat definisi tersebut maka jelas bahwa pada stack berlaku aturan LIFO (Last In First Out), yaitu elemen yang terakhir masuk akan pertama kali diambil atau dilayani. Salah satu analogi yang dapat dikemukakan di sini adalah tumpukan piring atau barang lain. Pada saat kita hendak menumpuk piring-piring tersebut tentulah yang kita lakukan adalah meletakkan piring pertama pada tempatnya, selsnjutnya meletakkan piring kedua di atas piring pertama dan demikian seterusnya. Pada saat kita hendak mengambil satu piring dari tumpukan tersebut, tentu yang diambil adalah piring teratas (yang terakhir kali ditaruh), bukan yang terbawah (yang pertama kali diletakkan).

Dua operasi dasar pada stack adalah PUSH (operasi pemasukan elemen ke dalam stack) dan POP (operasi pengambilan satu elemen dari dalam stack). Di bawah ini diberikan contoh pemakaian operasi PUSH dan POP dan isi stack untuk setiap selesai eksekusi satu operasi.
(Untuk mempermudah penulisan, di bawah ini isi stack tidak dituliskan secara bertumpuk, tetapi dengan kesepakatan:

  • elemen paling kanan adalah elemen yang ada pada TOS (Top Of the Stack)
  • stack yang dipakai bernama S
  • PUSH(S,B) berarti memasukkan elemen B ke dalam stack S
  • POP(B,S) berarti mengambil elemen dari stack S dan menaruhnya ke dalam variabel B
Operasi yang dilakukan Isi Stack Keterangan
Kondisi Awal kosong
PUSH(‘A’,S) A
PUSH(‘B’,S) AB
PUSH(‘C’,S) ABC
POP(Data,S) AB Variabel Data berisi ‘C’
PUSH(‘D’,S) ABD
POP(Data,S) AB Data berisi ‘D’
POP(Data,S) A Data berisi ‘B’


IMPLEMENTASI STACK DALAM BAHASA PASCAL

Implementasi dalam bahasa Pascal dapat dilakukan dengan memanfaatkan struktur data record dan array. Array dipergunakan untuk menyimpan elemen-elemen yang dimasukkan. Selain itu diperlukan pula suatu variabel untuk mencatat banyaknya elemen yang adadi dalam array yang sekaligus menunjukkan TOS. Pada implementasi di bawah ini:

  • konstanta maxelm menyatakan banyaknya elemen maksimum yang dapat ditampung oleh stack
  • typeelemen adalah tipe data yang akan disimpan di dalam stack (bisa integer, word, real, boolean, char , string atau lainya)
  • banyak adalah field yang menyatakan banyaknya elemen dalam stack saat itu, yang sekaligus menyatakan TOS

Deklarasi tipe untuk tumpukan (stack):
type tumpukan = record
banyak :0..maxelm;
elemen : array[1..maxelm] of typeelemen;
end;

Selain prosedur untuk POP dan PUSH, kita dapat pula menambahkan sejumlah fungsi untuk membantu penanganan kesalahan diantaranya adalah fungsi PENUHS (untuk mengecek apakah stack penuh) fungsi KOSONGS (untuk mengecek apakah stack kosong) dan fungsi SIZES (untuk mengetahui banyaknya elemen di dalam stack). Masing-masing sub program di atas dapat disajikan pseudocode-nya sebagai berikut:


Procedure Inisialisasi(var S : tumpukan);
begin
S. banyak¬ 0
end;


Function PENUHS(S : tumpukan): boolean;
begin
Jika S.banyak = maxelm maka PENUHS ¬ true
else PENUHS ¬false
end;


Function KOSONGS(S : tumpukan):boolean;
begin
If S.banyak = 0 then KOSONGS ¬ true
else KOSONGS¬false
end;


Procedure PUSH(data : tipeelemen; var S : tumpukan);
begin
If not KOSONGS(S) then
begin

  1. S.banyak ¬ S.banyak +1
  2. S.elemen[S.banyak]¬data

end
else
Tampilkan pesan kesalahan “Stack Penuh”
end;


Procedure POP(var S : tumpukan; var data : typeelemen);
begin
If not KOSONGS(S) then
begin

  1. data¬S.elemen[S.banyak]
  2. S.banyak ¬ S.banyak – 1

end
else
Tampilkan pesan kesalahan “Stack kosong”
End;


ke atas halaman ke menu utama


QUEUE (ANTRIAN)

Queue atau antrian sebenarnya juga merupakan suatu list. Salah satu sifat yang membedakan queue dengan stack adalah bahwa pada queue penambahan elemen dilakukan pada salah satu ujung (ujung depan) dan pengambilan dilakukan pada ujung yang lain (ujung belakang) . Dengan demikian queue menggunakan prinsip FIFO (First In First Out), yaitu elemen yang pertama masuk akan pertama kali pula dikeluarkan.

Seperti pada stack, operasi-operasi dasar pada queue adalah operasi penambahan elemen ( sebut “ADDQ”) dan operasi pengambilan elemen (sebut DELQ). Di bawah ini diberikan contoh pemakaian operasi PUSH dan POP dan isi stack untuk setiap selesai eksekusi satu operasi.
(Untuk mempermudah penulisan, di bawah ini isi queue tidak dituliskan secara bertumpuk, tetapi dengan kesepakatan:

  • elemen paling kanan adalah elemen yang ada pada ujung belakang (yang terakhir kali masuk)
  • queue yang dipakai bernama Q
  • ADDQ(Q,B) berarti memasukkan elemen B ke dalam queue Q
  • DELQ(B,Q) berarti mengambil elemen dari queue Q dan menaruhnya ke dalam variabel B
Operasi yang dilakukan Isi Queue Keterangan
Kondisi Awal kosong
ADDQ(‘A’,Q) A
ADDQ(‘B’,Q) AB
ADDQ(‘C’,Q) ABC
DELQ(Data,Q) BC Variabel Data berisi ‘A’
ADDQ(‘D’,Q) BCD
DELQ(Data,Q) CD Data berisi ‘B’
POP(Data,S) D Data berisi ‘C’


IMPLEMENTASI QUEUE DALAM BAHASA PASCAL

Implementasi dalam bahasa Pascal dapat dilakukan dengan memanfaatkan struktur data record dan array. Array dipergunakan untuk menyimpan elemen-elemen yang dimasukkan. Selain itu diperlukan pula suatu variabel untuk mencatat banyaknya elemen yang ada di dalam array. Pada implementasi di bawah ini:

  • konstanta maxelm menyatakan banyaknya elemen maksimum yang dapat ditampung oleh queue
  • typeelemen adalah tipe data yang akan disimpan di dalam queue(bisa integer, word, real, boolean, char , string atau lainya)
  • banyak adalah field yang menyatakan banyaknya elemen dalam queue saat itu
  • queue diimplementasikan sebagai array linier dengan memandang bahwa elemen terdepan selalu berada pada sel pertama (implementasi fisik), sehingga bila terjadi pengambilan satu elemen maka semua elemen di belakang elemen terambil (bila ada) harus digeser ke depan satu langkah

Deklarasi tipe untuk antrian (queue):
type antrian= record
banyak :0..maxelm;
elemen : array[1..maxelm] of typeelemen;
end;

Selain prosedur untuk ADDQ dan DELQ, kita dapat pula menambahkan sejumlah fungsi untuk membantu penanganan kesalahan diantaranya adalah fungsi PENUHQ (untuk mengecek apakah antrian penuh) fungsi KOSONGQ (untuk mengecek apakah antrian kosong) dan fungsi SIZEQ (untuk mengetahui banyaknya elemen di dalam queue). Masing-masing sub program di atas dapat disajikan pseudocode-nya sebagai berikut:


Procedure Inisialisasi(var q : antrian);
begin
Q. banyak ¬ 0
end;


Function PENUHQ(q : antrian): boolean;
begin
Jika Q.banyak = maxelm maka PENUHQ ¬ true
else PENUHQ¬false
end;


Function KOSONGQ(q : antrian):boolean;
begin
If Q.banyak = 0 then KOSONGQ ¬ true
else KOSONGQ ¬ false
end;


Procedure ADDQ(data : tipeelemen; var q : antrian);
begin
If not PENUHQ(Q) then
begin

  1. Q.banyak¬ Q.banyak+1
  2. Q.elemen[Q.banyak] ¬ data

end
else
Tampilkan pesan kesalahan “Antrian Penuh”
end;


Procedure DELQ(var q : antrian; var data : typeelemen);
begin
If not KOSONGS(Q) then
begin

  1. data ¬Q.elemen[1]
  2. for i:= 2 to Q.banyak
    Q.elemen[i-1] ¬ Q.elemen[i]
  3. Q.banyak ¬ Q.banyak- 1

end
else
Tampilkan pesan kesalahan “Antrian kosong”
End;


 


Dengan melihat implementasi di atas kita dapat merasakan adanya ketidakefisienan, yaitu bahwa untuk mengambil satu elemen dari queue kita harus menggeser sisa elemen yang sebenarnya tidak menjadi perhatian kita. Untuk data yang sedikit mungkin ini tidak terasa, tetapi untuk data yang banyak maka ketidakefisienan ini akan tampak jelas.

Untuk mengatasi permasalahan di atas kita dapat menggunakan implementasi queue berputar, yaitu dengan membiarkan sel tetap kosong bila elemen pada sel tersebut baru saja diambil. Bagaimanakah implementasi queue berputar? Perhatikan implementasi di bawah ini.

type antrian_putar= record
depan,belakang,banyak :0..maxelm;
elemen : array[1..maxelm] of typeelemen;
end;

Field depan dan belakang masing-masing adalah untuk mencatat lokasi elemen terdepan (yang akan diambil berikutnya) dan lokasi elemen paling belakang (elemen terakhir kali masuk)


Procedure ADDQ(data : tipeelemen; var q : antrian_putar);
begin
If not PENUHQ(Q) then
begin

  1. Q.belakang ¬ (Q.belakang mod maxelm)+1
  2. Q.elemen[Q.belakang] ¬ data

end
else
Tampilkan pesan kesalahan “Antrian Penuh”
end;


Procedure DELQ(var q : antrian_putar; var data : typeelemen);
begin
If not KOSONGS(Q) then
begin

  1. data ¬ Q.elemen[Q.depan]
  2. Q.banyak ¬ Q.banyak- 1
  3. Q.depan ¬ (Q.depan mod maxelm)+1

end
else
Tampilkan pesan kesalahan “Antrian kosong”
End;


PROSEDUR dan FUNGSI REKURSIF

PROSEDUR dan FUNGSI REKURSIF

Prosedur dan fungsi merupakan sub program yang sangat bermanfaat dalam pemrograman, terutama untuk program atau proyek yang besar. Manfaat penggunaan sub program antara lain adalah :


Prosedur dan fungsi merupakan sub program yang sangat bermanfaat dalam pemrograman, terutama untuk program atau proyek yang besar. Manfaat penggunaan sub program antara lain adalah :

  1. meningkatkan readibility, yaitu mempermudah pembacaan program
  2. meningkatkan modularity, yaitu memecah sesuatu yang besar menjadi modul-modul atau bagian-bagian yang lebih kecil sesuai dengan fungsinya, sehingga mempermudah pengecekan, testing dan lokalisasi kesalahan.
  3. meningkatkan reusability, yaitu suatu sub program dapat dipakai berulang kali dengan hanya memanggil sub program tersebut tanpa menuliskan perintah-perintah yang semestinya diulang-ulang.

Sub Program Rekursif adalah sub program yang memanggil dirinya sendiri selama kondisi pemanggilan dipenuhi.
adalah Dengan melihat sifat sub program rekursif di atas maka sub program rekursif harus memiliki :

  1. kondisi yang menyebabkan pemanggilan dirinya berhenti (disebut kondisi khusus atau special condition)
  2. pemanggilan diri sub program (yaitu bila kondisi khusus tidak dipenuhi)

Secara umum bentuk dari sub program rekursif memiliki statemen kondisional :

if kondisi khusus tak dipenuhi
then panggil diri-sendiri dengan parameter yang sesuai
else lakukan instruksi yang akan dieksekusi bila kondisi khusus dipenuhi

Sub program rekursif umumnya dipakai untuk permasalahan yang memiliki langkah penyelesaian yang terpola atau langkah-langkah yang teratur. Bila kita memiliki suatu permasalahan dan kita mengetahui algoritma penyelesaiannya, kadang-kadang sub program rekursif menjadi pilihan kita bila memang memungkinkan untuk dipergunakan. Secara algoritmis (dari segi algoritma, yaitu bila kita mempertimbangkan penggunaan memori, waktu eksekusi sub program) sub program rekursif sering bersifat tidak efisien .
Dengan demikian sub program rekursif umumnya memiliki efisiensi dalam penulisan perintah, tetapi kadang tidak efisien secara algoritmis. Meskipun demikian banyak pula permasalahan-permasalahan yang lebih sesuai diselesaikan dengan cara rekursif (misalnya dalam pencarian / searching, yang akan dibahas pada pertemuan-pertemuan yang akan datang).
Contoh sub program rekursif dalam bahasa Pascal.

    1. Contoh sederhana

PROCEDURE TULIS_1(banyak : integer;kata : string);
begin
if banyak > 1 then TULIS_1(banyak-1,kata);
writeln(kata, banyak:5);
end;

OUTPUT (misal dipanggil dengan TULIS_1(5,”Cetakan ke “))

Cetakan ke 1
Cetakan ke 2
Cetakan ke 3
Cetakan ke 4
Cetakan ke 5

Bandingkan prosedur dan outputnya di atas dengan prosedur di bawah ini!

PROCEDURE TULIS_2(banyak : integer;kata : string);
begin
writeln(kata, banyak:5);
if banyak > 1 then TULIS_1(banyak-1,kata);
end;

OUTPUT (misal dipanggil dengan TULIS_2(5,”Cetakan ke “))

Cetakan ke 5
Cetakan ke 4
Cetakan ke 3
Cetakan ke 2
Cetakan ke 1

Mengapa hasilnya jauh berbeda?

    1. Contoh terapan

Secara matematis, perkalian dua bilangan bulat positif a dengan b (ditulis ab atau a x b) pada hakekatnya merupakan penjumlahan dari a sebanyak b suku, yaitu a + a + a + …. + a sebanyak b suku. Misalnya 2 x 3 dapat diartikan sebagai 2 + 2 + 2 = 6 , yaitu penjumlahan 2 sebanyak 3 suku   Dengan mengingat bahwa suatu bilangan bila dikalikan dengan angka 1 (satu) akan menghasilkan bilangan itu sendiri, maka permasalahan perkalian dengan menyatakannya dalam bentuk penjumlahan di atas dapat diselesaikan dengan komputer secara mudah.


 


Dengan non rekursif

    1. Dengan prosedur

Procedure KALI_BIASA_P(a,b : integer; var hasil : longint);
var i : integer;
begin
hasil := 0;
for i:= 1 to b do hasil := hasil + a;
end;

    1. Dengan fungsi

Function KALI_BIASA_F(a,b:integer):longint;
var hasil : longint; i: integer;
begin
hasil := 0;
for i:= 1 to b do hasil := hasil + a;
KALI_BIASA_F := hasil;

end;


 


Dengan Rekursif

      1. Dengan Prosedur

Procedure KALI_REK_P(a,b:integer;var hasil:longint)
begin
if b>1 then KALI_REK_P(a,b-1,hasil);
hasil:= hasil+a;
end;

      1. Dengan Fungsi

Function KALI_REK_F(a,b:integer):longint;
begin
if b>1 then
KALI_REK_F := KALI_REK_F(a,b-1)+a
else
KALI_REK_F := a;
end;


 

REKAMAN (RECORD)
 

RECORD (REKAMAN)

Record adalah tipe terstruktur yang terdiri atas sejumlah elemen yang tipenya tidak harus sama.

Elemen di dalam suatu record disebut dengan istilah field (medan). Sebelumnya sudah dibicarakan struktur data yang juga memiliki sejumlah elemen yaitu array. Perbedaan utama dari keduanya adalah bahwa elemen dalam suatu array semuanya memiliki tipe yang sama sedang elemen-elemen di dalam rekaman tidak harus bertipe sama. Contoh :

type LARIK = array [1..100] of real;
var a : larik;

Dari deklarasi di atas berarti kita mendefinisikan suatu tipe data baru bernama LARIK yang merupakan array berisi data real dengan elemen maksimum yang dapat ditampung sebanyak 100 yang ditandai sebagai elemen ke-1, ke-2, ke-3 dan seterusnya. Salah satu variabel yang memiliki tipe LARIK adalah variabel A. Dengan demikian variabel A dapat menampung data maksimum sebanyak 100 dan data yang disimpan harus bertipe real.. Untuk memahami tipe data record perhatikan contoh tabel data mahasiswa di bawah ini.

NIM NAMA USIA JML_SAUDARA
5234 K Mustofa 26 2
5233 AS Anandya S 25 1
5127 Dina A 23 3
4006 Yadi 20 5

Bila kita perhatikan tabel di atas, kita peroleh gambaran:

    1. dalam 1 kolom, tipe data yang diisikan pasti sama (misal NIM dideklarasikan sebagai data numeric (integer misalnya) maka semua NIM harus berupa data angka)
    2. suatu obyek dapat dikenali secara tunggal menggunakan gabungan nilai data kolom-kolom dalam setiap barisnya. (misal : gabungan nilai NIM ‘5234’, NAMA ‘K. Mustofa’, USIA ‘26’ dan JML_SAUDARA ‘2’ mengacu pada suatu obyek yang tertentu yaitu seseorang)

Di dalam konsep database, kolom dalam suatu tabel seperti di atas disebut sebagai atribut atau field. Sedang gabungan field-field dalam suatu baris disebut tuple atau record. Dengan deskripsi di atas, dapat dikatakan bahwa seorang mahasiswa dapat dinyatakan sebagai suatu record yang memiliki 4 data (elemen) yaitu field NIM, field NAMA, field USIA dan field JML_SAUDARA.



Bagaimanakan representasi record dalam PASCAL?

Record dalam bahasa pascal dapat dideklarasikan dengan cara (bentuk umum) sebagai berikut:

TYPE nama_pengenal_record = RECORD
nama_field1: type_field1;
nama_field2: type_field2;
nama_field3: type_field3;
:
:
nama_fieldn: type_fieldn;
END;

Dengan mengambil contoh data mahasiswa di atas, kita dapat memiliki deklarasi sebagai berikut:

TYPE mhs = RECORD
nim : integer;
nama: string[30];
usia: byte;
jml_saudara: 0..15;
END;



Bagaimana Menggunakan Tipe Data Record dan Mengakses Field-Field di dalamnya?

Kalau kita sudah memiliki deklarasi record seperti di atas, maka untuk menggunakannya di dalam program tentunya kita tinggal memesan variabel-variabel yang kita perlukan dengan perintah VAR. Perhatikan contoh berikut:

var satu : mhs;
banyak : array[1..20] of mhs;

Deklarasi / pemesanan variabel di atas berarti program memerlukan alokasi memori yang akan dipergunakan untuk menyimpan data bertipe mhs. Variabel “satu” dapat dipergunakan untuk menyimpan data satu mahasiswa, sedang variabel “banyak” dapat dipergunakan untuk menyimpan maksimum 20 data mahasiswa. Untuk mengakses data bertipe record kita tidak dapa melakukannya dengan satu langkah seperti halnya ketika kita mengakses suatu variabel sederhana. Kalau kita memiliki variabel p bertipe sederhana (integer, byte, word, char, real) maka untuk memberikan nilai kira dapat menggunakan operator assignment (:=) atau untuk membaca masukan dari user kita dapat melakukannya dengan perintah readln(p), tetapi dengan data/variabel bertipe record kita tidak dapat melakukannya sesederhana itu. Untuk mengakses fiel-field pada suatu variabel bertipe record dapat dilakukan dengan dua cara :

  1. dengan menggunakan operator/notasi titik

Syntax secara umum :

nama_variabel_record . nama_field

Contoh berikut adalah sah:

    1. readln(satu.nim); readln(satu.nama);
    2. satu.nama := ‘AMIKOM’;
    3. banyak[1]. nim := 5558;
    4. banyak[6].nama := ‘YOGYAKARTA’;
  1. dengan menggunakan statemen pembatas with … do

Syntax secara umum :

with nama_variabel do
begin
lakukan operasi terhadap field-field
—–
—–
end;
Contoh berikut adalah valid :

    1. with satu do readln(nama)
    2. with satu do begin
      readln(nama);{sama artinya dengan readln (satu.nama)}
      readln(nim);
      readln(usia);
      jml_saudara := 5; {sama artinya dengan satu.jml_saudara := 5}
      nama:= ‘AKU’
      end;
    3. with banyak[5] do begin
      readln(usia);
      readln(nama);
      end;

Kembali ke atas


Contoh program :

Program contoh_rekaman;
uses crt;

type mhs = record
nim: string[8];
nama: string[30];
usia: byte;
jml_saudara: 0..20;
end;
var siswa : array[1..20] of mhs;
i, n : integer;
begin
clrscr;
write(‘Banyak data yang akan dimasukkan : ‘); readln(n);

{langkah pemasukan data}

for i:= 1 to n do
begin
clrscr;
writeln(‘Data ke : ‘,i);
with siswa[i] do
begin write(‘ NIM : ‘);readln(nim);
write(‘NAMA : ‘);readln(nama);
write(‘USIA : ‘);readln(usia);
write(‘SAUDARA : ‘);readln(jml_saudara);
end;
end;

{penampilan data}

clrscr;
writeln(‘DATA YANG ANDA MASUKKAN ‘);
writeln;
for i:= 1 to n do
begin
write(siswa[i].nim:11);
write(siswa[i].nama:23);
write(siswa[i].usia:5);
write(siswa[i].jml_saudara:5);
writeln;
end;
readln;
end.





Leave a comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s