2011-07-17 37 views
9

Yineleyiciler C++ 's STL'de nasıl çalışırlar diye merak ettim. Setin ikili arama ağacı kullanılarak gerçekleştirildiğini tahmin ediyorum, yani yineleyiciler bu ağacın geçişini yapıyor demektir. Ama benim sorum şu ki, ne zaman onlar gibi yaptığımız bu geçişi yaparlar, ve s =() gibi iç içe geçmiş imleçleri depolamak ve her artışta sadece bu veri yapısını belirtmek Yineleyicideki veya yineleyicideki artış ağacın üzerinde yeni bir harekette geçiş yapar. BizSette yineleyici nasıl çalışır

 set<int> s; 
    set<int>::iterator it; 

//and then use it like: 

     for(it = s.begin(); it!=s.end();) 
     { 
      dosth(); 
      ++it;  // does this do a inorder traversal of the tree again to find the next 
        // node or it gets the next node in the tree by reading the internal 
        // data structure(of inorder traversal) which is created when we do s.begin(). 
     } 

cevap

6

gibi uygulama bağımlı olduğunu başlatmak zaman

demek istiyorum. Ancak, std :: set yineleyicileri yalnızca yineleyici kümeden kaldırılan bir öğeye başvurduğunda geçersiz kılar. Bu nedenle, ağaçtaki düğümler olarak std::set yineleyicileri düşünebilirsiniz. ++, ağacın bir çapraz yönünde hareket eder ve - diğerini hareket ettirir.

Yineleyicilerin begin numaralı diğer işlevlerle döndüğünden, bunların geçerliliğinin yalnızca yeniden başlat/bitirme ile sınırlı olmadığını unutmayın.

+0

Cevabınız için teşekkürler .... ama soruyu başka bir şekilde koymama izin verin .. eğer sizden istenirse std :: setindeki yineleyicilerin artış işlemlerini nasıl uygularsınız? Bağlantılı liste yerine ikili arama ağacını kullanarak ... her seferinde her seferinde bu ağacın sırasını değiştirir misiniz? ++ ... Eğer siparişi düzenli olarak kaydedecek ve bunu yaptığınız her seferinde buna değecektir ++ – raja

+0

@raja: Basit bir bağlantılı liste kullanarak std :: set 'uygulayamazsınız. Bir kümede bir eleman bulmak O (log N) olmalıdır, ancak bağlantılı bir listede bir eleman bulmak O (N) 'dir. Bu mutlaka bir ağaçtır. Bir ağaç düğümü, üst düğümünde bir işaretçi tutarsa, "++ ++", tam bir ağaç geçişi olmadan her zaman bir sonraki en yüksek değeri bulabilir. – MSalters

6

Bu ilginç bir soru. Nicol'in belirttiği gibi, uygulamaya bağlı ve kendi setini uygularken küçük yineleyicileri veya daha hızlı geçişi tercih edip etmediğinize karar vermelisiniz (hızlandırmak için tekrarlayıcılara daha fazla veri koyabilirsiniz).

Platformumda (64 bit) std::set<T>::iterator 8 bayt boyutunda, bu yalnızca işaretçiyi gerçek düğüme tutmayı önerir. Eğer set bir çeşit ağaç kullanılarak uygulanırsa, o zaman yineleyicinin arttırılması kesinlikle bir O (1) işlem değildir ve log (N) ek düğümlere kadar (eğer dengeli ağaçtan bahsediyorsa) çaprazlamasına ihtiyaç duyar. Ayrıca farklı düğümler için ++it işleminin hızını da kontrol ettim ve bu, ekstra geçişler öneren sabit değil. Genel amaçlı set konteynır için tamamen iyidir, çünkü ağaç geçişi karmaşıklığı beklentisini karşılar ve insanlar genellikle yineleyicileri olabildiğince küçük tutarlar. Standart özyineleli ağaç geçişini uygularsanız, tam olarak aynıdır, yığın üzerindeki fazladan düğüm ziyaretlerini gizlersiniz.

Kendi ağaç yineleyicinizi uygulama hakkında daha ayrıntılı bilgi almak için Implementing an iterator over a binary search tree'a bakın.

+0

64 bit makinede çalışıyorsanız, adres 8 bayttır. Yineleyici, tek veri üyesi bir işaretçi olan bir sınıf olarak uygulanabilir. Bu, GNU uygulamasının tam olarak nasıl çalıştığını gösterir. –

+0

David, sen haklısın, şu an 64-bit makinede olduğumu unuttum. Teşekkürler, gönderimi düzenledim. – tomasz