[:tr]Haftalık C++ 2 – Konteynerler ve sıralı tutma [:en]Weekly C++ 2 – Containers and keeping sorted [:]

[:tr]Merhaba arkadaşlar,

Haftalık C++ kod örneklerimize devam ediyoruz. Bu haftaki problemimiz std::vector gibi konteynerlere (nedir arkadaş bu STL konteyner sevdası yahu 🙂 duyar gibiyim) bir yandan veri eklerken bir yandan da bunları sıralı tutabilir miyiz?

Bu probleme geçmeden önce konteyner konusuna ufak bir eğilelim, çünkü buradaki problemi çözerken bir miktar değinmemiz gerekecek. Bu sınıfların detaylarına girmeyeceğim ama merak edenler bu sayfaya göz atabilirler. Burada her bir sınıfa ilişkin detaylı bilgi, performans ve servisler sıralanmaktadır.

STL günlük hayatta ihtiyaç duyabileceğimiz veri yapılarına (queue, stack, linked list, vs) ilişkin bir çok konteyner sınıfını içerisinde barındırıyor. Genel olarak bunlar oldukça hızlı ve verimli bir şekilde gerçeklenmiş durumda. Hepsi ortak arayüzler sunuyorlar ve iyi bir şekilde dökümante edilmiş durumdalar. Genel olarak bu konteynerler dört ana gruba ayrılıyor:

  • Sıralı Konteynerler (“Sequence containers”)
    • Aynı tip verileri sıralı bir şekilde saklayan veri yapılarını ifade etmek için kullanılırlar,
    • Bu grup altında array (statik veri dizisi), vector (dinamik veri dizisi), forward_list (tek yönlü bağlı liste), list (çift yönlü bağlı liste) ve deque (çift yönlü kuyruk) konteynerleri var.
  • İlişkili Konteynerler (“Associative containers”)
    • Hızlı erişime olanak sağlamak adına sıralı veri yapıları sunan konteynerleri kapsar,
    • Bu grup altında set (tekli sıralı küme), map (tekli ilişkili dizi, anahtarlara göre sıralı) , multiset (çoklu sıralı küme), multimap (çoklu ilişkili dizi, anahtarlara göre sıralı) konteynerleri var.
  • Sırasız İlişkili Konteynerler (“Unordered associative containers”)
    • İlişkili dizilerden farklı olarak sırasız fakat hızlı erişim ( en kötü durumda O(n)  ) adına hash kullanan veri yapılarını ifade eden konteynerleri içerisinde barındırır,
    • Bu sınıflar C++ 11 ile birlikte sunulmaya başlandılar,
    • Bu grup altında unordered_set, unordered_map, unordered_multiset ve unordered_multimap konteynerlerini içerisinde barındırır. Bunlar ilişkili konteynerlerin hash kullanan karşılıklarıdır.
  • Konteyner Adaptörleri (“Container adapters”)
    • Bunlar alında kendi başlarına bir konteyner olmayan, daha çok yukarıdakileri kullanan/sarmalayan sınıflar olarak düşünülebilir,
    • Bu grup altında stack (“LIFO – Last in first out” yığın veri yapısı), queue (“LILO – Last in last out” kuyruk veri yapısı) ve priority_queue konteynerleridir. Bunlara ilişkin kabiliyet ve servisler vector, deque ve list ile de sunulabilmekte.

Şimdi gelelim problemimize elimizde sıralı konteynerler var (ör. vector) ve eklediğimiz her eleman ile sıranın bozulmadan korunmasını istiyoruz bunu kolay bir şekilde nasıl yapabiliriz?

İlk yöntem her ekleme sonrası “algorithm” kütüphanesi tarafından sunulan sort() metodunu kullanmak olabilir ki tahmin edeceğiniz üzere pek ucuz bir yöntem olmayacaktır 🙂 Neyse aşağıda örnek bir vector ilklendirelim ve bunu sıralayalım.

Evet sıralı eklemek için yine “algorithm” kütüphanesinden bir metottan yardım alacağız. Bu metot lower_bound().  Aşağıda bu metodun tanımını görebilirsiniz:

Metot kısaca [First, Last) aralığındaki verilen val değerinden küçük olmayan ilk elemanı işaret eden iterator’ü dönüyor.

Örneğin: {10, 20, 30, 40, 50} girdisi için 10 ve 50 arasında 35 değeri için bu metot 3 dönecek, 15 için ise 1 dönecek.

Aşağıda bu metodun ve kardeşinin (upper_bound()) kullanıma ilişkin örnek bir kod ta görebilirsiniz:

