Thread overview
C++'daki Yığıt(stack) Benzeri
Sep 14, 2012
Salih Dinçer
Sep 14, 2012
erdem
Sep 14, 2012
Salih Dinçer
Sep 15, 2012
Salih Dinçer
September 14, 2012

Merhaba,

C++'da, bir yığıt oluşturulduğunda, en sondaki değere top() üyesi ile erişebiliyoruz. Bu erişim zannedersem gösterge boyutunda çünkü içeriği değiştirilebiliyor. Bunun benzerini aşağıdaki yapıyla benzetmeye çalıştım:

struct Stack
{
   int konum;
   int[] stack;

   void push(T)(T veri)
   {
       stack ~= veri;
       konum++;
   }

   int pop()
   {
       return stack[--konum];
   }

   int * top()
   {
       return &stack[konum - 1];
   }

   bool empty() const
   {
       return konum == 0;
   }
}

import std.stdio;
void main() {
   Stack st;
   foreach(i; 0..10) st.push(i);
   writeln(*st.top);     // 9;
   writeln(++(*st.top)); // 10;
}

Ancak yine önemli bir fark çünkü göstergesiz bu değere erişemiyoruz ve kod içinde yıldızsız kullanamıyoruz. Oysa C++'da yıldız kullanmadan işleve sanki bir üye değişken gibi erişebiliyoruz. Sizce D'de bunun bir olanağı var mıdır?

Teşekkürler...

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

September 14, 2012

Alıntı (Salih Dinçer):

>

C++'da, bir yığıt oluşturulduğunda, en sondaki değere top() üyesi ile erişebiliyoruz. Bu erişim zannedersem gösterge boyutunda çünkü içeriği değiştirilebiliyor.

Hayır. Zaten amacımız en üstteki elemana erişmek.

// yigit.h

#if !defined YIGIT_H
#define YIGIT_H

const int yigitmaksimum = 16;

class TamsayiYigit
{
public:
   TamsayiYigit () : enust_ (0) {}
   void Ekle (int sayi);
   int Cikar ();
   int Tepedeki () const;
   bool DoluMu () const;
   bool BosMu () const;

private:
   int elemanlar_ [yigitmaksimum];
   int enust_;
};

#endif

// yigit.cpp

#include "yigit.h"
#include <iostream>
#include <stdexcept>
using std::cout;
using std::cin;
using std::cerr;

void TamsayiYigit::Ekle (int sayi)
{
   // Taşmaya izin verme
   if (enust_ >= yigitmaksimum)
       throw std::range_error ("Yigit maksimum sinirina ulasti\n");
   elemanlar_ [enust_] = sayi;
   ++enust_;
}

int TamsayiYigit::Cikar ()
{
   // Boş bir yığıttan eleman çıkarmaya kalkma
   if (enust_ <= 0)
       throw std::range_error ("Yigit bosken nesne cikaramam\n");
   --enust_;
   return elemanlar_ [enust_];
}

int TamsayiYigit::Tepedeki () const
{
   // Boş bir yığıtın en üstündeki elemanı öğrenmeye kalkma
   if (enust_ <= 0)
       throw std::range_error ("Bos yigitin en ust elemani ogrenilemez\n");
   return elemanlar_ [enust_ - 1];
}

bool TamsayiYigit::DoluMu () const
{
   return (enust_ == yigitmaksimum);
}

bool TamsayiYigit::BosMu () const
{
   return (enust_ == 0);
}

int main ()
{
   try
   {
       int sayi;
       TamsayiYigit tamsayi;
       tamsayi.Ekle (1);
       tamsayi.Ekle (8);
       cout << "Bir sayi girin:";
       cin >> sayi;

       cout << "Cikarilan sayi: " << tamsayi.Cikar () << "\n";
       cout << "Cikarilan sayi: " << tamsayi.Cikar () << "\n";
       cout << "Cikarilan sayi: " << tamsayi.Cikar () << "\n";
   }

   catch (std::exception const & hata)
   {
       cerr << "HATA :" << hata.what () << "\n";
       return 1;
   }

   catch (...)
   {
       cerr << "HATA :" << "Bilinmeyen bir hata var\n";
       return 1;
   }
}

Hatta biraz daha C++ stili yazarsak :-)

#include <algorithm>
#include <assert.h>

template <class T>
class Yigit
{
   T * nesneler_;
   int buyukluk_;
   int tepe_;

   void buyult()
   {
       int const eski_buyukluk = buyukluk_;
       buyukluk_ = ((buyukluk_ == 0)
                    ? 2
                    : buyukluk_ * 3 / 2);

       T * yeni_nesneler = new T[buyukluk_];
       std::copy(nesneler_,
                 nesneler_ + eski_buyukluk,
                 yeni_nesneler);

       delete[] nesneler_;
       nesneler_ = yeni_nesneler;
   }

public:

   Yigit()
       :
       nesneler_(0),
       buyukluk_(0),
       tepe_(-1)
   {}

   ~Yigit()
   {
       delete[] nesneler_;
   }

   // push
   void ekle(T const & nesne)
   {
       ++tepe_;

       if (tepe_ == buyukluk_)
       {
           buyult();
       }

       nesneler_[tepe_] = nesne;
   }

   // pop
   T cikart()
   {
       assert(tepe_ >= 0);
       --tepe_;
       return nesneler_[tepe_ + 1];
   }

