Anda di halaman 1dari 15

Judul:STACK

Mata Kuliah: PI1043 Struktur Data


Penulis: Tjokorda Agung Budi Wirayuda, ST, MT
Program Studi Diploma 3 Teknik Informatika
IT Telkom Bandung

STACK
Stack merupakan suatu bentuk struktur data yang digunakan untuk merepresentasikan mekanimse
penyimpanan data dengan mekanisme tumpukan. Salah satu ilustrasi ”mudah” untuk memahami
STACK bila kita melihat tumpukan buku, kardus atau kontainer. Asumsikan buku, kardus atau
kontainer sebagai data, maka dapat kita temukan:
1. Penambahan buku, kardus atau kontainer akan selalu diletakkan diatas
2. Kita hanya bisa mengambil/mengakses buku, kardus atau kontainer pada posisi teratas

Melihat prinsip dari STACK maka dapat dikatakan STACK menggunakan prinsip LIFO (Last In First Out)
dalam artian bahwa data yang terakhir masuk adalah data yang harus diproses pertama kali. Dalam
implementasinya STACK dapat dibangun denga menggunakan list berkait atau array (tergantung
pada kebutuhan). Secara formal dapat didefinisikan bahwa sebuah STACK memiliki ciri-ciri:

1. Terdapat sebuah acuan dengan nama TOP yang digunakan untuk mengacu pada Element
teratas pada STACK
2. Aturan penyisipan/penambahan dan penghapusan elemen mengikuti prinsip LIFO,
penyisipan dan penghapusan selalu dilakukan pada elemen teratas (bila dianalogikan
dengan konsep list-linear maka penyisipan selalu menggunakan InsertFirst() dan
pengaksesan/penghapusan menggunakan DeleteFirst())

Data yang dimasukkan secara berturut-turut adalah 55, 98, 10.


Dengan menggunakan STACK maka kondisi peyimpanan data
TOP adalah sebagai berikut:

@ 10 98 55

Gambar 1 Ilustrasi Penyimpanan Data Pada STACK dengan List-Linear


Salah satu pemanfaatan struktur data STACK adalah untuk proses perhitungan ekspresi aritmatika
(postfix), algoritma back-tracking dan algoritma rekursif.

Implementasi ADT STACK


ADT merupakan sebuah konsep untuk melakukan abtraksi terhadap suatu permasalahan dengan
menentukan/mendefinisikan sebuah TYPE dan sekumpulan PRIMITIF yang digunakan untuk
menyelesaikan masalah tersebut.

Dalam materi kali ini kita akan mengimplementasikan STACK dengan menggunakan list-linear,
dimana secara umum tahapannya sama dengan membangun List-Linear yaitu mendefinisikan
InfoType, Element, List dan Primitif. Dapat dikatakan bahwa STACK yang diimplementasikan
merupakan bentuk khusus dari List-Linear dengan menerapkan prinsip LIFO.

Algoritma Bahasa C
TYPE InfoType: typedef struct tempInfoType {
< Data: Integer int Data;
> } InfoType;
TYPE ElementS: typedef struct tempElementS {
< Info: InfoType, InfoType Info;
Next : Address struct ElementS *Next;
> } ElementS, *ElementSPtr
TYPE Stack: typedef struct tempStack {
< TOP: Address ElementSPtr TOP;
> } Stack;
S:Stack Stack S;

PRIMITIF
#define TOP(S) S->TOP
#define INFO(P) P->Info
#define NEXT(P) P->Next
ILUSTRASI

ALGORITMA
Define TOP(S) adalah alamat elemen TOP, dimana operasi penyisipan dan
penghapusan dilakukan (mengembalikan element pertama pada STACK)
Define Info(P) adalah informasi yang disimpan pada alamat P
Define NEXT(P) adalah alamat suksesor P
KODE C
#define TOP(S) S->TOP;
#define INFO(P) P->Info;
#define NEXT(P) P->Next;
typedef enum {false=0,true=1} boolean;

PRIMITIF
boolean IsStackEmpty(Stack S);
ILUSTRASI

ALGORITMA
Function StackEmpty (S) -> boolean
{Test stack kosong, true jika kosong, false jika tidak}
-> (TOP(S)==Nil)
KODE C
boolean IsStackEmpty(Stack S)
{
if (S.TOP==NULL)
return true;
else
return false;
}

PRIMITIF
void CreateStack(Stack *S)
ILUSTRASI

