DP
Kembali ke Tutorial
Computer ScienceLanjutan

Algoritma dan Struktur Data dengan JavaScript

Pelajari fondasi algoritma dan struktur data melalui JavaScript: Big O, array, object map, stack, queue, searching, sorting, recursion, dan latihan problem solving.

8 menit baca20 Mei 2025oleh Reza Maulana

Algoritma dan Struktur Data dengan JavaScript

Algoritma adalah langkah sistematis untuk menyelesaikan masalah. Struktur data adalah cara menyimpan dan mengorganisasi data agar operasi tertentu dapat dilakukan dengan efisien. Keduanya menjadi fondasi penting dalam pemrograman, baik untuk membangun aplikasi sehari-hari maupun menghadapi technical interview.

Tutorial ini memakai JavaScript karena sintaksnya relatif mudah diikuti. Namun, konsep yang dibahas berlaku di banyak bahasa pemrograman.

Tujuan Belajar

Setelah membaca tutorial ini, kamu diharapkan mampu:

  • Menjelaskan makna algoritma dan struktur data.
  • Membaca kompleksitas waktu dengan notasi Big O sederhana.
  • Memilih struktur data dasar seperti array, object map, stack, dan queue.
  • Menulis algoritma searching dan sorting sederhana.
  • Memahami recursion dan kapan perlu berhati-hati.
  • Melatih cara memecah masalah sebelum menulis kode.

Cara Berpikir Sebelum Coding

Sebelum menulis kode, biasakan menjawab pertanyaan berikut:

  • Apa input-nya?
  • Apa output yang diharapkan?
  • Apakah ada batasan ukuran data?
  • Apakah data boleh diubah langsung atau harus dipertahankan?
  • Kasus tepi apa yang mungkin muncul?

Contoh masalah: "Cari angka terbesar dalam array".

js
function findMax(numbers) {
  if (numbers.length === 0) return null;

  let max = numbers[0];

  for (const number of numbers) {
    if (number > max) {
      max = number;
    }
  }

  return max;
}

console.log(findMax([4, 2, 9, 1])); // 9
console.log(findMax([])); // null

Kasus array kosong dipikirkan sejak awal, bukan setelah bug muncul.

Big O Singkat

Big O membantu kita membahas bagaimana waktu atau memori bertambah saat ukuran input bertambah.

NotasiContohGambaran
O(1)Mengambil item pertama arrayKonstan, tidak bergantung panjang input.
O(n)Loop seluruh arrayBertambah seiring jumlah data.
O(n log n)Sorting efisienUmum pada algoritma sorting praktis.
O(n^2)Nested loop seluruh pasanganCepat berat saat data besar.

Big O bukan alat untuk menebak waktu pasti dalam milidetik. Big O dipakai untuk membaca pola pertumbuhan.

Array

Array cocok untuk daftar berurutan. Mengakses item berdasarkan index biasanya cepat, tetapi mencari data tertentu tetap perlu menelusuri item jika belum ada index bantu.

js
const lessons = ["HTML", "CSS", "JavaScript"];

console.log(lessons[0]); // HTML
lessons.push("React");

for (const lesson of lessons) {
  console.log(lesson);
}

Operasi umum:

OperasiKompleksitas umumCatatan
Akses by indexO(1)Jika index diketahui.
Cari by valueO(n)Perlu scan item.
Tambah di akhirO(1) rata-ratapush biasanya efisien.
Hapus di tengahO(n)Item setelahnya perlu bergeser.

Object Map

Object atau Map cocok ketika kita perlu mencari data berdasarkan key.

js
const usersById = {
  u1: { id: "u1", name: "Ayu" },
  u2: { id: "u2", name: "Bima" },
};

console.log(usersById.u2.name);

Dengan Map:

js
const scores = new Map();

scores.set("ayu", 90);
scores.set("bima", 82);

console.log(scores.get("ayu"));
console.log(scores.has("citra"));

Map berguna ketika key bukan hanya string biasa atau ketika kita ingin API yang eksplisit seperti set, get, has, dan delete.

Stack

Stack memakai prinsip LIFO: last in, first out. Data terakhir yang masuk akan keluar lebih dulu. Contoh penggunaan: undo, call stack, dan parsing tanda kurung.

js
class Stack {
  constructor() {
    this.items = [];
  }

  push(item) {
    this.items.push(item);
  }

  pop() {
    return this.items.pop();
  }

  peek() {
    return this.items[this.items.length - 1];
  }

  isEmpty() {
    return this.items.length === 0;
  }
}

Contoh validasi tanda kurung:

js
function isBalanced(input) {
  const stack = [];
  const pairs = { ")": "(", "]": "[", "}": "{" };

  for (const char of input) {
    if (char === "(" || char === "[" || char === "{") {
      stack.push(char);
    }

    if (char === ")" || char === "]" || char === "}") {
      const last = stack.pop();
      if (last !== pairs[char]) return false;
    }
  }

  return stack.length === 0;
}

console.log(isBalanced("{[()]}")); // true
console.log(isBalanced("{[(])}")); // false

Queue

Queue memakai prinsip FIFO: first in, first out. Data pertama yang masuk akan keluar lebih dulu. Contoh penggunaan: antrean pekerjaan, BFS, dan event processing.

js
class Queue {
  constructor() {
    this.items = [];
  }

  enqueue(item) {
    this.items.push(item);
  }

  dequeue() {
    return this.items.shift();
  }

  isEmpty() {
    return this.items.length === 0;
  }
}

Catatan: shift() pada array JavaScript dapat menjadi O(n) karena item perlu bergeser. Untuk antrean besar, gunakan implementasi dengan pointer index.

