Pertanyaan serupa diajukan sebelumnya di sana , tetapi pertanyaan di sini adalah kebalikannya, menggunakan dua antrian sebagai tumpukan. Pertanyaan...
Mengingat dua antrian dengan operasi standar ( enqueue
, dequeue
, isempty
, size
), menerapkan stack dengan operasi standar ( pop
, push
, isempty
, size
).
Seharusnya ada dua versi solusinya.
- Versi A : Tumpukan harus efisien saat mendorong item; dan
- Versi B : Tumpukan harus efisien saat memunculkan item.
Saya tertarik pada algoritma lebih dari implementasi bahasa tertentu. Namun, saya menyambut solusi yang dinyatakan dalam bahasa yang saya kenal (Jawa,c #,ular sanca,vb,javascript,php).
algorithm
data-structures
stack
TechTravelThink
sumber
sumber
Pop
berfungsi dalam $ O (1) $ danPush
bekerja dalam $ O (\ sqrt {n}) $ waktu diamortisasi.Jawaban:
Versi A (dorongan efisien):
Versi B (pop efisien):
sumber
Cara termudah (dan mungkin satu-satunya) untuk melakukan ini adalah dengan mendorong elemen baru ke dalam antrian kosong, dan kemudian mengeluarkan yang lain dan enqeuing ke antrian yang sebelumnya kosong. Dengan cara ini yang terbaru selalu ada di depan antrian. Ini akan menjadi versi B, untuk versi A Anda hanya membalikkan proses dengan membagi elemen ke dalam antrian kedua kecuali yang terakhir.
Langkah 0:
Langkah 1:
Langkah 2:
Langkah 3:
sumber
Kita dapat melakukan ini dengan satu antrian:
Dorong:
n
jumlah elemen dalam antrian, maka hapus dan masukkan elemenn-1
kali.pop:
.
Implementasi sampel:
sumber
sumber
Bisakah kita menggunakan satu antrian untuk mengimplementasikan stack? Saya dapat menggunakan dua antrian, tetapi mempertimbangkan satu antrian akan lebih efisien. Ini kodenya:
sumber
sumber
Inilah jawaban saya - di mana 'pop' tidak efisien. Tampaknya semua algoritme yang langsung muncul di benak Anda memiliki kompleksitas N, di mana N adalah ukuran daftar: apakah Anda memilih untuk bekerja pada 'pop' atau bekerja pada 'push'
Algoritma tempat daftar diperdagangkan kembali dan keempat mungkin lebih baik, karena perhitungan ukuran tidak diperlukan, meskipun Anda masih perlu mengulang dan membandingkan dengan yang kosong.
Anda dapat membuktikan algoritma ini tidak dapat ditulis lebih cepat dari N dengan mencatat bahwa informasi tentang elemen terakhir dalam antrian hanya tersedia dengan mengetahui ukuran antrian, dan bahwa Anda harus memusnahkan data untuk sampai ke elemen itu, maka antrian ke-2 .
Satu-satunya cara untuk mempercepat ini adalah dengan tidak menggunakan antrian sejak awal.
sumber
Berikut adalah solusi saya yang berfungsi untuk O (1) dalam kasus rata-rata. Ada dua antrian:
in
danout
. Lihat pseudocode di bawah:sumber
Seperti yang telah disebutkan, bukankah satu antrian akan berhasil? Ini mungkin kurang praktis tetapi sedikit lebih licin.
sumber
Berikut adalah beberapa kode pseudo sederhana, push adalah O (n), pop / mengintip adalah O (1):
sumber
Biarkan S1 dan S2 menjadi dua tumpukan untuk digunakan dalam implementasi antrian.
Kami memastikan bahwa satu antrian kosong selalu.
Operasi push: Antrian mana pun yang tidak kosong, masukkan elemen di dalamnya.
Push (struct Stack *S, int data) { if(isEmptyQueue(S->Q1) EnQueue(S->Q2, data); else EnQueue(S->Q1, data); }
Kompleksitas Waktu: O (1)
Operasi Pop: Transfer elemen n-1 ke antrian lain dan hapus yang terakhir dari antrian untuk melakukan operasi pop.
`
Kompleksitas Waktu: Menjalankan Waktu operasi pop adalah O (n) karena setiap kali pop dipanggil, kami mentransfer semua elemen dari satu antrian ke oter.
sumber
sumber
sumber
Inilah satu solusi lagi:
untuk PUSH: -Tambahkan elemen pertama dalam antrian 1. -Ketika menambahkan elemen kedua dan seterusnya, Enqueue elemen dalam antrian 2 terlebih dahulu dan kemudian salin semua elemen dari antrian 1 ke antrian2. -Untuk POP, cukup dekor elemen dari antrian dari Anda memasukkan elemen terakhir.
Begitu,
}}
Ada satu masalah, saya tidak bisa mencari tahu, bagaimana cara mengganti nama antriannya ???
sumber
sumber
Kode Python Menggunakan Hanya Satu Antrian
sumber
di sini adalah kode kerja lengkap dalam c #:
Telah diimplementasikan dengan Antrian Tunggal,
Dorong:
pop:
sumber
Berikut adalah solusi yang sangat sederhana yang menggunakan satu Antrian dan memberikan fungsionalitas seperti Stack.
Jadi di kelas di atas bernama "CustomStack" yang saya lakukan adalah hanya memeriksa antrian untuk kosong, jika kosong kemudian masukkan satu dan sejak saat itu di bangsal masukkan dan kemudian hapus masukkan. Dengan logika ini pertama akan menjadi yang terakhir. Contoh: Dalam antrian saya memasukkan 1 dan sekarang mencoba memasukkan 2. Kedua kalinya hapus 1 dan masukkan lagi sehingga menjadi urutan terbalik.
Terima kasih.
sumber
Di bawah ini adalah solusi Java yang sangat sederhana yang mendukung operasi push secara efisien.
Algoritma -
Nyatakan dua Antrian q1 dan q2.
Operasi push - Elemen enqueue untuk mengantri q1.
Operasi sembulan - Pastikan antrian q2 tidak kosong. Jika kosong, maka dequeue semua elemen dari q1 kecuali elemen terakhir dan enqueue ke q2 satu per satu. Dequeue elemen terakhir dari q1 dan simpan sebagai elemen yang muncul. Tukar antrian q1 dan q2. Kembalikan elemen muncul yang tersimpan.
Mengintip operasi - Pastikan antrian q2 tidak kosong. Jika kosong, maka dequeue semua elemen dari q1 kecuali elemen terakhir dan enqueue ke q2 satu per satu. Dequeue elemen terakhir dari q1 dan simpan sebagai elemen yang diintip. Enqueue kembali ke antrian q2 dan menukar antrian q1 dan q2. Kembalikan elemen mengintip yang tersimpan.
Di bawah ini adalah kode untuk algoritma di atas -
sumber
Inilah solusi saya ..
Concept_Behind ::
push(struct Stack* S,int data)
:: Fungsi ini memberikan elemen pertama pada Q1 dan sisanya pada Q2pop(struct Stack* S)
:: jika Q2 tidak mengosongkan transfer semua elem ke Q1 dan mengembalikan elem terakhir di Q2 yang lain (yang berarti Q2 kosong) mentransfer semua elem ke Q2 dan mengembalikan elem terakhir di Q1Efficiency_Behind ::
push(struct Stack*S,int data)
:: O (1) // sejak enqueue tunggal per datapop(struct Stack* S)
:: O (n) // karena transfer data n-1 terburuk per pop.sumber
sumber
sumber