Sabit Zaman ve İtfa Edilen Sabit Zaman etkili bir şekilde eşdeğer kabul edilir mi?


16

Sabit Zaman (O (1)) ekler ve rasgele kaldırma sağlayan bir RandomQueue yazmak gerekiyor.

İlk düşüncem, dizilerin bir dizin aracılığıyla sürekli erişime sahip olması nedeniyle bir çeşit Array (ArrayList seçtim) ile destek olmaktı.

Yine de belgelere baktığımda, ArrayLists'in eklemelerinin İtfa Edilmiş Sabit Zaman olarak kabul edildiğini fark ettim, çünkü bir ekleme O (n) olan temel dizinin yeniden tahsis edilmesini gerektirebilir.

İtfa Edilen Sabit Zaman ve Sabit Zaman etkili bir şekilde aynı mıdır, yoksa her ekleme için tam bir yeniden tahsis gerektirmeyen bir yapıya bakmam gerekir mi?

Bunu soruyorum çünkü dizi tabanlı yapılar bir kenara (bildiğim kadarıyla her zaman Amortize Sabit Zaman eklemeleri olacak), gereksinimleri karşılayacak bir şey düşünemiyorum:

  • Ağaç tabanlı herhangi bir şey en iyi O (log n) erişimine sahip olacaktır
  • Bağlantılı bir liste potansiyel olarak O (1) ilavesine sahip olabilir (kuyruğa bir referans tutulursa), ancak rastgele bir kaldırma en iyi O (n) olmalıdır.

İşte tam soru; bazı önemli detayların üzerine bir sır attığımda:

Bir RandomQueue tasarlayın ve uygulayın. Bu, remove () işleminin şu anda kuyrukta bulunan tüm öğeler arasında rasgele olarak seçilen bir öğeyi kaldırdığı Kuyruk arabiriminin bir uygulamasıdır. (RandomQueue'yu, öğe ekleyebileceğimiz veya rastgele bir öğeye erişip körü körüne kaldırabileceğimiz bir çanta olarak düşünün.) RandomQueue'daki add (x) ve remove () işlemleri, işlem başına sabit sürede çalışmalıdır.


Ödev rastgele kaldırma işlemlerinin nasıl yapıldığını belirtiyor mu? Kaldırılacak bir dizin mi yoksa bir kuyruk öğesine referans mı verildi?

Herhangi bir ayrıntı vermez. Gereksinimler yalnızca Queue arabirimini uygulayan ve O (1) eklemeleri ve kaldırma işlemlerini içeren bir yapıdır.
Carcigenicate

Bir kenara - O (n) büyüyen yeniden boyutlandırılabilir bir dizi mutlaka O (1) ekine sahip değildir: bu , diziyi nasıl büyüttüğümüze bağlıdır . Sabit bir miktarda a büyümesi hala ekleme 1/aiçin O (n) 'dir (O ​​(n) operasyonu için bir şansımız vardır), ancak sabit bir faktörle büyümek a > 1O (1)' in eklenmesi için itfa edilir: (1/a)^nO (n) operasyon, ancak bu olasılık büyük için sıfıra yaklaşır n.
amon

ArrayLists sonuncuyu doğru kullanıyor mu?
Carcigenicate

1
Sorunun yazarı (ben) itfa edilmiş sabit zaman çözümünü düşünüyordu. Bunu bir sonraki baskıda açıklığa kavuşturacağım. (Her ne kadar en kötü durum sabit zamanı burada amortisman tekniği kullanılarak elde edilebilir .)
Pat Morin

Yanıtlar:


10

İtfa Edilen Sabit Zaman hemen hemen her zaman Sabit Zamana eşdeğer kabul edilebilir ve başvurunuzun özelliklerini ve bu kuyruğa yapmayı planladığınız kullanım türünü bilmeden, büyük olasılıkla karşılanmanızdır.

Bir dizi listesi , temelde şimdiye kadar ihtiyaç duyulan en büyük boyut / uzunluk / sayı sayısına eşit olan kapasite kavramına sahiptir. Yani, başlangıçta dizi listesinin, öğeleri eklemeye devam ederken kapasitesini artırmak için kendini yeniden tahsis etmeye devam edeceği, ancak bir noktada birim zamanda eklenen ortalama öğe sayısının kaçınılmaz olarak ortalama öğe sayısıyla eşleşeceği birim zaman başına kaldırılırsa (aksi takdirde yine de hafızanız biter), bu noktada dizinin kendini yeniden tahsisi durur ve tüm ekler O (1) sabit zamanında karşılanır.

Bununla birlikte, varsayılan olarak, bir dizi listesinden rastgele kaldırmanın O (1) olmadığını, O (N) olmadığını unutmayın, çünkü dizi listeleri kaldırılan öğeden sonraki tüm öğeleri kaldırılanın yerini almak için bir konum aşağı taşır öğe. O (1) 'e ulaşmak için, kaldırılan öğeyi dizi listesinin son öğesinin bir kopyasıyla değiştirmek için varsayılan davranışı geçersiz kılmanız ve ardından son öğeyi kaldırmanız gerekir, böylece hiçbir öğe taşınmaz. Ama sonra, bunu yaparsanız, artık tam olarak bir kuyruğunuz yok.


1
Lanet olsun, taşınma konusunda iyi bir nokta; Ben bunu düşünmedim. Ve rastgele öğeleri kaldırdığımız için, bu teknik olarak artık bu anlamda artık bir kuyruk olmadığı anlamına gelmiyor mu?
Carcigenicate

Evet, bu gerçekten bir kuyruk olarak muamele görmediğiniz anlamına gelir. Ama kaldırılacak eşyaları nasıl bulmayı planladığınızı bilmiyorum. Onları bulma mekanizmanız, sıraya eklendikleri sırayla mevcut olmalarını beklerse, şansınız kalmaz. Öğelerin sırasının bozuk olup olmadığını umursamıyorsanız, o zaman iyisiniz.
Mike Nakis

2
Beklentim, arabirimi RandomQueueuygulamam Queueve sağlanan removeyöntemin kafayı patlatmak yerine rastgele kaldırmasıdır, bu nedenle belirli bir sıralamaya güvenmenin herhangi bir yolu olmamalıdır. Ben o zaman rastgele doğası göz önüne alındığında, kullanıcı herhangi bir özel sipariş tutmak için beklememelisiniz düşünüyorum. Açıklamam için sorumun ödevini alıntıladım. Teşekkür ederim.
Carcigenicate

2
Evet, öğe kaldırma işleminin önerdiğim şekilde yapıldığından emin olursanız iyi olacaksınız gibi görünüyor.
Mike Nakis

Sakıncası yoksa son bir şey. Ben daha çok düşündüm ve hem "gerçek" O (1) eklemeler ve "gerçek" O (1) rastgele kaldırma mümkün gibi görünmüyor; ya tek başına ayrılmış bir yapıya (bir dizi gibi) kaldırma sağlayan ancak ek olmayan ya da ekleri veren ancak kaldırmayan Bağlantılı Liste gibi yığın ayrılmış bir yapıya sahipsiniz. Bu doğru mu? Tekrar teşekkür ederim.
Carcigenicate

14

Soru, amortize edilmiş sabit bir zaman değil, özellikle sabit bir zaman istemektedir . Dolayısıyla, alıntılanan soru ile ilgili olarak, hayır, etkin bir şekilde aynı değildirler *. Ancak bunlar gerçek dünya uygulamalarında mı?

İtfa edilmiş sabit ile ilgili tipik sorun, zaman zaman birikmiş borcu ödemek zorunda olmanızdır. Bu nedenle, insertler genellikle sabitken, bazen yeni bir blok tahsis edildiğinde her şeyi yeniden yerleştirmenin yükünü çekmeniz gerekir.

Sabit zaman ile itfa edilmiş sabit zaman arasındaki farkın bir uygulama ile ilgili olduğu durumlarda, bu çok düşük hızın kabul edilebilir olup olmadığına bağlıdır. Çok sayıda alan için bu genellikle uygundur. Özellikle konteyner etkili bir maksimum boyuta sahipse (önbellekler, geçici tamponlar, çalışma kapları gibi) uygulama sırasında maliyetlerini sadece bir kez etkili bir şekilde ödeyebilirsiniz.

Kritik uygulamalarda bu süreler kabul edilemez. Kısa süreli bir geri dönüş garantisini karşılamanız gerekiyorsa, bunu zaman zaman aşacak bir algoritmaya güvenemezsiniz. Daha önce bu tür projeler üzerinde çalıştım, ancak bunlar son derece nadir.

Ayrıca, bu maliyetin gerçekte ne kadar yüksek olduğuna da bağlıdır. Vektörler, yeniden tahsis maliyetleri nispeten düşük olduğundan iyi performans gösterir. Ancak karma haritaya giderseniz, yeniden tahsis çok daha yüksek olabilir. Yine de, çoğu uygulama için muhtemelen iyi, özellikle kaptaki öğeler üzerinde bir üst sınırı olan daha uzun ömürlü sunucular.

* Yine de burada bir sorun var. Herhangi bir genel amaçlı kabın yerleştirilmesi için sabit bir zaman olması için iki şeyden birinin tutulması gerekir:

  • Konteyner sabit bir maksimum boyuta sahip olmalıdır; veya
  • ayrı öğelerin bellek ayırma süresinin sabit olduğunu varsayabilirsiniz.

"karaciğer sunucusu" burada kullanmak için garip bir ifade gibi görünüyor. Şunu mu demek istediniz: "live server" belki?
Pieter Geerkens

6

Verim için mi yoksa gecikme için mi optimize ettiğinize bağlıdır:

  • Gecikmeye duyarlı sistemler tutarlı performans gerektirir. Böyle bir senaryo için, sistemin en kötü durum davranışını vurgulamamız gerekir. Örnekler, tutarlı bir kare hızı elde etmek isteyen oyunlar veya belirli bir sıkı zaman aralığı içinde yanıt göndermek zorunda olan web sunucuları gibi yumuşak gerçek zamanlı sistemlerdir: CPU döngülerini boşa geçirmek geç olmaktan daha iyidir.
  • Verimliliği optimize edilmiş sistemler, azami miktarda veri uzun vadede işlenebildiği sürece, ara sıra duraklarla ilgilenmez. Burada öncelikli olarak itfa edilmiş performansla ilgileniyoruz. Bu genellikle sayı sıkışma veya diğer toplu işleme işleri için geçerlidir.

Bir sistemin farklı kategorilere ayrılması gereken farklı bileşenlere sahip olabileceğini unutmayın. Örneğin, modern bir metin işlemcisinde gecikmeye duyarlı bir kullanıcı arayüzü iş parçacığı bulunur, ancak yazım denetimi veya PDF dışa aktarma gibi diğer görevler için iş hacmi için optimize edilmiş iş parçacıkları bulunur.

Ayrıca, algoritmik karmaşıklık çoğu zaman düşündüğümüz kadar önemli değildir: Bir sorun belirli bir sayıya bağlı olduğunda, gerçek ve ölçülen performans özellikleri “çok büyük n için ” davranışından daha önemlidir .


Ne yazık ki, çok az geçmişim var. Soru şu şekilde biter: "Bir RandomQueue'daki add (x) ve remove () işlemleri, işlem başına sabit zamanda çalışmalıdır".
Carcigenicate

2
@Sistemin gecikmeye duyarlı olduğunu bilmiyorsanız, bir veri yapısı seçmek için itfa edilmiş karmaşıklığı kullanmak kesinlikle yeterli olmalıdır.
amon

Bunun bir programlama alıştırması veya bir test olabileceği izlenimini edindim. Ve kesinlikle kolay değil. Çok nadiren önemli olduğu kesinlikle doğrudur.
gnasher729

1

"İtfa edilmiş sabit zaman" algoritması istenirse, algoritmanız bazen uzun sürebilir. Örneğin, C ++ 'da std :: vector kullanıyorsanız, böyle bir vektör 10 nesne için alan ayırmış olabilir ve 11. nesneyi ayırdığınızda, 20 nesne için alan ayrılır, 10 nesne kopyalanır ve 11. nesne eklenir. uzun zaman alır. Ancak bir milyon nesne eklerseniz, ortalama süre hızlı olmak üzere 999.980 hızlı ve 20 yavaş işleminiz olabilir.

"Sabit zaman" algoritması istenirse, algoritmanız her işlem için daima hızlı olmalıdır . Bu, her bir işlemin her zaman hızlı olduğu garantisine ihtiyaç duyabileceğiniz gerçek zamanlı sistemler için önemlidir . "Sabit zaman" genellikle gerekli değildir, ancak kesinlikle "itfa edilmiş sabit zaman" ile aynı değildir .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.