js
class FastQueue {
  constructor() {
    this.items = [];
    this.head = 0;
  }

  enqueue(item) {
    this.items.push(item);
  }

  dequeue() {
    if (this.head >= this.items.length) return undefined;
    const item = this.items[this.head];
    this.head += 1;
    return item;
  }
}

Linear search menelusuri data satu per satu.

js
function linearSearch(items, target) {
  for (let index = 0; index < items.length; index += 1) {
    if (items[index] === target) return index;
  }

  return -1;
}

Binary search lebih cepat, tetapi syaratnya data harus sudah terurut.

js
function binarySearch(numbers, target) {
  let left = 0;
  let right = numbers.length - 1;

  while (left <= right) {
    const middle = Math.floor((left + right) / 2);

    if (numbers[middle] === target) return middle;
    if (numbers[middle] < target) {
      left = middle + 1;
    } else {
      right = middle - 1;
    }
  }

  return -1;
}

console.log(binarySearch([1, 3, 5, 8, 13], 8)); // 3

Binary search biasanya O(log n), jauh lebih baik dari O(n) untuk data besar yang sudah terurut.

Sorting Sederhana

JavaScript memiliki sort, tetapi memahami sorting dasar tetap berguna. Contoh bubble sort:

js
function bubbleSort(numbers) {
  const result = [...numbers];

  for (let i = 0; i < result.length; i += 1) {
    for (let j = 0; j < result.length - i - 1; j += 1) {
      if (result[j] > result[j + 1]) {
        const temp = result[j];
        result[j] = result[j + 1];
        result[j + 1] = temp;
      }
    }
  }

  return result;
}

console.log(bubbleSort([5, 2, 9, 1]));

Bubble sort mudah dipahami tetapi tidak efisien untuk data besar karena O(n^2). Untuk aplikasi nyata, gunakan sorting bawaan atau algoritma yang lebih efisien sesuai kebutuhan.

Recursion

Recursion terjadi ketika function memanggil dirinya sendiri. Setiap recursion harus memiliki base case agar berhenti.

js
function factorial(n) {
  if (n <= 1) return 1;
  return n * factorial(n - 1);
}

console.log(factorial(5)); // 120

Recursion cocok untuk struktur yang secara alami bercabang, seperti tree. Namun, recursion yang terlalu dalam dapat menyebabkan call stack overflow. Untuk data sangat besar, pertimbangkan loop atau struktur iteratif.

Problem Solving: Two Sum

Masalah: diberikan array angka dan target, cari dua angka yang jika dijumlahkan menghasilkan target.

Solusi O(n^2):

js
function twoSumSlow(numbers, target) {
  for (let i = 0; i < numbers.length; i += 1) {
    for (let j = i + 1; j < numbers.length; j += 1) {
      if (numbers[i] + numbers[j] === target) {
        return [i, j];
      }
    }
  }

  return null;
}

Solusi O(n) dengan Map:

js
function twoSum(numbers, target) {
  const seen = new Map();

  for (let index = 0; index < numbers.length; index += 1) {
    const number = numbers[index];
    const complement = target - number;

    if (seen.has(complement)) {
      return [seen.get(complement), index];
    }

    seen.set(number, index);
  }

  return null;
}

console.log(twoSum([2, 7, 11, 15], 9)); // [0, 1]

Struktur data yang tepat dapat mengubah solusi lambat menjadi jauh lebih efisien.

Kesalahan Umum

KesalahanDampakPerbaikan
Langsung coding tanpa memahami input-outputSolusi mudah salah arahTulis contoh kasus dulu.
Mengabaikan kasus kosongError pada data edge caseUji array kosong, null, dan nilai tidak ditemukan.
Memakai nested loop untuk semua halLambat pada data besarCari struktur data bantu seperti Map atau Set.
Menghafal algoritma tanpa memahami trade-offSulit menyesuaikan soal baruPahami alasan di balik langkah.

Coba Sendiri

Kerjakan latihan berikut:

  • Buat function countWords(text) yang menghitung frekuensi kata menggunakan Map.
  • Buat function isPalindrome(text) yang mengabaikan spasi dan kapitalisasi.
  • Buat queue dengan pointer index, bukan shift.
  • Ubah twoSum agar mengembalikan pasangan nilai, bukan index.
  • Bandingkan jumlah operasi pada twoSumSlow dan twoSum untuk array 1000 item.

Contoh awal:

js
function countWords(text) {
  const counts = new Map();
  const words = text.toLowerCase().split(/\s+/);

  for (const word of words) {
    if (!word) continue;
    counts.set(word, (counts.get(word) ?? 0) + 1);
  }

  return counts;
}

console.log([...countWords("aku belajar aku bisa")]);

Cek Pemahaman

Kuis

Apa makna umum O(n) dalam analisis algoritma?

Pilih satu jawaban.

Kuis

Mengapa Map membantu solusi Two Sum menjadi lebih efisien?

Pilih satu jawaban.

Ringkasan

Algoritma dan struktur data membantu kita menulis solusi yang bukan hanya benar, tetapi juga masuk akal untuk ukuran data tertentu. Mulailah dari input-output, pahami kompleksitas dasar, lalu pilih struktur data sesuai operasi yang paling sering dilakukan. JavaScript sudah menyediakan array, object, Map, dan Set yang cukup untuk banyak kebutuhan awal, asalkan kita memahami trade-off-nya.

#algoritma#data-structure#javascript#problem-solving#computer-science
Apakah konten ini membantu?

Feedback kamu membantu kami memperbaiki materi berikutnya.

Diskusi (0)

Silakan masuk terlebih dahulu untuk ikut berdiskusi

Login Sekarang