Mencari nilai terkecil dan terbesar muncul di mana-mana: suhu tertinggi hari ini, produk dengan stok paling sedikit, laporan tertinggi dan terendah sekaligus. Header <algorithm> menyediakan tiga algoritma untuk rentang iterator — std::min_element, std::max_element, dan std::minmax_element — plus std::min dan std::max untuk membandingkan dua nilai (atau initializer list) secara langsung. Semuanya berjalan linier O(n) dan tidak menuntut data terurut. Chapter ini membedakan kapan memakai yang mana dan menyoroti satu detail bagus dari minmax_element yang sering muncul di pertanyaan wawancara.

min_element dan max_element #

Keduanya mengembalikan iterator ke elemen ekstrem pada rentang [first, last), bukan nilainya. Mengembalikan iterator lebih kuat: dari situ kita bisa membaca nilai dengan *, menghitung indeks dengan pengurangan iterator, atau langsung menghapus elemen tersebut. Bila rentang kosong, min_element dan max_element mengembalikan last — jadi seperti biasa, periksa terhadap end() sebelum mendereference.

cpp
#include <algorithm>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> suhu = {28, 31, 24, 35, 19, 31};

    // min_element / max_element: iterator ke elemen ekstrem
    auto terkecil = std::min_element(suhu.begin(), suhu.end());
    auto terbesar = std::max_element(suhu.begin(), suhu.end());
    std::cout << "Terendah : " << *terkecil << " (indeks "
              << (terkecil - suhu.begin()) << ")\n";
    std::cout << "Tertinggi: " << *terbesar << " (indeks "
              << (terbesar - suhu.begin()) << ")\n";

    // minmax_element: dua iterator sekaligus dalam std::pair
    auto [lo, hi] = std::minmax_element(suhu.begin(), suhu.end());
    std::cout << "minmax   : " << *lo << " dan " << *hi << "\n";

    // std::min / std::max untuk membandingkan dua nilai
    std::cout << "min(28, 31)    : " << std::min(28, 31) << "\n";
    std::cout << "max(28, 31)    : " << std::max(28, 31) << "\n";
    std::cout << "min({5, 2, 9}) : " << std::min({5, 2, 9}) << "\n";

    // clamp: jepit nilai ke dalam rentang [lo, hi]
    std::cout << "clamp(37, 19, 31) = " << std::clamp(37, 19, 31) << "\n";
    std::cout << "clamp(15, 19, 31) = " << std::clamp(15, 19, 31) << "\n";
    return 0;
}

Output yang Dihasilkan:

text
Terendah : 19 (indeks 4)
Tertinggi: 35 (indeks 3)
minmax   : 19 dan 35
min(28, 31)    : 28
max(28, 31)    : 31
min({5, 2, 9}) : 2
clamp(37, 19, 31) = 31
clamp(15, 19, 31) = 19

Bedah baris demi baris:

  1. Baris 8-9: min_element mengembalikan iterator ke nilai 19 (indeks 4), max_element ke 35 (indeks 3). Perhatikan 31 muncul dua kali tetapi bukan ekstrem, sehingga tidak terlibat ambiguitas.
  2. Baris 13-14 (auto [lo, hi] = std::minmax_element(...)): satu jalan program mendapatkan kedua ekstrem sekaligus dalam std::pair yang dibongkar lewat structured bindings. Hasilnya sama dengan memanggil dua algoritma di atas, tetapi hanya satu kali jalan data.
  3. Baris 17-19: std::min(28, 31) dan std::max(28, 31) membandingkan dua nilai dan mengembalikan nilai, bukan iterator. Versi initializer list std::min({5, 2, 9}) membandingkan beberapa nilai sekaligus.
  4. Baris 22-23 (std::clamp): bonus dari keluarga yang sama — menjepit nilai ke dalam rentang [lo, hi]. Angka 37 di atas batas 31 ditekan menjadi 31; angka 15 di bawah 19 dinaikkan menjadi 19.

Setelah hasil ekstrem diketahui, indeks dihitung dengan terkecil - suhu.begin(), konvensi yang sudah kita pakai sejak Chapter std::find.

Detail Penting Saat Ada Duplikat #

Bila nilai minimum atau maksimum muncul lebih dari sekali, pilihan algoritma menentukan elemen mana yang dikembalikan. Standar menjamin: min_element mengembalikan kemunculan pertama dari nilai terkecil, max_element mengembalikan kemunculan pertama dari nilai terbesar, sedangkan minmax_element mengembalikan minimum pertama dan maksimum terakhir. Deskripsi “pertama” dan “terakhir” ini bukan detail implementasi — ia diatur standar, sehingga hasilnya identik di semua compiler yang patuh.

Dua catatan pemakaian lainnya. Pertama, untuk tipe dengan perbandingan khusus — misalnya mencari Siswa dengan nilai tertinggi — ketiga algoritma ini menerima comparator sebagai argumen terakhir, sama seperti std::sort. Kedua, std::min dan std::max pada argumen yang saling mempengaruhi (misalnya std::max(x, y) lalu mengubahnya) perlu ditulis hati-hati karena keduanya mengembalikan salinan nilai, bukan referensi ke variabel asal (versi referensi tersedia lewat std::minmax atau penulisan manual).

Kapan Memakai yang Mana #

Pilih min_element/max_element bila hanya satu ekstrem yang dibutuhkan dan program harus jelas maksudnya. Pilih minmax_element bila keduanya dibutuhkan sekaligus — selain sekali jalan, hasilnya juga lebih informatif saat ada duplikat. Pakai std::min/std::max untuk dua nilai atau beberapa literal, misalnya menahan variabel dalam batas tertentu. Dan bila kebutuhanmu berkembang menjadi “jepit nilai ke rentang”, std::clamp sudah tersedia tanpa perlu menulis std::max(lo, std::min(x, hi)) secara manual.

Chapter berikutnya membahas saudara dari keluarga pencacah: std::count dan count_if, yang juga linier O(n) tapi mengembalikan angka, bukan iterator.

Rujukan resmi: std::min_element , std::max_element , dan std::minmax_element .