ALGORITMA
CreateStack: -> S
{Membuat sebuah stack kosong}
TOP(S) <- Nil
KODE C
void CreateStack(Stack *S)
{
TOP(S)=NULL;
}

PRIMITIF
void PUSH@(Stack *S,ElementSPtr *P);
ILUSTRASI

ALGORITMA
procedure PUSH@(in S:Stack;out P:ElementS)
{ I.S Terdefinisi sebuah Stack S
F.S Memasukkan sebuah elemen ke dalam STACK
}
NEXT(P) <- TOP(S)
TOP(S) <- P
KODE C
void PUSHV(Stack *S,ElementSPtr P)
{
NEXT(P) = TOP(S);
TOP(S) = P;
}

PRIMITIF
void PUSH(Stack *S, InfoType *E);
ILUSTRASI

ALGORITMA
procedure PUSH(in S:Stack; out E:InfoType)
{ I.S Terdefinisi sebuah Stack S
F.S Memasukkan sebuah InfoType E ke dalam STACK
}
Kamus P:Address
Alokasi(P)
Info(P) <- E
PUSH(S,P)
KODE C
void PUSH(Stack *S, InfoType E)
{
ElementSPtr P;
P=createElement(E);
PUSHV(S,P);
}

PRIMITIF
ElementSPtr POP@(Stack *S)
ILUSTRASI

ALGORITMA
function POP@(in S:Stack) -> Address
{ I.S Terdefinisi sebuah Stack S
F.S Mengembalikan Element pertama dari STACK
}
Kamus Lokal P:Address
P <- TOP(S)
TOP(S) <- NEXT(P)
->P
KODE C
ElementSPtr POPV(Stack *S)
{
ElementSPtr P;
P=TOP(S);
TOP(S)=NEXT(P);
return P;
}

PRIMITIF
InfoType POP(Stack *S);
ILUSTRASI

ALGORITMA
function POP(in S:Stack)-> InfoType
{ I.S Terdefinisi sebuah Stack S
F.S Mengembalikan InfoType Element pertama dari STACK dan
menghapus Element Pertama dari STACK
}
Kamus P:Address
E: InfoType
P <- POP@(S)
E <-Info(P)
Dealokasi(P)
-> E

KODE C
InfoType POP(Stack *S)
{ InfoType E;
ElementSPtr P;
P=POPV(S);
E=P->Info;
return E;
}
Implementasi ADT STACK untuk Pemrosesan Ekspresi Artimatik
Seperti yang telah disampaikan sebelumnya bahwa STACK sering digunakan untuk melakukan
pemrosesan Ekspersi Aritmatik. Ekspresi aritmatik secara umum dapat dalam bentuk:

1. Infix, adalah bentuk ekspresi aritmatik dimana Operator terletak di antara 2 buah Operan
contohnya (2+2).
2. Prefix, adalah bentuk ekspresi aritmatik dimana Operator terletak di didepan 2 buah Operan
contohnya + 2 2
3. Postfix, , adalah bentuk ekspresi aritmatik dimana Operator terletak di setelah Operan
contohnya 2 2 +

Dari sisi eksekusi operator maka notasi infix harus diproses sesuai dengan tingkat/level operator
yang ada (precedence rule). Misalkan untuk ekspresi: 10 + 2 * 3 akan menghasilkan nilai 60 bukan
36 karena operasi perkalian dilakukan terlebih dahulu. Urutan eksekusi operator dalam notasi infix
dapat ditegaskan dengan menggunakan tanda kurung buka “(“ dan kurung tutup “)” . Misalkan
untuk contoh sebelumnya, apabila kita menuliskan sebagai (10 + 2 ) * 3 maka akan dihasilkan nilai
36. Hal tersebut tidak berlaku dalam notasi prefix dan postfix, dimana urutan operator menentukan
urutan operasi yang akan dieksekusi.

Infix Prefix PostFix


((15 / (7 - (1 + 1))) * 3) - (2 + (1 + - * / 15 - 7 + 1 1 3 + 2 + 1 1 15 7 1 1 + - / 3 * 2 1 1 + + -
1))

Dari sisi manusia dapat dikatakan bahwa notasi infix lebih mudah dihitung namun tidak halnya
dengan komputer. Komputer akan lebih mudah menghitung suatu ekspresi apabila diberikan dalam
notasi prefix atau postfix. Algoritma dari cara eksekusi Komputer terhadap ekspresi prefix dan
postfix adalah sebagai berikut:

Algoritma Pemrosesan notasi infix yang disederhanakan


Misalkan diketahui Input telah berisi ekspresi infix. Pemrosesan
hasil akhir ekspresi:
1. Baca Input mulai dari elemen awal sampai elemen akhir
2. Bila hasil pembacaan adalah Operand maka simpan operand
Tersebut dalam Stack
3 Bila hasil pembacaan adalah Operator maka ambil 2 buah elemen
Dalam stack lalu lakukan operasi dan simpan hasilnya dalam
Stack
4.Hasil akhir operasi akan berada pada Stack sebagai elemen Pertama

Algoritm Pemrosesan ekspresi prefix [Wikipedia]


Scan the given prefix expression from right to left
for each symbol
{
if operand then
push onto stack
if operator then
{
operand1=pop stack
operand2=pop stack
compute operand1 operator operand2
push result onto stack
}
}
return top of stack as result

Algoritm Pemrosesan ekspresi posfix [Wikipedia]


While there are input tokens left
Read the next token from input.
If the token is a value
Push it onto the stack.
Otherwise, the token is an operator
It is known a priori that the operator takes n arguments.
If there are fewer than n values on the stack
# (Error) The user has not input sufficient values in the
expression.
Else,
Pop the top n values from the stack.
Evaluate the operator, with the values as arguments.
Push the returned results, if any, back onto the stack.
If there is only one value in the stack
That value is the result of the calculation.
Else If there are more values in the stack
(Error) The user input has too many values.

Materi kali ini kita akan mencoba untuk melakukan konversi suatu bentuk notasi infix menjadi prefix,
adapun algoritma konversi secara umum adalah sebagai berikut:

Konversi notasi infix ke postfix


Baca Input mulai dari elemen awal sampai elemen akhir
Lakukan pembacaan elemen Terdapat 4 (empat) aturan yang digunakan
untuk memproses token yang diterima yaitu :
1. Jika ditemukan simbol kurung buka “(“ lakukan Operasi push pada
stack akan digunakan untuk menyimpan simbol tersebut ke dalam stack.
2. Jika ditemukan simbol kurung tutup “)” lakukan Operasi pop
digunakan untuk mengeluarkan operator-operator yang berada di dalam
stack.
3. Jika terdapat simbol operator:
 Jika TOP(S) dari stack tersebut kosong atau berisi simbol
