Archive | September, 2013

Struktur data dan algoritma Tree pada ML (Meta Language)

26 Sep

Konsep struktur data Tree telah dipelajari pada kuliah struktur data dan algoritma. Soal-soal pada latihan tutorial kali ini adalah soal-soal yang relatif pernah dikerjakan secara imperatif. Peserta diharapkan memahami bagaimana algoritma tree direpresentasi dalam pemrograman fungsional. Peserta juga diharapkan dapat membandingkan penyelesaian imperatif dengan fungsional pada setial soal yang diberikan. Tuliskan analisa perbandingan dalam komentar program. Analisa perbandingan dapat meliputi: kompleksitas running time dan alokasi memory, kemudahan pembuatan/perbaikan/modifikasi program, dan kemudahan membaca program. Gunakan sebisa mungkin higher order function pada setiap soal. Bila ada yang kurang jelas pada soal, silahkan tambahkan asumsi anda.

1. Buatlah sebuah fungsi bernama “soal1”. Fungsi tersebut menerima sebuah string, dan menghasilkan list of pair, yang tiap pairnya menyatakan karakter dan jumlah kemunculan karakter tersebut pada string input. Urutan pada pair output tidak penting.

soal1 :  string → (char * int) list

Contoh:

– soal1 “saya makan”

> val it = [(#”s”, 1), (#”a”,4), (#”y”,1), (#”m”,1), (#”k”,1), (#”n”,1)]

(Catatan: soal ini terkait dengan penerapan huffman code untuk kompresi,  harap melanjutkan lagi pengerjaannya hingga sampai encoding dan decoding, tidak perlu  dikumpulkan pada tutorial, tapi sebagai bagian persiapan ujian)

2. Buatlah sebuah fungsi bernama “soal2”. Fungsi tersebut membaca sebuah input dengan struktur data tree dan memeriksa apakah input tree tersebut merupakan binary search tree atau tidak. Struktur data tree didefinisikan dengan:

datatype bst = Leaf | Node of int * bst * bst

soal2 : bst → bool

Contoh:

– val t1 = Node(6, Node(4,Leaf,Leaf),
Node(15, Node(11,Leaf,Leaf), Node(24,Leaf,Leaf)));
– soal2 t1;
> val it = true : bool

3. Buatlah sebuah fungsi bernama “soal3” yang menerima satu argument tree. Fungsi ini akan mencetak isi tree yang diberikan secara inorder. (hint: gunakan perintah “print”);

soal3 : bst → unit

4. Buatlah sebuah fungsi bernama “soal4” yang memiliki dua argumen. Argumen pertama adalah sebuah list bilangan dan argumen kedua adalah sebuah tree. Fungsi ini akan memasukan argumen pertama kedalam tree satu persatu mulai dari elemen pertama pada list, dengan tetap mempertahankan struktur binary search tree namun tidak perlu balance.

soal4 : int list → bst → bst

5. Buatlah sebuah fungsi bernama “soal5”. Fungsi ini serupa dengan “soal4” namun dengan mengimplementasikan AVL Tree. Input tree yang diberikan bila bukan merupakan AVL Tree maka soal5 memberikan output berupa exception “Input bukan AVL Tree”. (hint: gunakan
“raise”)
soal5 : int → bst → bst

JAWABAN:

load "List";
load "Int";

datatype bst = Leaf | Node of int * bst * bst;

val tr = Node (4,
Node (2,
Node (1, Leaf, Leaf),
Node (3, Leaf, Leaf)
),
Node (6,
Node (5, Leaf, Leaf),
Node (7, Leaf, Leaf)
)
);

val ntr = Node (4,
Node (2,
Node (3, Leaf, Leaf),
Node (1, Leaf, Leaf)
),
Node (6,
Node (5, Leaf, Leaf),
Node (7, Leaf, Leaf)
)
);

val soal1 = let
fun calc [] = []
| calc (c::cs)= let
val next = List.filter (fn x => x <> c) cs
in (c,length cs - length next + 1) :: (calc next) end
in calc o explode end;

fun inorder Leaf = []
| inorder (Node (k,l,r)) = inorder l @ [k] @ inorder r;

val soal2 = let
fun sorted [] = true
| sorted [_] = true
| sorted (x1::x2::xs) = x1 <= x2 andalso sorted (x2::xs)
in sorted o inorder end;

val soal3 = (map (print o Int.toString)) o inorder

fun insert (k,Leaf) = Node (k, Leaf, Leaf)
| insert (k, Node (x,l,r))= if k < x
then Node (x, insert (k,l), r)
else Node (x, l, insert (k,r))

exception NotBST;
fun soal4 ls tree = if soal2 tree
then foldl insert tree ls;
else raise NotBST

fun rotateR Leaf = Leaf
| rotateR (Node (k,Leaf,r)) = Node (k,Leaf,r)
| rotateR (Node (k,Node (l,ll,lr),r)) = Node (l,ll,Node (k,lr,r));

fun rotateL Leaf = Leaf
| rotateL (Node (k,l,Leaf)) = Node (k,l,Leaf)
| rotateL (Node (k,l,(Node (r,rl,rr)))) = Node (r,Node (k,l,rl),rr);

fun height Leaf = 0
| height (Node (_,l,r)) = Int.max (height l, height r) + 1

fun balance Leaf = Leaf
| balance (Node (k,l,r)) = if height l > height r
then let
fun rotate' tree = case tree of Leaf => Leaf
| (Node (x,xl,xr)) => if height xr > height xl
then rotateL tree
else tree
val subtree = (k,rotate' l,r)
in rotateR (Node subtree) end
else let
fun rotate' tree = case tree of Leaf => Leaf
| (Node (x,xl,xr)) => if height xl > height xr
then rotateR tree
else tree
val subtree = (k,l,rotate' r)
in rotateL (Node subtree) end;

fun isBalanced Leaf = true
| isBalanced (Node (k,l,r)) = Int.abs (height l - height r) <= 1
andalso isBalanced l
andalso isBalanced r;

fun rebalance Leaf = Leaf
| rebalance (Node (k,l,r)) = let
val tree = Node (k,rebalance l, rebalance r)
in if isBalanced tree
then tree
else balance tree
end;

exception NotAVL;
fun soal5 k tree = if soal2 tree andalso isBalanced tree
then rebalance (insert (k,tree))
else raise NotAVL;