Pertemuan 01
Universitas Pertahanan RI
Setelah pertemuan ini, mahasiswa mampu:
Struktur Data adalah cara mengorganisasikan, menyimpan, dan mengelola data dalam memori komputer sehingga dapat diakses dan dimodifikasi secara efisien.
🗂️ Organisasi
Bagaimana data disusun dalam memori
🔍 Akses
Bagaimana data dapat diambil atau diubah
⚙️ Operasi
Apa saja yang dapat dilakukan terhadap data
Pemilihan struktur data yang tepat sangat mempengaruhi efisiensi program.
Sistem yang mengelola ribuan data posisi unit militer secara real-time:
❌ Tanpa Struktur Data Tepat:
✅ Dengan Struktur Data Tepat:
Gambar 1.4: Klasifikasi struktur data — Linear vs Non-Linear
| Jenis | Karakteristik | Contoh Penggunaan |
|---|---|---|
| Linear | Elemen tersusun berurutan, satu demi satu | Antrian pesan, history command |
| Non-Linear | Elemen dapat terhubung ke banyak elemen lain | Struktur organisasi, jaringan komunikasi |
Abstract Data Type (ADT) adalah model matematis untuk tipe data yang didefinisikan oleh perilakunya (semantik), bukan implementasinya.
| Aspek | ADT | Struktur Data Konkret |
|---|---|---|
| Level | Abstrak/Konseptual | Implementasi |
| Fokus | APA yang dilakukan | BAGAIMANA melakukannya |
| Detail | Tersembunyi | Terlihat |
| Contoh | Stack (konsep LIFO) | Array-based Stack, Linked Stack |
📦 Data
Nilai-nilai yang dapat disimpan
⚙️ Operasi
Fungsi-fungsi yang dapat dilakukan pada data
📜 Aturan
Perilaku yang dijamin dari operasi
ADT Stack:
Data:
- Kumpulan elemen dengan tipe T
Operasi:
- push(item): Menambah item ke puncak stack
- pop(): Menghapus dan mengembalikan item dari puncak
- peek()/top(): Melihat item di puncak tanpa menghapus
- isEmpty(): Mengecek apakah stack kosong
Aturan:
- LIFO (Last In First Out)
- push lalu pop mengembalikan item yang sama
- pop pada stack kosong menghasilkan error
Sebutkan 3 operasi dasar yang harus dimiliki ADT Queue!
enqueue(item) — Menambah elemen ke belakangdequeue() — Menghapus elemen dari depanfront()/peek() — Melihat elemen depan tanpa menghapusPointer adalah variabel yang menyimpan alamat memori dari variabel lain.
Pointer adalah salah satu fitur paling powerful sekaligus berbahaya dalam C++.
int main() {
int nilai = 42; // Variabel biasa
int* ptr = &nilai; // Pointer menyimpan alamat 'nilai'
cout << "Nilai variabel: " << nilai << endl; // 42
cout << "Alamat variabel: " << &nilai << endl; // 0x7ffd...
cout << "Nilai pointer: " << ptr << endl; // 0x7ffd...
cout << "Nilai yang ditunjuk: " << *ptr << endl; // 42
return 0;
}
| Operator | Nama | Fungsi | Contoh |
|---|---|---|---|
& |
Address-of | Mengambil alamat variabel | &x → alamat x |
* |
Dereference | Mengakses nilai di alamat | *ptr → nilai di ptr |
-> |
Arrow | Akses member via pointer | ptr->member |
Gambar 1.1: Ilustrasi pointer arithmetic pada array integer
int arr[5] = {10, 20, 30, 40, 50};
int* ptr = arr;
ptr++; // Pindah ke elemen berikutnya (+sizeof(int))
ptr += 2; // Pindah 2 elemen ke depan
Apa output dari kode berikut?
int x = 10;
int* p = &x;
*p = 20;
cout << x << endl;
Output: 20
Karena p menunjuk ke x, mengubah *p sama dengan mengubah x.
void tukar(int* a, int* b) {
int temp = *a; // Simpan nilai di alamat a
*a = *b; // Copy nilai di alamat b ke alamat a
*b = temp; // Copy temp ke alamat b
}
int main() {
int x = 5, y = 10;
tukar(&x, &y); // Kirim alamat x dan y
// Hasil: x = 10, y = 5
}
Referensi adalah alias (nama lain) untuk variabel yang sudah ada. Setelah diinisialisasi, referensi selalu merujuk ke variabel yang sama.
int nilai = 42;
int& ref = nilai; // ref adalah alias untuk nilai
ref = 100; // Sama dengan nilai = 100
cout << nilai; // Output: 100
| Aspek | Pointer | Referensi |
|---|---|---|
| Inisialisasi | Bisa tanpa nilai awal | Harus langsung diinisialisasi |
| Null | Bisa null | Tidak bisa null |
| Reassignment | Bisa menunjuk variabel lain | Selalu merujuk variabel yang sama |
| Syntax | Perlu * dan & |
Langsung seperti variabel biasa |
// Pass by value - tidak mengubah variabel asli
void tambahSatu_nilai(int x) {
x = x + 1;
}
// Pass by reference - mengubah variabel asli
void tambahSatu_ref(int& x) {
x = x + 1;
}
int main() {
int a = 5, b = 5;
tambahSatu_nilai(a); // a tetap 5
tambahSatu_ref(b); // b jadi 6
}
Gambar 1.2: Perbandingan Stack dan Heap Memory
| Segmen | Karakteristik | Contoh |
|---|---|---|
| Stack | Otomatis dialokasi/dealokasi, ukuran terbatas, cepat | Variabel lokal, parameter fungsi |
| Heap | Manual dialokasi/dealokasi, ukuran besar, lebih lambat | Data dengan new, array dinamis |
new dan delete
int main() {
// Alokasi single variable
int* ptr = new int; // Alokasi memori untuk satu integer
*ptr = 42;
delete ptr; // Dealokasi memori
// Alokasi dengan inisialisasi
int* ptr2 = new int(100);
delete ptr2;
return 0;
}
int main() {
int ukuran;
cin >> ukuran;
int* arr = new int[ukuran]; // Alokasi array dinamis
// Mengisi dan menggunakan array
for (int i = 0; i < ukuran; i++) {
arr[i] = i * 10;
}
// PENTING: gunakan delete[] untuk array!
delete[] arr;
return 0;
}
⚠️ Untuk array dengan new[], selalu gunakan delete[]!
delete vs delete[]| Operator | Penggunaan | Dealokasi |
|---|---|---|
delete ptr |
Single object (new) |
Satu objek |
delete[] ptr |
Array (new[]) |
Seluruh array |
// Single object
int* single = new int(42);
delete single; // ✅ BENAR
// Array
int* arr = new int[10];
delete[] arr; // ✅ BENAR
Gambar 1.3: Ilustrasi Memory Leak dan Dangling Pointer
Memory Leak terjadi ketika memori yang dialokasikan di heap tidak pernah didealokasi.
void fungsiMasalah() {
int* data = new int[1000];
// ... melakukan operasi ...
// ❌ MASALAH: fungsi berakhir tanpa delete[]
// Memori 1000 integer hilang!
}
int main() {
for (int i = 0; i < 100000; i++) {
fungsiMasalah(); // Setiap panggilan = memory leak
}
// Program mungkin kehabisan memori!
}
delete atau delete[]Dangling Pointer adalah pointer yang menunjuk ke lokasi memori yang sudah tidak valid.
int* buatDangling() {
int lokal = 42;
return &lokal; // ❌ BAHAYA! mengembalikan alamat variabel lokal
} // lokal dihancurkan saat fungsi berakhir
int main() {
int* ptr = new int(100);
delete ptr; // Memori didealokasi
cout << *ptr; // ❌ UNDEFINED BEHAVIOR - dangling pointer!
}
int main() {
int* ptr = nullptr; // 1. Selalu inisialisasi pointer
if (ptr != nullptr) { // 2. Periksa sebelum menggunakan
cout << *ptr << endl;
}
ptr = new int(42);
delete ptr;
ptr = nullptr; // 3. Set ke nullptr setelah delete
return 0;
}
Raw pointer memiliki beberapa masalah:
| Smart Pointer | Kepemilikan | Penggunaan |
|---|---|---|
unique_ptr |
Exclusive (satu pemilik) | Default choice, tidak bisa di-copy |
shared_ptr |
Shared (banyak pemilik) | Ketika perlu berbagi kepemilikan |
weak_ptr |
Non-owning reference | Menghindari circular reference |
unique_ptr
#include <memory>
int main() {
unique_ptr<int> ptr1(new int(42));
cout << "Nilai: " << *ptr1 << endl;
// unique_ptr tidak bisa di-copy
// unique_ptr<int> ptr2 = ptr1; // ❌ ERROR!
// Tapi bisa di-move
unique_ptr<int> ptr2 = move(ptr1);
// ptr1 sekarang nullptr
// Otomatis dealokasi saat keluar scope!
return 0;
}
✅ Keuntungan:
// Smart pointer - aman
void fungsiSmart() {
unique_ptr<int> ptr(new int(42));
// Jika exception, ptr tetap
// dealokasi otomatis!
riskyOperation();
// Tidak perlu delete
}
int arrStatis[100]; // Selalu menggunakan memori untuk 100 int
// Tidak bisa diperbesar
Array dinamis dapat tumbuh sesuai kebutuhan dengan strategi:
| Strategi | Deskripsi | Kelebihan | Kekurangan |
|---|---|---|---|
| Tambah tetap (+k) | newCap = oldCap + k |
Hemat memori | Banyak realokasi |
| Lipat dua (×2) | newCap = oldCap * 2 |
Realokasi jarang | Boros memori |
Strategi lipat dua memberikan amortized O(1) untuk operasi tambah.
Gambar 1.5: Ilustrasi proses penghapusan elemen pada array dinamis
Kompleksitas waktu: O(n) karena perlu menggeser elemen
class ArrayDinamis {
private:
int* data;
int ukuran; // Jumlah elemen saat ini
int kapasitas; // Total kapasitas array
public:
ArrayDinamis(int kapasitasAwal = 10) {
kapasitas = kapasitasAwal;
ukuran = 0;
data = new int[kapasitas];
}
~ArrayDinamis() {
delete[] data; // Destructor - dealokasi
}
void tambah(int nilai); // Tambah elemen
int ambil(int index); // Akses elemen
void hapus(int index); // Hapus elemen
};
| Konsep | Deskripsi |
|---|---|
| Struktur Data | Cara mengorganisasi data dalam memori (Linear vs Non-Linear) |
| ADT | Model matematis yang mendefinisikan operasi tanpa detail implementasi |
| Pointer | Variabel yang menyimpan alamat memori (int* ptr = &var;) |
| Referensi | Alias untuk variabel lain (int& ref = var;) |
| new / delete | Alokasi dan dealokasi memori di heap |
| Memory Leak | Memori yang dialokasi tidak pernah didealokasi |
| Dangling Pointer | Pointer yang menunjuk ke memori tidak valid |
| Smart Pointer | Pointer yang mengelola memori otomatis (unique_ptr, shared_ptr) |
Silakan bertanya atau diskusi
Referensi: Cormen Ch.10 | Weiss Ch.1 | Hubbard Ch.1-2
Struktur Data dan Algoritma
Pertemuan 01
© 2026 - CC BY 4.0