MAKALAH
" DESAIN DAN ANALISIS ALGORITMA (DAA) "
Mencari Nilai Median dari Senarai yang Tidak Terurut dengan Metode : Divide and Conquer dan Decrease and Conquer
Oleh :
FAUZI DWI SUSANTO (105060801111041) RIDHO SAPUTRA (105060807111053) RIFQI KURNIAWAN (105060807111155)
PROGRAM STUDI TEKNIK INFORMATIKA
PROGRAM TEKNOLOGI INFORMASI DAN ILMU KOMPUTER UNIVERSITAS BRAWIJAYA
MALANG
2012
1. Pengertian
A. Divide dan Conquer
Algoritma Divide and Conquer merupakan algoritma yang sangat popular di dunia Ilmu Komputer. Divide and Conquer merupakan algoritma yang berprinsip memecah-mecah permasalahan yang terlalu besar menjadi beberapa bagian kecil sehingga lebih mudah untuk diselesaikan.
Langkah-langkah umum algoritma Divide and Conquer :
Divide : Membagi masalah menjadi beberapa upa-masalah yang memiliki kemiripan dengan masalah semula namun berukuran lebih kecil ( idealnya berukuran hampir sama ).
Conquer : Memecahkan ( menyelesaikan ) masing-masing upa-masalah ( secara rekursif ).
Combine : Menggabungkan solusi masing-masing upa-masalah sehingga membentuk solusi masalah semula.
B. Decrease dan Conquer
Algoritma Decrease and conquer merupakan metode desain algoritma dengan mereduksi persoalan menjadi beberapa sub-persoalan yang lebih kecil, tetapi selanjutnya hanya memproses satu sub-persoalan saja. Berbeda dengan divide and conquer yang memproses semua sub-persoalan dan menggabung semua solusi setiap sub-persoalan.
Langkah-langkah umum algoritma Decrease and Conquer :
Decrease :
mereduksi persoalan menjadi beberapa persoalan yang lebih kecil (biasanya dua sub-persoalan).Conquer : Selesaikan permasalahan yang lebih kecil tersebut dengan cara memproses satu sub-persoalan secara rekursif.
Kembangkan permasalahan yang lebih kecil itu sehingga menyelesaikan permasalahan sebenarnya. Dapat dilakukan dengan dengan metode top down atau bottom up.
Tidak ada tahap combine dalam decrease and conquer.
2. Permasalahan
Bagaimana mencari median dari senarai yang tidak terurut ?
3. Solusi Permasalahan a. Divide dan Conquer
1. Lakukan partisi pada senarai tersebut menjadi bagian yang lebih kecil dengan cara membaginya menjadi sub bagian yang memiliki kemiripan dengan senarai semula namun berukuran lebih kecil (idealnya berukuran hampir sama). Misalnya jumlah bilangan dalam senarai tersebut ada 7, maka kita bagi menjadi 7 bagian.
2. Lakukan sorting (pengurutan) dengan menggunakan merge sort pada kumpulan bilangan dalam senarai yang telah dibagi menjadi kecil sebelumnya. Langkah ini merupakan metode combine dari divide dan conquer.
3. Setelah proses sorting selesai, dilakukan pemecahan (solusi) masalah mencari mediannya dengan cara menjumlahkan jumlah senarai tersebut dan kemudian membaginya dengan 2.
- Jika jumlah senarainya genap maka median terletak di setengah jumlah senarai tersebut + 1. Misal jumlah senarainya ada 8, maka setengah dari jumlah senarai tersebut adalah 4 lalu +1, sehingga mediaanya adalah 4+1 = 5.
- Jika jumlah senarainya ganjil maka mediannya terletak di tengah dari jumlah senarainya. Misal jumlah senarainya 7 maka mediannya 4.
b. Decrease dan Conquer
1. Lakukan partisi dengan memilih pivot pada elemen bilangan pertama dari senarai tersebut.
2. Lalu, bandingkan pivot tersebut dengan bilangan setelahnya sampai dengan elemen senarai terakhir.
3. Setelah melakukan perbandingan dengan pivot tadi, cek letak pivot tersebut.
Jika urutan pivot = (jumlah senarai / 2) maka mediannya adalah pivot tersebut.
Jika urutan pivot > (jumlah senarai / 2) maka mediannya terletak
terdapat pada bagian kiri pivot. Setelah itu, hapus pivot dan semua bilangan di sebelah kanan pivot tersebut.
Jika urutan pivot < (jumlah senarai / 2) maka mediannya terletak
terdapat pada bagian kanan pivot. Setelah itu, hapus pivot dan semua bilangan di sebelah kiri pivot tersebut.
4. Ulangi langkah 3 sampai nilai mediannya ditemukan.
5. Algoritma Program a. Divide dan Conquer
int main deklarasi
jumdata : integer a : integer
*data : int
for a <- 0 to jumdata do --> masukkan data[a]
endfor
for a <- 0 to jumdata do --> tampilkan data[a]
endfor Merge
for a <- 0 to jumdata do
--> tampilkan data[a] //data sudah tersorting endfor
tampil median : proses median Proses Merge
deklarasi a : integer b : integer batas : integer temp : integer
batas := kurang(jumdata,1) for a <- 0 to batas do
for b <- batas to (b > a) do if(data[b] < data [a] then temp <- data[b];
data[b] <- data[a];
data[a] <- temp;
endif
endfor endfor
Proses Median result : float index : int Proses isGenap
return (angka % 2 == 0) if(isGenap(jumdata)) then index <- (jumdata / 2)
result := bagi((jumlah (data[index-1],data[index])), 2) else
result <- data[bagi((kurang (jumdata, 1)), 2)]
endif
return(result)
b. Decrease dan Conquer
struct (value : int, *next : nilai, *prev : nilai) nilai int main
deklarasi jumdata : int a : int
*data : int
for a <- 0 to jumdata do --> input data[a]
for a <- 0 to jumdata do --> output data[a]
*pivot, *min, *max : nilai min <- pivot
max <- pivot
for a <- 1 to jumdata do
if(data[a]<=pivot->value) then *temp : nilai
temp->value <- data[a]
if(if(data[a]<=min->value) then min->prev <- temp
temp->prev <- NULL temp->next <- min min <- temp
else
*walker : nilai walker <- min
while (data[a]>walker->value) do walker <- walker->next
endwhile
temp->prev <- walker->prev walker->prev->next <- temp walker->prev <- temp
temp->next <- walker walker <- temp
endif endif
else if (data[a]>=pivot->value) then *temp : nilai
temp->value <- data[a]
if(if(data[a]>=min->value) then max->prev <- temp
temp->prev <- max temp->next <- NULL max <- temp
else
*walker : nilai walker <- max
while (data[a]<walker->value) do walker <- walker->prev
endwhile
temp->next <- walker->next temp->prev->walker
walker->next->prev <- temp walker->next <- temp
walker <- temp endif
endif endfor jum <- 0 walker <- min
while (walker != NULL) do jum++
tampilkan walker->value walker <- walker->next endwhile
med <- (jum/2)+1 jum <- 0
walker <- min
while (walker != NULL) do jum++
tampilkan walker->value walker <- walker->next if (jum==med) then
median <- walker break
endif endwhile
--> output walker->prev->value //nilai median
6. Kompleksitas
a. Divide dan Conquer
Untuk menyederhanakan perhitungan kompleksitas waktu MergeSort, kita membuat asumsi ukuran senarai adalah perpangkatan dari 2, yaitu n=2
kdengan k adalah bilangan bulat positif.
Kompleksitas waktu dihitung dari jumlah perbandingan dengan elemen-elemen senarai.
T(n) = jumlah perbandingan pada pengurutan dua buah sub senarai + jumlah perbandingan pada prosedur Merge.
Kompleksitas prosedur Merge adalah t(n) = cn = O(n), sehingga kompleksitas algoritma Merge Sort menjadi (dalam bentuk relasi rekurens) :
T (n )= { 2T n 2 a , n=1 + cn , n>1
dalam hal ini,a dan c adalah konstanta.
Penyelesaian persamaan rekurens : T(n) = T(n/2)+cn
= 2(2T(n/4) + cn/2) + cn = 4T(n/4) + 2cn
= 4(2T(n/8) + cn/4) + 2 cn = ...
= 2
kT(n/2
k)+kcn
Persamaan terakhir dapat diselesaikan karena basis rekursif adalah ketika ukuran senarai adalah 1, sehingga :
T(n) = nT(1) + cn
2log n
Banyak langkah dalam algoritma sorting (p) = C + 1 +1 + 1 = C + 3 Untuk for banyak langkah = (akhir-awal+2)+ (akhir-awal+1)(p+1)
= ((n-1)-0+2) + ((n-1)+0+1) (C+3+1)
= (n-1+2) + (n-1+1) (C+4)
= 3n+1 + n(C+4)
= 3n + 1 + Cn + 4n
= 7n + Cn + 1
Best Casenya : C(n) = ∑
i=1 1
7 n+Cn+1
Worstcasenya : C(n) = ∑
i=1 n
7 n+Cn+1
Average casenya tidak ada karena seluruh operasi dilakukan untuk membandingkan dari elemen yang pertama sampai yang terakhir.
Sehingga,
T(n) = nT(1) + cn
2log n
= na + cn
2log n = O(n(
2log n))
Jadi, MergeSort mempunyai kompleksitas waktu asimptotik O (n
2log n).
b. Decrease dan Conquer
Algoritma di dalam Selection Sort terdiri dari kalang bersarang. Dimana kalang tingkat pertama (disebut pass) berlangsung N-1 kali. Di dalam kalang kedua, dicari elemen dengan nilai terkecil. Jika didapat, indeks yang didapat ditimpakan ke variabel min. Lalu dilakukan proses penukaran. Begitu seterusnya untuk setiap Pass. Pass sendiri makin berkurang hingga nilainya menjadi semakin kecil. Berdasarkan operasi perbandingan elemennya :
Banyak langkah dalam algoritma sorting (p) = 6C + 8
Untuk for banyak langkah = (akhir-awal+2)+ (akhir-awal+1)(p+1)
= (n-1+2) + (n-1+1) (6C+8+1)
= (n+1) + (n) (6C+9)
= (n+1) + 6Cn + 9n
= 10n + 6Cn + 1
Best Casenya : C(n) = ∑
i=1 1
10 n+6 Cn+1
Worstcasenya : C(n) = ∑
i=1 n
10 n+6 Cn+1
Average casenya tidak ada karena seluruh operasi dilakukan untuk membandingkan dari elemen yang pertama sampai yang terakhir.
T (n )=(n−1)+(n−2)+…+2+1= ∑
i=1 n−1
n−i
¿ n(n−1)
2 =O(n
2)
Jadi kompleksitasnya secara simptotik adalah O(n
2).
7. Kode Program
a. Divide dan Conquer
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
float median(int*, int);
void merge(int*, int);
int isGenap(int);
int main(){
int jumdata,a;
int *data;
printf("\n ========================================================\n\n");
printf(" PROGRAM MENCARI NILAI MEDIAN DENGAN DIVIDE & CONQUER \n\n");
printf(" ========================================================\n\n");
printf("\n Masukkan jumlah data (senarai) : ");
scanf("%d",&jumdata);
data=(int*)malloc (sizeof(int)*jumdata);
for(a=0;a<jumdata;a++){
printf(" Masukkan data ke %d: ",a+1);
scanf("%d",&data[a]);
}
printf("\n");
printf(" Tampilkan data yang telah diiputkan : ");
for(a=0;a<jumdata;a++){
printf("%d ",data[a]);
}
printf("\n\n");
merge(data, jumdata);
printf(" Tampilkan data yang sudah di sorting : ");
for(a=0;a<jumdata;a++){
printf("%d ",data[a]);
}
printf("\n\n\n");
printf(" ---\n");
printf(" Maka, nilai mediannya adalah : | %0.0f |\n", median(data, jumdata));
printf(" ---\n");
getch();
return 0;
}
void merge(int* data, int jumdata){
int a,b,batas, temp;
batas = jumdata-1; // array paling tinggi, karena dimulai dari 0 for(a=0;a<batas;a++){
for(b=batas;b>a;b--){
if(data[b] < data[a]){
temp = data[b];
data[b] = data[a];
data[a] = temp;
} }
} }
int isGenap(int angka){
return (angka % 2 == 0);
}
float median(int* data, int jumdata){
float result;
if(isGenap(jumdata)){
int index = jumdata/2;
result = (float)(data[index-1] + data[index]) / 2; //krn array dari 0 }
else{
result = (float)data[(jumdata-1)/2]; //krn array dari 0 }
return(result);
}
b. Decrease dan Conquer
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
struct nilai { int value;
nilai *next;
nilai *prev;
} typedef nilai;
int main(){
int jumdata,a;
int *data;
printf("\n ========================================================\n\n");
printf(" PROGRAM MENCARI NILAI MEDIAN DENGAN DECREASE & CONQUER \n\n");
printf(" ========================================================\n\n");
printf("\n Masukkan jumlah data (senarai) : ");
scanf("%d",&jumdata);
data=(int*)malloc (sizeof(int)*jumdata);
for(a=0;a<jumdata;a++){
printf(" Masukkan data ke %d: ",a+1);
scanf("%d",&data[a]);
}
printf("\n");
printf(" Tampilkan data yang telah diiputkan : ");
for(a=0;a<jumdata;a++){
printf("%d ",data[a]);
}
printf("\n\n");
nilai *pivot;
pivot=(nilai *)malloc(sizeof(nilai));
nilai *min;
nilai *max;
pivot->value=data[0];
pivot->next=NULL;
pivot->prev=NULL;
min=pivot;
max=pivot;
for(a=1;a<jumdata;a++){
if(data[a]<=pivot->value){
nilai *temp;
temp=(nilai *)malloc(sizeof(nilai));
temp->value=data[a];
if(data[a]<=min->value){
min->prev=temp;
temp->prev=NULL;
temp->next=min;
min=temp;
} else{
nilai *walker;
walker=min;
while(data[a]>walker->value){
walker=walker->next;
}
temp->prev=walker->prev;
walker->prev->next=temp;
walker->prev=temp;
temp->next=walker;
walker=temp;
} }
else if(data[a]>=pivot->value){
nilai *temp;
temp=(nilai *)malloc(sizeof(nilai));
temp->value=data[a];
if(data[a]>=max->value){
max->next=temp;
temp->prev=max;
temp->next=NULL;
max=temp;
} else{
nilai *walker;
walker=max;
while(data[a]<walker->value){
walker=walker->prev;
}
temp->next=walker->next;
temp->prev=walker;
walker->next->prev=temp;
walker->next=temp;
walker=temp;
} } }
nilai *median, *walker;
int jum=0;
walker=min;
while(walker!=NULL){
jum++;
printf(" %d->",walker->value);
walker=walker->next;
}
int med;
med=(jum/2)+1;
printf("\n\n");
jum=0;
walker=min;
while(walker!=NULL){
jum++;
printf(" %d->",walker->value);
walker=walker->next;
if(jum==med){
median=walker;
break;
} }
printf("\n\n");
printf(" ---\n");
printf(" Maka, nilai mediannya adalah : | %d |\n", walker->prev->value);
printf(" ---\n");
getch();
return 0;
}