“(“ maka operasi push akan digunakan untuk memasukan
operator tersebut pada posisi di TOP(S)
 Jika operator yang berada dipuncak stack merupakan elemen
yang memiliki tingkat yang sama atau lebih tinggi maka
operasi pop digunakan untuk mengeluarkan operator tersebut
diikuti operasi push untuk menyimpan operator hasil scanning
untaian.
 Jika operator yang berada di puncak stack memiliki tingkat
yang lebih rendah dari operator yang discan, maka operator
baru akan langsung dimasukan ke dalam stack dengan operasi
push.
4. Jika ditemukan suatu operand maka Nilai operand yang ada langsung
dijadikan output dari notasi Postfix.

Dengan melihat/mengamati Algoritma Konversi infix menjadi postfix diatas maka kita dapat
membangun pseudo-code dalam bentuk notasi algortima

Misalkan Input adalah array yang telah berisi ekspresi infix yang
terpisah-pisah
for i=1 to length(Input)
E=input[i];
if (isOperand(E)==true) then
output(E)
else
depend on (E)
case '(' : PUSH(S,E);
case ')' : while TOP(S) <> '('
output(POP(S))
endwhile
POP(S)
case '=' : while (isStackEmpty()==false)
output(POP(S))
endwhile
else :
temp=TOP(S)
lv1=cekLevel(temp)
lv2=cekLevel(E)
if temp=='(' then
PUSH(S,E)
else
if lv1 >= lv2 then
output(POP(S));
PUSH(S,E);
else
PUSH(S,E)
endif
endif
enddependon
endif
endfor

LAMPIRAN A: Kode Lengkap Untuk Stack Awal


STACK.H
#ifndef __STACK_H
#define __STACK_H
#define TOP(S) S->TOP
#define INFO(P) P->Info
#define NEXT(P) P->Next
typedef enum {false=0,true=1} boolean;

typedef struct tempInfoType {


char Data[20];
} InfoType;
typedef struct tempElementS {
InfoType Info;
struct ElementS *Next;
} ElementS, *ElementSPtr;
typedef struct tempStack {
ElementSPtr TOP;
} Stack;
Stack S;
//=======InfoType primitif==========
InfoType entriInfoType();
InfoType entriInfoTypeV(char *a);
void setData(InfoType *temp);
char* getData(InfoType *temp);
void displayInfo(InfoType temp);
//==================================
//======Element Primitif============
ElementSPtr createElementV();
ElementSPtr createElementV2(char *a);
ElementSPtr createElement(InfoType a);
//===================================
//=======STACK PRIMITIF==============
boolean IsStackEmpty(Stack S);
void CreateStack(Stack *S);
void PUSHV(Stack *S,ElementSPtr P);
void PUSH(Stack *S, InfoType E);
ElementSPtr POPV(Stack *S);
InfoType POP(Stack *S);
//===================================
#endif

stackImp.c
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include "stack.h"
//=======Implementasi InfoType primitif==========
void setData(InfoType *temp)
{ /*I.S : InfoType temp terdefinisi dan masih kosong
F.S : Informasi data dari InfoType temp terentri dan disimpan*/
fflush(stdin);
gets(temp->Data);
fflush(stdin);
}
InfoType entriInfoType()
{/*I.S: -
F.S: Tercipta sebuah info Type yang telah berisi data */
InfoType temp;
printf("Masukkan Data:");
setData(&temp);
return temp;
}
InfoType entriInfoTypeV(char *a)
{/*I.S: -
F.S: Tercipta sebuah info Type yang telah berisi data */
InfoType temp;
strcpy(temp.Data,a);
return temp;
}
char* getData(InfoType *temp)
{ /*I.S : InfoType temp terdefinisi dan telah berisi data
F.S : Mengembalikan Informasi Indeks dari InfoType temp */
return temp->Data;
}

void displayInfo(InfoType temp)


{/*I.S: InfoType temp telah terdefinisi dan berisi data
F.S: Menampilkan informasi yang dari temp ke layar */
printf("Data : %s \n",getData(&temp));
}
//===================================
//======Implementasi Element Primitif============
ElementSPtr createElement(InfoType a)
{/*I.S: InfoType a telah terdefinisi
F.S: Tercipta sebuah elemen dimana Data yang dimiliki sama dengan data
pada InfoType a */
ElementSPtr temp=(ElementSPtr)malloc(sizeof(ElementS));
if (temp==NULL)
{printf("Gagal Alokasi Memori\n");}
else
{printf("Sukses Alokasi Memori\n");}
temp->Next=NULL;
temp->Info=a;
return temp;
}

ElementSPtr createElementV()
{/*I.S: InfoType belum terdefinisi
F.S: Tercipta sebuah elemen dimana dengan meminta user untuk
mengentrikan data dengan memanggil entriInfoType() */
createElement(entriInfoType());
}
ElementSPtr createElementV2(char *a)
{/*I.S: InfoType belum terdefinisi
F.S: Tercipta sebuah elemen dimana dengan meminta user untuk
mengentrikan data dengan memanggil entriInfoType() */
createElement(entriInfoTypeV(a));
}
//===================================

//=======Implementasi STACK PRIMITIF==============


boolean IsStackEmpty(Stack S)
{
if (S.TOP==NULL)
return true;
else
return false;
}
void CreateStack(Stack *S)
{
TOP(S)=NULL;
}
void PUSHV(Stack *S,ElementSPtr P)
{
NEXT(P) = TOP(S);
TOP(S) = P;
}
void PUSH(Stack *S, InfoType E)
{
ElementSPtr P;
P=createElement(E);
PUSHV(S,P);
}
ElementSPtr POPV(Stack *S)
{
ElementSPtr P;
P=TOP(S);
TOP(S)=NEXT(P);
return P;
}
InfoType POP(Stack *S)
{ InfoType E;
ElementSPtr P;
P=POPV(S);
E=P->Info;
return E;
}

main.c
#include <stdio.h>
#include <stdlib.h>
#include "stack.h"

int main(int argc, char *argv[])


{ //Misalkan akan dientri data 10,20,30
CreateStack(&S);
//Entri 10
PUSHV(&S,createElementV2("10"));
//Entri 20
PUSHV(&S,createElementV2("20"));
//Entri 30
PUSHV(&S,createElementV2("30"));
//Menampilkan data
displayInfo(POP(&S));
displayInfo(POP(&S));
displayInfo(POP(&S));
system("PAUSE");
return 0;
}

Hasil Program

LAMPIRAN A-2: Kode Lengkap STACK Operasi Infix ke PostFix dengan


Array

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
char input[20];
typedef enum {false=0,true=1} boolean;
typedef struct tempStack{
char Data[20];
int idS;
}STACK;
STACK SOprnd,SOprtr;
void PUSH(STACK *S,char a);
char POP(STACK *S);
char TOP(STACK S);
float Hitung(char *OP1,char *OP2,char *OPRT);
boolean isOperand(char a);
boolean isStackEmpty(STACK S);
int cekLevel(char *a);
int main(int argc, char *argv[])
{ //menyiapkan stack operand
SOprnd.idS=0;
SOprtr.idS=0;
printf("Masukkan operasi infix: ");
fflush(stdin);
gets(input);
printf("Notasi infix: %s \n",input);
printf("Notasi prefix: \n");
int i;
int j;
char temp[3];
char tempO;
int lv1,lv2;
for(i=0;i<strlen(input);i++)
{ j=0;
while((isOperand(input[i])==true)&&(i<strlen(input))){
temp[j]=input[i];
j++;i++;
}

//keluar dari while maka dapat temp akan berisi operand jika j>0
if (j>0)
{printf("%s ",temp);
i--;}
else
{ temp[0]=input[i];
switch(temp[0])
{ case '(' : PUSH(&SOprtr,temp[0]);break;
case ')' : while((TOP(SOprtr)!='(')&&(isStackEmpty(SOprtr)==false)){
tempO=POP(&SOprtr);
printf("%c ",tempO);
}
POP(&SOprtr);
break;
case '=' : while (isStackEmpty(SOprtr)==false){
tempO=POP(&SOprtr);
printf("%c ",tempO);
}
break;
default:
tempO=TOP(SOprtr);
lv1=cekLevel(&tempO);
lv2=cekLevel(&temp[0]);
if (tempO=='(')
PUSH(&SOprtr,temp[0]);
else
{ if (lv1>=lv2)
{tempO=POP(&SOprtr);
printf("%c ",tempO);
PUSH(&SOprtr,temp[0]);}
else

PUSH(&SOprtr,temp[0]);
}
}
}
}
printf("\n");
system("PAUSE");
return 0;
}
void PUSH(STACK *S,char a)
{ S->Data[S->idS]=a;
S->idS++;

}
char POP(STACK *S)
{ char temp;
temp=S->Data[S->idS-1];
S->idS--;
return temp;
}
char TOP(STACK S)
{ return S.Data[S.idS-1];
}
boolean isStackEmpty(STACK S)
{ if (S.idS>0)
return false;
else
return true;
}
float Hitung(char *OP1,char *OP2,char *OPRT){
char temp;
float op1,op2,hasil;
op1=atof(OP1);
op2=atof(OP2);
temp=OPRT[0];
switch (temp){
case '+': hasil=op1+op2;break;
case '-': hasil=op1-op2;break;
case '*': hasil=op1*op2;break;
case '/': hasil=op1/op2;break;
}
return hasil;
}
boolean isOperand(char a)
{ boolean status;
status=true;
switch (a){
case '+': status=false;break;
case '-': status=false;break;
case '*': status=false;break;
case '/': status=false;break;
case '=': status=false;break;
case '(': status=false;break;
case ')': status=false;break;
}
return status;
}

int cekLevel(char *a)


{ char temp; int level;
level=0;
temp=a[0];
switch (temp){
case '+': level=1;break;
case '-': level=1;break;
case '*': level=2;break;
case '/': level=2;break;
}
return level;
}

Hasil Program

Lampiran B Precedence Rule untuk Simbol Aritmatik


Level Precedence Simbol Makna
1 () [] -> . :: Grouping, scope, array/member access
2 ! ~ - + * & sizeof type cast (most) unary operations, sizeof and
++x --x type casts
3 * / % Multiplication, division, modulo
4 + - Addition and subtraction
5 << >> Bitwise shift left and right
6 < <= > >= Comparisons: less-than, ...
7 == != Comparisons: equal and not equal
8 & Bitwise AND
9 ^ Bitwise exclusive OR
10 | Bitwise inclusive (normal) OR
11 && Logical AND
12 || Logical OR
13 ?: Conditional expression (ternary
operator)
14 = += -= *= /= %= &= |= ^= Assignment operators
<<= >>=
15 , Comma operator
Semakin kecil level maka Simbol menjadi semakin penting