Stack<T> adalah sebuah tumpukan: kamu menaruh item di atas dengan Push dan mengambilnya dari atas dengan Pop, jadi item yang terakhir masuk adalah yang pertama keluar (LIFO). Hanya bagian atas yang bisa dijangkau, dan setiap operasi padanya berjalan dalam waktu konstan.
Push, Pop, dan Peek
Output:
On top: green
Count: 3
Took green
On top: red
Took red
Took blue
Count: 0
green dimasukkan paling akhir, jadi ia keluar paling dulu. Peek mengembalikan item teratas tanpa mengubah stack, dan dengan cara itulah kamu melihat apa yang akan diberikan Pop sebelum memutuskan untuk mengambilnya.
Exception saat stack kosong dan TryPop
Melakukan pop atau peek pada stack kosong melempar InvalidOperationException. Ini paling sering muncul di parser dan algoritma yang menerima input dengan item penutup lebih banyak daripada item pembuka.
Output:
Caught InvalidOperationException
True 10
False 0
TryPop dan TryPeek (.NET Core 2.0 dan sesudahnya) mengembalikan false pada stack kosong dan mengisi variabel out dengan nilai default, di sini 0. Di .NET Framework, periksa Count > 0 lebih dulu.
Urutan iterasi: yang teratas lebih dulu
Melakukan enumerasi pada stack tidak menghapus apa pun, dan urutannya dari atas ke bawah, sesuai urutan item yang akan dikembalikan Pop:
Output:
checkout products home
checkout > products > home
True
home
checkout
Salinan yang terbalik sering menjebak: constructor-nya menerima IEnumerable<T> apa pun dan melakukan push pada itemnya secara berurutan, sedangkan stack melakukan enumerasi dari atas, jadi item teratas yang lama berakhir di dasar salinannya. Membalik urutannya lebih dulu (Reverse() dari LINQ mengembalikan item mulai dari dasar) menghasilkan salinan dengan item teratas yang sama.
Melakukan push pada daftar item ke stack baru juga membalik urutannya, dan ini cara cepat untuk membalik sebuah urutan: new Stack<char>("hello") mengembalikan o, l, l, e, h saat diambil dengan pop.
Contoh: riwayat undo
Editor menyimpan setiap perubahan di sebuah stack. Undo melakukan pop pada perubahan terbaru lalu membatalkannya; redo menyimpan stack kedua berisi perubahan yang sudah dibatalkan.
Output:
Hello, world!
Hello, world
Hello
Hello, world
Menyimpan seluruh snapshot adalah versi yang paling sederhana. Editor sungguhan melakukan push pada object command kecil (apa yang disisipkan, dan di mana), masing-masing dengan method untuk membalikkan dirinya, tetapi kedua stack-nya bekerja dengan cara yang sama.
Contoh: kurung yang seimbang
Memeriksa bahwa (, [, dan { ditutup dengan urutan yang benar adalah latihan stack yang standar, dan logika yang sama ada di dalam setiap compiler dan parser JSON.
Output:
"f(a[i], {x: 1})" -> True
"(]" -> False
"((a)" -> False
"a)b(" -> False
"" -> True
Ketiga pengecekan kegagalan itu sesuai dengan tiga cara kurung bisa salah: kurung tutup tanpa ada kurung yang terbuka (a)b(, ditangkap oleh Count == 0 alih-alih exception dari Pop), kurung tutup dengan jenis yang salah ((]), dan kurung buka yang tidak pernah ditutup (((a), ditangkap oleh pengecekan terakhir).
Pemakaian lainnya
- Depth first search. Ganti queue di breadth first search dengan stack, maka penelusurannya masuk ke dalam lebih dulu sebelum melebar. Stack eksplisit juga bisa menggantikan rekursi saat input cukup dalam sehingga berisiko memicu
StackOverflowException, yang tidak bisa ditangkap. - Mengevaluasi ekspresi. Notasi postfix (
3 4 + 2 *) dievaluasi dengan melakukan push pada angka dan pop dua angka untuk setiap operator. - Backtracking. Riwayat navigasi, penyelesaian labirin, dan state parser melakukan push pada sebuah posisi lalu kembali ke posisi itu dengan pop saat menemui jalan buntu.
Lihat Queue untuk pasangannya yang first in, first out.
Stack vs Queue vs List
Stack<T> | Queue<T> | List<T> | |
|---|---|---|---|
| Urutan keluar | Terbaru lebih dulu | Terlama lebih dulu | Bebas, lewat indeks |
| Tambah | Push | Enqueue | Add, Insert |
| Hapus | Pop (atas) | Dequeue (depan) | Remove, RemoveAt |
| Lihat | Peek | Peek | list[i] |
| Varian aman | TryPop, TryPeek | TryDequeue, TryPeek | tidak diperlukan |
Untuk banyak thread, ConcurrentStack<T> di System.Collections.Concurrent menyediakan Push, TryPop, dan TryPeek tanpa lock.
Kesalahan umum
- Melakukan pop tanpa memeriksa. Stack kosong melempar
InvalidOperationException; periksaCountatau pakaiTryPop. - Mengira
foreachdimulai dari item yang pertama dimasukkan. Urutannya dimulai dari atas. - Menyalin dengan
new Stack<T>(stack). Salinannya terbalik. - Melakukan push di dalam
foreachpada stack yang sama. Ini melempar exception; pakai perulanganwhile (stack.Count > 0).
Pertanyaan yang sering diajukan
Apa itu Stack di C#?
Stack<T> di System.Collections.Generic adalah collection last in, first out (LIFO). Push menaruh item di atas, Pop menghapus dan mengembalikan item teratas, dan Peek mengembalikan item teratas tanpa menghapusnya. Ketiganya berjalan dalam waktu konstan.
Apa yang terjadi jika Pop dipanggil pada stack kosong di C#?
Pop dan Peek melempar InvalidOperationException saat stack kosong. Periksa stack.Count > 0 lebih dulu, atau pakai TryPop(out var item) dan TryPeek(out var item), yang mengembalikan false alih-alih melempar exception (.NET Core 2.0 dan sesudahnya).
Dalam urutan apa foreach menelusuri sebuah Stack?
Dari atas ke bawah: item yang terakhir dimasukkan muncul pertama, sama dengan urutan yang akan dikembalikan Pop. ToArray() memakai urutan yang sama. Akibatnya, new Stack<T>(otherStack) menghasilkan salinan yang terbalik, karena constructor-nya melakukan push pada item sesuai urutan enumerasinya.
Apa perbedaan Stack dan Queue di C#?
Stack<T> mengembalikan item terbaru lebih dulu (last in, first out), sedangkan Queue<T> mengembalikan item terlama lebih dulu (first in, first out). Pakai stack untuk riwayat undo, struktur bersarang, dan depth first search; pakai queue untuk memproses pekerjaan sesuai urutan kedatangan dan breadth first search.
Bagaimana cara memeriksa kurung yang seimbang di C#?
Telusuri string sekali saja. Lakukan push untuk setiap kurung buka ke Stack<char>. Untuk setiap kurung tutup, stack tidak boleh kosong dan item teratasnya harus kurung buka yang cocok, lalu kamu melakukan pop pada item itu. String-nya seimbang jika penelusuran selesai dengan stack kosong.