   T & tepe()
   {
       return nesneler_[tepe_];
   }

   // Bu da sabit Yigit nesneleri icin
   T const & tepe() const
   {
       return nesneler_[tepe_];
   }

};

#include <iostream>

using std::cout;

int main()
{
   int const adet = 3;
   Yigit<int> yigit;

   for (int i = 0; i != adet; ++i)
   {
       cout << "Ekliyorum: " << i << '\n';
       yigit.ekle(i);
   }

   for (int i = 0; i != adet; ++i)
   {
       cout << "Cikarttim: " << yigit.cikart() << '\n';
   }

   yigit.ekle (8);
   int const tepedeki = yigit.tepe();
   yigit.cikart();
   cout << "Cikarttim: " << tepedeki << '\n';
}

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

September 14, 2012

Teşekkürler,

ref takısını denemiştim ama herhalde çok hızlı geçmiş olmalıyım ve/veya bir şeyleri karıştırmışım ki C gibi yapmayı yeğledim. Böylesi daha yakışıklı oldu...:)

Ancak hızlıSırala() algoritmasını tam olarak beceremedim. Eminim koşullar ile ilgili ufak bir hata yapıyorum. Çünkü çoğunluğu doğru sıralıyor ama son adımlarda işler karışıyor...:(

void hızlıSırala(T)(ref T[] dizi) {
 Stack!T st;
 st.push(0);
 st.push(dizi.length - 1);

 do {
   T Üst = st.pop();
   T Alt = st.pop();

   do {
     T altSınır = Alt;
     T üstSınır = Üst;

     T Mihenk = dizi[(Alt + Üst) / 2];
     while(altSınır <= üstSınır) {
       while(dizi[altSınır] < Mihenk) ++altSınır;
       while(dizi[üstSınır] > Mihenk) --üstSınır;
       if(altSınır != üstSınır) {
         T tmp;
         tmp = dizi[altSınır];
         dizi[altSınır] = dizi[üstSınır];
         dizi[üstSınır] = tmp;
       } else {
         ++altSınır;
         --üstSınır;
       }
     }
     if(altSınır > Üst) {
       st.push(altSınır);
       st.push(Üst);
     }
     Üst = üstSınır;
   } while(Alt < Üst);
 } while(!st.empty);
}

import std.stdio;
void main() {
 auto dizi = [5, 3, 25, 6, 10, 17, 1, 2, 18, 8];
 dizi.writeln;
 hızlıSırala(dizi);
 dizi.writeln;
}

Çıktısı:
'[5, 3, 25, 6, 10, 17, 1, 2, 18, 8]
[1, 2, 5, 6, 3, 8, 10, 17, 18, 25]'

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

September 14, 2012

C++'ta std::stack::top() üstteki elemana referans döndürür:

     value_type& top ( );
const value_type& top ( ) const;

Referanslar D'de de var. (Ama C++ kadar yaygın değil çünkü yerel ref değişkenleri oluşturamıyoruz. (Walter'ın söylediğine göre bunun geçerli nedenleri varmış ama ben hiç bilmiyorum.))

   ref int top()
   {
       return stack[konum - 1];
   }

Artık yıldıza gerek yok:

   writeln(st.top);     // 9;
   writeln(++(st.top)); // 10;

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

September 14, 2012

if(altSınır != üstSınır) karşılaştırması mı doğru değil acaba? Eğer doğru anlıyorsam Rosetta Code'da orada <= var:

http://rosettacode.org/wiki/Sorting_algorithms/Quicksort#C

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

September 15, 2012

Maalesef başka bir sorun var! Sanırım stack ile ilgili çünkü şuradaki (http://jeffreystedfast.blogspot.com/2007/03/quick-sort.html) algoritmayı kendime uyarladığımda netice benzer...:(

Bu sefer de son değişimi yapmadığı gibi sonsuz döngüye giriyor. Olayı fark edebilmek için core.thread'daki uyuma olayını eklediğim bir satır daha ekledim. Ayrıca iç içe döngülerden birinden kurtulmuş oldum. En iyisi salim kafayla bu non-recursive quick sort algorithm'i tekrar yazmalı:

void hızlıSırala(T)(ref T[] dizi) {
 Stack!T lo, hi;
 lo.push(0);
 hi.push(dizi.length - 1);

 do {
   T Üst = hi.pop();
   T Alt = lo.pop();

   if((Üst - Alt) < 1) continue;
   T Mihenk = dizi[(Alt + Üst) / 2];

   T altSınır = Alt;
   T üstSınır = Üst;

     do {
       while(altSınır < üstSınır && dizi[altSınır] < Mihenk) {
         ++altSınır;
       }
       while(üstSınır > altSınır && dizi[üstSınır] > Mihenk) {
         --üstSınır;
       }
       if(altSınır <= üstSınır) {
         T tmp;
         tmp = dizi[altSınır];
         dizi[altSınır] = dizi[üstSınır];
         dizi[üstSınır] = tmp;
         ++altSınır;
         --üstSınır;
         dizi.writeln;Thread.sleep(dur!"msecs"(500));
       } else break;
     } while(true);

   if(Alt < üstSınır) {
     lo.push(Alt);
     hi.push(üstSınır);
   }
   if(altSınır < Üst) {
     lo.push(altSınır);
     hi.push(Üst);
   }
 } while(!(lo.empty && hi.empty));
}

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]