Mata Kuliah: Struktur Data dan Algoritma
Pertemuan: 05
Topik: Stack
Waktu: 150 menit
Sifat: Open Book
Instruksi: Pilih satu jawaban yang paling tepat.
Stack adalah struktur data yang mengikuti prinsip:
Pada stack, operasi untuk menambahkan elemen disebut:
Operasi peek() pada stack berfungsi untuk:
Pada implementasi stack dengan array, jika topIndex = -1, maka:
Diberikan stack kosong S. Setelah operasi: push(1), push(2), push(3), pop(), push(4), elemen top adalah:
Kompleksitas waktu operasi push() pada stack yang diimplementasikan dengan linked list adalah:
Mengapa operasi push dan pop pada stack menggunakan linked list dilakukan di head (bukan tail)?
Dalam algoritma balanced parentheses, ketika menemukan kurung tutup ), aksi yang dilakukan adalah:
String mana yang balanced?
([)]{[()]}((()){[}Dalam konversi infix ke postfix, operator dengan prioritas lebih tinggi akan:
Ekspresi infix A + B * C dalam notasi postfix adalah:
+ A * B CA B C * +A B + C *A B C + *Dalam evaluasi postfix 3 4 + 5 *, urutan operasi yang benar adalah:
Hasil evaluasi postfix 8 2 / 3 - adalah:
Dalam doubling strategy untuk dynamic array stack, kapan resize dilakukan?
Amortized time complexity dari operasi push pada dynamic array stack dengan doubling strategy adalah:
Apa yang menyebabkan “stack overflow” pada rekursi?
Dalam sistem undo/redo, ketika user melakukan aksi baru setelah undo, apa yang terjadi dengan redo stack?
Untuk mengimplementasikan queue menggunakan stack, minimal diperlukan berapa stack?
Operator ^ (pangkat) berbeda dari +, -, *, / dalam hal:
Dalam implementasi MinStack (stack dengan operasi getMin O(1)), struktur data tambahan yang dibutuhkan adalah:
Trace Operasi Stack
Diberikan stack kosong. Trace operasi berikut dan tuliskan:
push(10), push(20), pop(), push(30), push(40), pop(), pop(), push(50)
Perbandingan Implementasi
Jelaskan kelebihan dan kekurangan implementasi stack menggunakan: a) Array statis b) Array dinamis c) Linked list
Dalam kondisi apa masing-masing implementasi paling cocok digunakan?
Balanced Parentheses Trace
Trace algoritma balanced parentheses untuk string berikut. Tunjukkan isi stack pada setiap langkah dan tentukan apakah balanced atau tidak:
a) {[()()]}
b) [({}])
Konversi Infix ke Postfix
Konversi ekspresi infix berikut ke postfix menggunakan algoritma Shunting-Yard. Tunjukkan trace lengkap (token, action, stack, output):
A * (B + C) - D / E
Evaluasi Postfix
Evaluasi ekspresi postfix berikut. Tunjukkan trace lengkap (token, action, stack, calculation):
6 2 3 + - 3 8 2 / + *
Implementasi peek() dan isEmpty()
Implementasikan method peek() dan isEmpty() untuk stack menggunakan array dalam C++. Sertakan penanganan error yang tepat.
Implementasi Stack dengan Linked List
Implementasikan class StackLinkedList dalam C++ dengan operasi:
push(int value)pop()peek()isEmpty()size()Sertakan destructor untuk mencegah memory leak.
Analisis Kompleksitas
Analisis kompleksitas waktu (best, worst, average case) dan ruang untuk operasi berikut pada stack yang diimplementasikan dengan array dinamis:
a) push() saat array belum penuh b) push() saat array penuh (perlu resize) c) 100 operasi push berturut-turut (amortized)
Konversi Rekursi ke Iterasi
Fungsi rekursif berikut menghitung jumlah digit suatu bilangan:
int sumDigits(int n) {
if (n == 0) return 0;
return (n % 10) + sumDigits(n / 10);
}
Ubah fungsi ini menjadi versi iteratif menggunakan stack eksplisit.
String Reversal dengan Stack
Implementasikan fungsi untuk membalik string menggunakan stack. Fungsi harus:
Validasi Ekspresi Matematika
Modifikasi algoritma balanced parentheses untuk memvalidasi ekspresi matematika yang mengandung:
(), [], {}+, -, *, /Fungsi harus mengembalikan true jika ekspresi valid (kurung balanced dan operator/operand benar).
Next Greater Element
Jelaskan algoritma untuk menemukan Next Greater Element (NGE) untuk setiap elemen dalam array menggunakan stack dengan kompleksitas O(n). Berikan contoh untuk array [4, 5, 2, 10, 8].
Browser History
Jelaskan bagaimana browser history (back/forward) dapat diimplementasikan menggunakan dua stack. Gambarkan state kedua stack setelah operasi berikut:
Sort Stack
Implementasikan fungsi untuk mengurutkan stack secara ascending (elemen terkecil di top) menggunakan hanya satu stack tambahan sebagai tempat sementara. Tidak boleh menggunakan struktur data lain.
Stock Span Problem
Stock span adalah jumlah hari berturut-turut sebelum hari ini di mana harga saham ≤ harga hari ini. Implementasikan fungsi untuk menghitung span menggunakan stack dengan kompleksitas O(n).
Contoh:
Harga: [100, 80, 60, 70, 60, 75, 85]
Span: [1, 1, 1, 2, 1, 4, 6]
Latar Belakang: Dalam operasi militer, sistem command & control harus mampu mengelola perintah dengan fitur undo/redo untuk mengantisipasi perubahan situasi di lapangan. Setiap perintah memiliki ID, deskripsi, unit pelaksana, dan timestamp.
Tugas:
Rancang dan implementasikan MilitaryCommandSystem dengan spesifikasi:
struct Command {
int id;
string description;
string unit;
time_t timestamp;
int priority; // 1-5, 5 tertinggi
};
issueCommand(description, unit, priority): Mengeluarkan perintah barucancelLastCommand(): Membatalkan perintah terakhirreinstateCommand(): Mengembalikan perintah yang dibatalkangetActiveCommands(): Menampilkan semua perintah aktifgetHighPriorityCommand(): Mengembalikan perintah dengan prioritas tertinggiLatar Belakang: Sistem radar pertahanan udara menerima data sinyal secara real-time. Untuk mendeteksi anomali, sistem perlu menganalisis pola kenaikan dan penurunan kekuatan sinyal menggunakan konsep sliding window maximum.
Tugas:
Implementasikan RadarSignalAnalyzer yang dapat:
processSignal(int strength): Memproses sinyal barugetMaxInWindow(): Mendapatkan nilai maksimum dalam window terakhirdetectAnomalies(): Mendeteksi lonjakan sinyal yang mencurigakangetSignalHistory(int n): Mendapatkan n sinyal terakhirAlgoritma Sliding Window Maximum: Gunakan struktur data berbasis stack/deque untuk mencapai kompleksitas O(n) untuk memproses n sinyal.
Sinyal: [10, 15, 12, 20, 18, 50, 25, 30, 28, 35]
Window size: 3
| No | Jawaban | Penjelasan Singkat |
|---|---|---|
| 1 | B | LIFO - Last-In-First-Out |
| 2 | C | push adalah operasi menambah elemen |
| 3 | B | peek melihat tanpa menghapus |
| 4 | C | topIndex = -1 berarti kosong |
| 5 | D | Stack: [1,2,4], top = 4 |
| 6 | C | O(1) karena selalu di head |
| 7 | C | Pop di tail perlu traverse O(n) |
| 8 | B | Pop dan cek apakah match |
| 9 | B | {[()]} adalah balanced |
| 10 | C | Prioritas tinggi menyebabkan pop rendah |
| 11 | B | A B C * + (B*C dulu, lalu +A) |
| 12 | A | 3+4=7, lalu 7*5=35 |
| 13 | B | 8/2=4, 4-3=1 |
| 14 | C | Resize saat penuh |
| 15 | C | O(1) amortized |
| 16 | B | Tidak ada/tidak tercapai base case |
| 17 | C | Redo stack di-clear |
| 18 | B | Minimal 2 stack |
| 19 | B | ^ adalah right-to-left |
| 20 | B | Stack tambahan untuk minimum |
| Operasi | Stack | Return |
|---|---|---|
| push(10) | [10] | - |
| push(20) | [10, 20] | - |
| pop() | [10] | 20 |
| push(30) | [10, 30] | - |
| push(40) | [10, 30, 40] | - |
| pop() | [10, 30] | 40 |
| pop() | [10] | 30 |
| push(50) | [10, 50] | - |
Hasil akhir: Stack = [10, 50], Return values: 20, 40, 30
a) Array Statis:
b) Array Dinamis:
c) Linked List:
a) {[()()]}
| Char | Action | Stack | Status |
|---|---|---|---|
| { | Push | [{] | - |
| [ | Push | [{, [] | - |
| ( | Push | [{, [, (] | - |
| ) | Pop, match | [{, [] | ✓ |
| ( | Push | [{, [, (] | - |
| ) | Pop, match | [{, [] | ✓ |
| ] | Pop, match | [{] | ✓ |
| } | Pop, match | [] | ✓ |
Hasil: BALANCED ✓
b) [({}])
| Char | Action | Stack | Status |
|---|---|---|---|
| [ | Push | [[] | - |
| ( | Push | [[, (] | - |
| { | Push | [[, (, {] | - |
| } | Pop, match | [[, (] | ✓ |
| ] | Pop | [[, (] | ( ≠ ] ✗ |
Hasil: NOT BALANCED ✗
Infix: A * (B + C) - D / E
| Token | Action | Stack | Output |
|---|---|---|---|
| A | Output | [] | A |
| * | Push | [*] | A |
| ( | Push | [*, (] | A |
| B | Output | [*, (] | AB |
| + | Push | [*, (, +] | AB |
| C | Output | [*, (, +] | ABC |
| ) | Pop sampai ( | [*] | ABC+ |
| - | Pop *, Push - | [-] | ABC+* |
| D | Output | [-] | ABC+*D |
| / | Push (/ > -) | [-, /] | ABC+*D |
| E | Output | [-, /] | ABC+*DE |
| END | Pop all | [] | ABC+*DE/- |
Hasil Postfix: ABC+*DE/-
Postfix: 6 2 3 + - 3 8 2 / + *
| Token | Action | Stack | Calculation |
|---|---|---|---|
| 6 | Push | [6] | - |
| 2 | Push | [6, 2] | - |
| 3 | Push | [6, 2, 3] | - |
| + | Pop, calc, push | [6, 5] | 2+3=5 |
| - | Pop, calc, push | [1] | 6-5=1 |
| 3 | Push | [1, 3] | - |
| 8 | Push | [1, 3, 8] | - |
| 2 | Push | [1, 3, 8, 2] | - |
| / | Pop, calc, push | [1, 3, 4] | 8/2=4 |
| + | Pop, calc, push | [1, 7] | 3+4=7 |
| * | Pop, calc, push | [7] | 1*7=7 |
Hasil: 7
class StackArray {
private:
static const int MAX_SIZE = 100;
int data[MAX_SIZE];
int topIndex;
public:
StackArray() : topIndex(-1) {}
bool isEmpty() {
return topIndex == -1;
}
int peek() {
if (isEmpty()) {
throw runtime_error("Stack is empty - cannot peek");
// atau: cout << "Error: Stack kosong!" << endl; return -1;
}
return data[topIndex];
}
};
#include <iostream>
using namespace std;
struct Node {
int data;
Node* next;
Node(int val) : data(val), next(nullptr) {}
};
class StackLinkedList {
private:
Node* topNode;
int count;
public:
StackLinkedList() : topNode(nullptr), count(0) {}
~StackLinkedList() {
while (!isEmpty()) {
pop();
}
}
void push(int value) {
Node* newNode = new Node(value);
newNode->next = topNode;
topNode = newNode;
count++;
}
int pop() {
if (isEmpty()) {
cout << "Error: Stack Underflow!" << endl;
return -1;
}
Node* temp = topNode;
int value = temp->data;
topNode = topNode->next;
delete temp;
count--;
return value;
}
int peek() {
if (isEmpty()) {
cout << "Error: Stack kosong!" << endl;
return -1;
}
return topNode->data;
}
bool isEmpty() {
return topNode == nullptr;
}
int size() {
return count;
}
};
a) push() saat array belum penuh:
b) push() saat array penuh (resize):
c) 100 operasi push (amortized):
int sumDigitsIterative(int n) {
stack<int> s;
// Push semua digit ke stack
while (n > 0) {
s.push(n % 10);
n = n / 10;
}
// Pop dan jumlahkan
int sum = 0;
while (!s.empty()) {
sum += s.top();
s.pop();
}
return sum;
}
#include <stack>
#include <string>
using namespace std;
string reverseString(string str) {
stack<char> s;
// Push semua karakter
for (char c : str) {
s.push(c);
}
// Pop untuk mendapatkan reversed string
string reversed = "";
while (!s.empty()) {
reversed += s.top();
s.pop();
}
return reversed;
}
bool isValidExpression(string expr) {
stack<char> s;
bool expectOperand = true; // Mulai dengan expecting operand
for (char c : expr) {
if (c == ' ') continue;
// Kurung buka
if (c == '(' || c == '[' || c == '{') {
s.push(c);
expectOperand = true;
}
// Kurung tutup
else if (c == ')' || c == ']' || c == '}') {
if (s.empty()) return false;
char top = s.top(); s.pop();
if (!isMatchingPair(top, c)) return false;
expectOperand = false;
}
// Operator
else if (c == '+' || c == '-' || c == '*' || c == '/') {
if (expectOperand) return false; // Operator tanpa operand
expectOperand = true;
}
// Operand (angka atau huruf)
else if (isalnum(c)) {
expectOperand = false;
}
}
return s.empty() && !expectOperand;
}
Algoritma:
Contoh: [4, 5, 2, 10, 8]
| Index | Element | Stack Before | Action | NGE | Stack After |
|---|---|---|---|---|---|
| 4 | 8 | [] | Push | -1 | [8] |
| 3 | 10 | [8] | Pop 8, Push | -1 | [10] |
| 2 | 2 | [10] | Push | 10 | [10, 2] |
| 1 | 5 | [10, 2] | Pop 2, Push | 10 | [10, 5] |
| 0 | 4 | [10, 5] | Push | 5 | [10, 5, 4] |
Hasil NGE: [5, 10, 10, -1, -1]
| Operasi | Current | Back Stack | Forward Stack |
|---|---|---|---|
| Initial | - | [] | [] |
| Visit google | [] | [] | |
| Visit youtube | youtube | [google] | [] |
| Visit facebook | [google, youtube] | [] | |
| Back | youtube | [google] | [facebook] |
| Back | [] | [facebook, youtube] | |
| Forward | youtube | [google] | [facebook] |
| Visit twitter | [google, youtube] | [] |
State Akhir:
void sortStack(stack<int>& input) {
stack<int> tempStack;
while (!input.empty()) {
int temp = input.top();
input.pop();
// Pindahkan elemen dari tempStack yang > temp kembali ke input
while (!tempStack.empty() && tempStack.top() > temp) {
input.push(tempStack.top());
tempStack.pop();
}
tempStack.push(temp);
}
// Pindahkan kembali ke input (sekarang terurut descending)
while (!tempStack.empty()) {
input.push(tempStack.top());
tempStack.pop();
}
}
Kompleksitas: O(n²) worst case
vector<int> calculateSpan(vector<int>& prices) {
int n = prices.size();
vector<int> span(n);
stack<int> s; // Stack menyimpan indeks
for (int i = 0; i < n; i++) {
// Pop semua elemen dengan harga <= harga saat ini
while (!s.empty() && prices[s.top()] <= prices[i]) {
s.pop();
}
// Hitung span
span[i] = s.empty() ? (i + 1) : (i - s.top());
s.push(i);
}
return span;
}
// Untuk: [100, 80, 60, 70, 60, 75, 85]
// Hasil: [1, 1, 1, 2, 1, 4, 6]
Kompleksitas: O(n) - setiap elemen di-push dan di-pop maksimal sekali
Struktur Utama:
class MilitaryCommandSystem {
private:
stack<Command> activeCommands;
stack<Command> cancelledCommands;
vector<string> operationLog;
int nextId;
const int MAX_UNDO_HISTORY = 20;
public:
void issueCommand(string desc, string unit, int priority);
bool cancelLastCommand(bool forceCancel = false);
void reinstateCommand();
void getActiveCommands();
Command getHighPriorityCommand();
void logOperation(string operation);
};
Kompleksitas:
Algoritma Sliding Window Maximum menggunakan Deque:
class RadarSignalAnalyzer {
private:
deque<pair<int, int>> window; // (value, index)
vector<int> signalHistory;
int windowSize;
int currentIndex;
public:
int processSignal(int strength) {
currentIndex++;
// Hapus elemen yang keluar dari window
while (!window.empty() &&
window.front().second <= currentIndex - windowSize) {
window.pop_front();
}
// Hapus elemen yang lebih kecil dari strength baru
while (!window.empty() && window.back().first <= strength) {
window.pop_back();
}
window.push_back({strength, currentIndex});
signalHistory.push_back(strength);
return window.front().first; // Maximum in window
}
};
Analisis untuk data [10, 15, 12, 20, 18, 50, 25, 30, 28, 35], window=3:
| Signal | Window | Max | Anomaly |
|---|---|---|---|
| 10 | [10] | 10 | - |
| 15 | [10,15] | 15 | - |
| 12 | [10,15,12] | 15 | - |
| 20 | [15,12,20] | 20 | - |
| 18 | [12,20,18] | 20 | - |
| 50 | [20,18,50] | 50 | ⚠️ Lonjakan 150% |
| 25 | [18,50,25] | 50 | - |
| 30 | [50,25,30] | 50 | - |
| 28 | [25,30,28] | 30 | ⚠️ Penurunan 44% |
| 35 | [30,28,35] | 35 | - |
Anomali terdeteksi: Index 5 (lonjakan), Index 8 (penurunan setelah puncak)
| Komponen | Poin | Kriteria |
|---|---|---|
| Bagian A | 40 | 2 poin per jawaban benar |
| Bagian B | 160 | Sesuai bobot per soal |
| Bagian C | 100 | 50 poin per studi kasus |
| Total | 300 |
| Rentang | Nilai |
|---|---|
| 255-300 | A |
| 240-254 | A- |
| 225-239 | B+ |
| 210-224 | B |
| 195-209 | B- |
| 180-194 | C+ |
| 165-179 | C |
| 120-164 | D |
| 0-119 | E |
This repository is licensed under the Creative Commons Attribution 4.0 International (CC BY 4.0). Commercial use is permitted, provided attribution is given to the author.
© 2026 Anindito