• Bağış
  • Hızlı Sıralama Algoritması (Quick Sort Algorithm)

    Yazan : Şadi Evren ŞEKER

    Verinin hafızada sıralı tutulması için geliştirilen sıralama algoritmalarından (sorting algorithms) bir tanesidir. Basitçe sıralanacak olan dizideki orta noktada (mean) bulunan bir sayıyı seçerek diğer bütün sayıları bu orta sayıdan büyük veya küçük diye sınıflayarak sıralama yapmayı hedeflemektedir. Bu açıdan bir parçala fethet (divide and conquere) yaklaşımıdır. Ayrıca bu seçilen orta noktaya eksen (pivot) adı da verilir çünkü bütün diğer sayılar bu sayının ekseninde sıralanacaktır.

    Get the Flash Player to see this content.

    Sıralanmak istenen verimiz:

    5,7,2,9,6,1,4,7 (düzeltildi, Erol Bey'e teşekkürler)

    olsun. Bu verilerin bir oluşumun(composition) belirleyici alanları olduğunu düşünebiliriz. Yani örneğin vatandaşlık numarası veya öğrenci numarası gibi. Dolayısıyla örneğin öğrencilerin numaralarına göre sıralanması durumunda kullanılabilir.

    Yukarıda verilen bu örnek dizinin sıralanması adım adım aşağıda anlatılmıştır:

    1. adım, dizinin ortasındaki sayı bulunur. Bu örnekte 8 sayı olduğu için ortadaki sayı 4. elemandır. Bu elemanın değeri de 9′dur. Bu durum aslında biraz bahtsız bir durumdur çünkü tesadüfen dizideki en büyük sayıdır. Bu mesele 2. adımda ortaya çıkacaktır.

    2.adım: Diziden 1.adımda seçilen sayıya göre dizideki bütün elemanları küçük veya büyük diye sınıflandır. Tabi 1. adımda şanssız bir şekilde en büyük sayı seçildiği için bütün sayılar 9′dan küçük olarak sınıflandırılacaktır.

    5,7,2,6,1,4,7 (9)

    3. adım: Sınıflandırılana küçük ve büyük dizileri tekrar hızlı sıralamaya ver. Yani 5,7,2,6,1,4,7 dizisini aynı adımlarla tekrar sıralıyoruz.

    4. adım: eleman sayımız 7 ve ortadaki eleman 3. eleman olan 6 olur. Dizideki sayılar 6′dan büyük ve 6′dan küçük diye sınıflandırılırsa:

    5,2,1,4 (6) 7,7

    olarak iki grup elde edilir. Bu grupları da sıralamak üzere tekrar hızlı sıralama algoritmasına veririz. Dolayısıyla 5,2,1,4 sayıları ayrı ve 7,7 sayıları ayrı ayrı sıralanacaktır.

    5. adım 5,2,1,4 sayılarının orta değeri 2′dir ve sınıflandırılırsa:

    1 (2) 4,5 bulunur. Aynı zamanda diğer dizi olan 7,7 sıralanırsa sonuç değişmez ve 7,7 bulunur.

    6. adım 1 sıralanırsa 1 ve 4,5 sıralanırsa 4,5 bulunur.

    7.adım. Bu adımdan sonra artık birleştirme işlemine geçilebilir. Buna göre 6. adımda sıralanan değerleri birleştirirsek :

    1,2,4,5 değerleri elde edilir.

    8.adım: 4. adımdaki sayılar birleştirilirse 1,2,4,5,(6),7,7 sayıları elde edilir.

    9.adım: 2. adımdaki sayılar birleştirilirse 1,2,4,5,6,7,7 (9) olarak dizinin sıralanmış hali elde edilir.

    Bu algoritmanın JAVA dilindeki karşılığı aşağıdaki şekilde yazılabilir:

      public static void quickSort(int A[],int p, int r)
    {
        int q;
        if(p<r)
        {
            q=partition(A,p, r);
            quickSort(A,p, q-1);
            quickSort(A,q+1, r);
        }
    }

    Görüldüğü üzere yukarıdaki kod özyineli (recursive) bir koddur ve kendi içerisinde orta değeri bulmak için partition adı verile harici bir fonksiyonu çağırmıştır. Bu fonksiyonun kodu da aşağıda verilmiştir:

    public static int partition(int A[],int p, int r){
        int tmp;
        int x = A[r];
        int i = p-1;
    
        for(int j=p; j<=r-1; j++)
        {
            if(A[j]<=x)
            {
                i++;
                tmp=A[i];
                A[i]=A[j];
                A[j]=tmp;
            }
        }
        tmp=A[i+1];
        A[i+1]=A[r];
        A[r]=tmp;
        return i+1;
    }

    Yukarıdaki bu orta nokta bulmaya yarayan fonksiyonun en büyük özelliği tek bir dizi kullanarak bu dizi içerisindeki indisi döndürmeye çalışmasıdır. Bu yüzden hangi parça üzerinde orta nokta aradığını alt ve üst limitleri parametre alarak bulur. Bu parametreler koddaki p ve r değişkenleridir.

    Hızlı sıralamanın algoritma karmaşıklığına bakıldığında O(nlogn) olarak bulunur çünkü üzerinde çalışılan dizi her adımda en fazla 2ye bölünmüştür (Big-O hesaplanırken en kötü ihtimalin hesaplandığını hatırlayınız) böylece sonuç dizisi olan 2şer elemanlı dizilere log2n adımda ulaşılabilir. Daha sonra her n eleman için sıralama yapıldığı ve her n eleman üzerinden geçildiği için bu değer çarpan olarak gelmekte ve sonuç nlog2n olarak bulunmaktadır.

    Örnek görsel çalışma

    Yapılan yorumlardan sonra hızlı sıralama algoritmasının çalışmasını görsel bir örnek üzerinden göstermeye karar verdim.

    Sıralayacağımız sayılar 88,31,52,25,98,14,30,62,23,79 olarak verilsin

    Yukarıdaki bu sayıları sıralamak için öncelikle ortadaki değer (pivot) bulunur. Bu değer sayılar arasından rast gele seçilebileceği gibi dizinin ilk elemanı, son elemanı gibi belirli bir yerdeki sayı olarak da atanabilir. Bu değer yukarıdaki kodda verilen p değişkeni ile gösterilen değerdir. Biz örneğimizde 52 olarak seçtiğimizi düşünelim:

    Yukarıdaki şekilde gösterildiği üzere sayı rast gele olarak seçildikten sonra, diğer sayılar, bu seçilen rast gele sayıdan (52) büyük ve küçük olarak sınıflandırılır.

    Görüldüğü üzere problem iki parçaya bölünmüş ve burada parçala fethet (divide and conquere) yaklaşımı kullanılmıştır. Artık problemin her iki alt kümesi ayrı ayrı yeniden hızlı sıralama algoritmasına verilecek ve bir önceki adımda olduğu gibi sayılar arasından rast gele bir sayı seçilerek problemi alt parçalara bölecektir:

    Yukarıdaki son şekilde görüldüğü üzere problem bir önceki adımda bulunan parçaların alt parçalara bölünmesi ile daha küçük hale getirilmiştir. Burada rast gele olarak seçilen pivot sayıları ilk grup için 25 ve ikinci grup için 79 olmuştur.

    Problem son kez alt adımlara bölünerek çözülür

    Görüldüğü üzere son adımda son kümeler için yine pivot seçimi yapılmış ve 23, 31, 98 sayıları pivot olarak seçilmiştir. Problem bu aşamadan sonra çözülmüştür çünkü bu sayıların alt grupları tek elemanlı kümeler haline gelmiştir.

    Ardından her küme kendi pivotunun solunda veya sağında olmasına göre yukarı doğru toplanır. Bu toplama işlemi yukarıkida şeklin en altında gösterilmiştir.

    Benzer Yazılar:

    Bilgisayar Kavramları üzerinde şu anda okumakta olduğunuz 'Hızlı Sıralama Algoritması (Quick Sort Algorithm)' isimli yazı 09 Aug 2008 tarihinde, saat: 22:22 'de Şadi Evren ŞEKER tarafından gönderilmiş, toplam 7036 defa okunmuştur.

    Benzer yazıları JAVA, algoritma analizi (teory of algorithms), veri yapıları kategorilerinden okuyabilirsiniz. Yazar ile irtibat kurmak için email gönderebilirsiniz. Yazıya yorum yapabilir ya da yapılan yorumları RSS 2.0 ile takibe alabilirsiniz.


    Category: JAVA, algoritma analizi (teory of algorithms), veri yapıları
    Tags: , , , , ,
    11 responses to “Hızlı Sıralama Algoritması (Quick Sort Algorithm)”
    1. mehmet usta says:

      Teşekkürler, gayet güzel ve anlaşılır bir anlatım olmuş.

    2. ERol says:

      Merhaba,
      yararli bir makale, emeginiz icin tesekkürler.
      Fakat gördügüm bir yanlislik var :

      ilk verdiginiz deger :

      Sıralanmak istenen verimiz:

      5,7,2,9,6,1,3,7

      (buradaki 3 degeri 2. Asamada 4 olarak yaziliyor)

    3. Şadi Evren ŞEKER says:

      hatayı düzelttim, ilginiz için teşekkürler

    4. Bekir says:

      Teşekkürler hocam konuyu burdaki anlatım sayesinde daha iyi anladım fakat bir de c dilinde bir kod örneği yayınlayabilirseniz adım adım yorumlayarak tam oturcak konu hocam.İyi çalışmalar(aynı sıkıntı bubblesort,mergesort tada yapabilirseniz çok iyi olur hocam binary search te anlattığınız gibi.)

    5. Anonymous says:

      thank you bilgileriniz için ama akış diyagramınıda çizseydiniz daha iyi olurdu.

    6. Acelya says:

      Merhaba, öncelikle elinize sağlık, gerçekten çok güzel bir anlatım olmuş. Fakat bir noktada takıldım, buradaki p,q ve r değerleri tam olarak neye karşılık geliyor acaba?

      Teşekkürler…:)

    7. Mustafa SARIGÜL says:

      5. adımdaki sıralama 1 (2) 4,5 değil 1 (2) 5,4 olacak
      http://www.erbaaeml.k12.tr7

    8. Şadi Evren ŞEKER says:

      Bu kodda bulunna partition fonksiyonu verilen pivota göre diziyi ikiye bölmektedir.
      Bu durumu açıklayan bir resmi yukarıdaki yazıya ekliyorum. Sanırım daha açıklayıcı olacak.

      Acelya Hanıma uyarısından dolayı teşekkür ederim.

    9. Şadi Evren ŞEKER says:

      evet haklsınız sayıları 5. adımda yazarken 4 ile 5′in yeri değişmiş, yukarıdaki yazıda belirttiğiniz bu hatayı düzeltiyorum.

      Mustafa Bey’e teşekkür ederim.

    10. esra says:

      recursive algoritmalarda ogrenemedigim bir sorun var.yukarıda yazılan kodda quickSort(A,p, q-1);
      isimli fonksiyon if(p<r) kosulu ile calısmaktaysa,bu kosulu terkettiginde nasıl bu fonksiyonuda calıstır? quickSort(A,q+1, r); yardımcı olurmusunuz :(

    11. Şadi Evren ŞEKER says:

      Sorunuzun cevabı, basitçe çalıştırmaz!

      Bakın bahsettiğiniz kod parçasında, p ve r değerleri birer tam sayı ve dizi üzerindeki sıralanacak bölümün sınırlarını tutuyorlar.

      Yani örneğin P=5 , r= 18 için (bu sayıları rast gele yazdım) kodumuz 5. ve 18. dizi elemanları arasındaki sayıları sıralamaya çalışıyor.

      Video’da da anlatmaya çalıştım, hızlı sıralama algoritması, sıralamak istediği sayı bloğunun en sonuncu elemanını pivot olarak alabilir. (farklı sayılarda seçilebilir ama kodda ve video’da son elemanı kabul ettim) dolayısıyla buradaki p-r aralığı sıralanırken, partition isimli fonksiyonda görüldüğü üzere x değeri A[r] yani dizinin sıralanmasını istediğimiz alandaki son eleman oluyor.

      Ardından p ile r arasında dönen bir for döngüsü ile bütün sayılar, bu x değerinden yani pivot değerinden büyük ve küçük olarak tasnif ediliyor.

      Elbette bu sıralama işleminin sadece bir kısmı, ardından bu problem pivotun solundakiler ve pivot’un sağındakiler olarak alt gruplarda çözülecek. Yani bir seviye alta iniyoruz ve buradaki sayıları da sıralıyoruz. Bunun için quicksort fonksiyonunda bulunan diğer iki quicksort fonksiyonu çağırmasına ihtiyaç var. Bu fonksiyonlardan birisi p ile q-1 arasını (buradaki q değeri, pivotun dizideki kaçıncı sayı olduğu) diğer fonksiyon ise q+1 ile r arasını sıralıyor. Yani problem, p-r arasındaki sayılar iken iki alt probleme indiriliyor p-q ve q-r şeklinde iki grup sıralanıyor.
      q elemanı iki gruba da dahil değil (birisinde q-1′e kadar diğerinde q+1′den sonraki sayılar sıralamaya dahil edilmiş) bunun sebebi q değerinin pivot olması ve sıralama işleminde herhangi bir alt gruba girmemesi gerektiğidir.

      Sizin sorunuza dönecek olursak. Bahsettiğiniz if bloğuna pr durumlarında girmez. Bu durumlar da zaten sıralanacak eleman sayımız 0 veya sıfırdan küçük sayıda demektir ki bu da saçmadır. Yani en son 1 eleman sıralanabilir ve bu tek elemanın sıralanmış hali yine kendisidir. 1 elemandan az gruplar sıralanamaz ve bu if kontrolu bunu belirtir.

      Peki neden böyle bir if kontrolüne ihtiyaç duyoruz? Sebebi basit, her pivota göre sağ ve sol şeklinde problemi böldükten sonra elaman sayımız azalıyor. En nihayetinde tek eleman kalıyor ve bu tek elemanı sıralayıp işlemi bitiriyoruz. Şayet bu if kontrollerini koymazsak sıralama işlemi hiç bitmez ve 0 veya eksi değerdeki elemanları da sıralamaya çalışırız.

      Yani daha basit bir ifade ile, bu if kontollerinin amacı, tek elemandan az sayıdaki elemanları sıralamayarak, sıralama işleminin bu seviyede tamamlandığını belirtmektir.

      Bu koşul terk edildiğinde de (yani çalıştırılmadığında) fonksiyon işlemini bitirerek çıkar ve bu fonksiyonu çağırmış olan bir üstteki fonksiyon işe kaldığı yerden devam eder.

    Leave a Reply