Şimdi geldi sıra assolistimize (addSorted) 🙂

addSorted() metodu nasıl çalışıyor? Aslında bütün espri lower_bound() metodunda bütün listeyi bu metoda geçiriyoruz ve o da bize değeri ekleyeceğimiz yeri dönüyor. Daha sonra da vector sınıfının insert() metodu ile elemanı ekliyoruz.

Tabi şimdi bunu diğer konteynerler de kullanamaz mıyız diye sorduğunu duyar gibiyim. Elbette sevgili yazılımperver dostum elbette. Bunun için “template” ları kullanacağız. Aşağıda daha jenerik addSorted() metodumuz ve bunu list ile olan kullanımını bulabilirsin.

Bir sonraki haftalık C++ yazımda görüşmek üzere.

Kendinize iyi bakın.[:en]Hello everybody,

We continue to our Weekly C++ posts. This week’s problem is to check if it is possible to keep the containers like std::vector sorted as inserting new elements. Well the short answer is yes!

Before delving into problem, let me briefly talk about containers as we need to mention the nature of containers while dealing with problem. I will not explain all details but if you are interested in details you can check this page out. You can find a summary of all classes and operations.

STL contains many data structures that you may need during developing your applications. Generally, these are optimized and efficient classes which are being used extensively in production code. Most of them have similar interfaces and very well documented. We can group these containers as follow:

  • Sequence containers
    • Covers the data structures that store same type of data sequentially,
    • array (statik veri dizisi), vector (dinamik veri dizisi), forward_list (tek yönlü bağlı liste), list (çift yönlü bağlı liste) ve deque (çift yönlü kuyruk) are the containers that listed under this group.
  • Associative containers
    • Covers the sorted data structures that can be quickly searched,
    • set (tekli sıralı küme), map (tekli ilişkili dizi, anahtarlara göre sıralı) , multiset (çoklu sıralı küme), multimap (çoklu ilişkili dizi, anahtarlara göre sıralı) are the containers that listed under this group.
  • Unordered containers
    • Different from the previous group of containers, these containers are not ordered, however, they use hash data structure for fast access and search,
    • These are introduced with C++ 11 ,
    • unordered_set, unordered_map, unordered_multiset ve unordered_multimap are the containers that listed under this groups. These are the hash-based version of associative containers.
  • Container adapters
    • This group of containers are wrapper to sequential container which provide different interfaces,
    • stack (“LIFO – Last in first out” yığın veri yapısı), queue (“LILO – Last in last out” kuyruk veri yapısı) ve priority_queue are the containers that listed under this group. In fact, similar behavior and capabilities can be achieved with containers using vector, deque and list.

Now lets go back to our problem. We have a sequential container (e.g. vector) and we would like to keep it sorted with consequtive insertion operations. How can we achieve this?

Well, obviously the first method is to use the sort() method provided by “algorithm” library which as you may guess will not be cheap 🙂 Now, lets initialize a vector and then sort it:

Well, to resolve this problem, we will employ another method from “algorithm” library which is lower_bound() method.   You can find the signature of this method below:

Briefly this method returns the iterator that points the index of first element which is not less (which of course might be equal) than provided value in given range of [First, Last) .

For instance, for provided {10, 20, 30, 40, 50} input and range of [10, 50] and 35 input value it will return 3 and for input value 15 it will return 1.

You can find an example usage of this method with its sister (upper_bound()):

Finally, let’s define our method: addSorted()

how addSorted() method works? In fact, lower_bound() performs the most of the task that we need and return the place that we should add new element. Then what we need to do is simply call insert() method of vector.

Now you may wonder if we can utilize this method with other containers. Well, sure, as long as they are sequential container. To do so, we will get help from templates. Below you can find the generic version of addSorted() method and example usage with list container.

See you soon in another Weekly C++ post.[:]

2 Comments [:tr]Haftalık C++ 2 – Konteynerler ve sıralı tutma [:en]Weekly C++ 2 – Containers and keeping sorted [:]

  1. mehmet uluskan

    Aslında unordered’lar da Associative konteynerler. 3 ana gruba ayrılsa başta daha mantıklı gibi. İyi çalışmalar

    1. yazılımperver

      Doğrudur, sırasız konteyner’ler de aslında “associative”, fakat map ve set gibi olanlardan da farklılar (hem kullanılan veri yapıları hem de anahtarların yönetilmesi anlamında). Bu sebeple ayrılıyorlar. Bu bağlamda ilgili grup ismini güncelledim.
      Elbette, “Associative” vs “Sequential” diye de bir ayrıma gidilebilir ama genel kabül gören yaklaşım bu.

Comments are closed.