Veri Tipleri ve Veri Yapıları

advertisement
Veri Tipleri ve Veri Yapıları
Algoritmalar tarafından işlenen en temel elemanlara (sayısal bilgiler, metinsel bilgiler, resimler, sesler
ve girdi, çıktı olarak veya ara hesaplamalarda kullanılan diğer bilgiler... ) veri denir. Bir algoritmanın
etkin, anlaşılır ve doğru olabilmesi için, algoritmanın işleyeceği verilerin düzenlenmesi gerekir.
Bir programda veri, yapı ve algoritma birbirinden ayrılmaz bileşenlerdir ve her biri önemlidir.
Verilerin düzenlenme biçimleri önemlidir. Çünkü yapı iyi tasarlandığında, etkin, doğru, anlaşılır ve
hızlı çalışıp az kaynak kullanan algoritma geliştirmek kolaylaşır.
Veri Tipleri
Veri tipi (data type) program içinde kullanılacak değişken, sabit, fonksiyon isimleri gibi
tanımlayıcıların tipini, yani bellekte ayrılacak bölgenin büyüklüğünü, belirlemek için kullanılır. Bir
programcı, bir programlama dilinde ilk olarak öğrenmesi gereken, o dile ait veri tipleridir. Çünkü bu,
programcının kullanacağı değişkenlerin ve sabitlerin sınırlarını belirler.
Veriler bilgisayarda bellekte tutulurlar. Bellekte veriler
bitler (1 yada 0) şeklinde tutulur. Bellek, verilerin
tutulduğu birimlerden oluşan bir yapıdır. Her birimin bir
adresi vardır (F3444 gibi). Program yazarken bu adresler
yerine adresleri temsil eden değişkenleri kullanılmış olur.
Bu adresleme değişkenlerin tuttuğu verinin içeriğine göre
farklılık gösterir.1
Günümüzde
kullanılan
programlama
dillerinde
değişkenleri kullanmadan önce kullanılacak değişkenleri
programa tanıtmak gerekmektedir. Bu tanıtma işlemi bazı programlama dillerinde program kodları
yazılmaya başlanmadan önce yapılır. Bazı programlama dillerinde ise değişkenin tanımlanması
değişken kullanımı esnasında yapılabilir
Mantıksal Veri Tipi
Mantıksal veri tipi, içerisinde mantıksal değer olan True (doğru, evet, var) veya False (yanlış, hayır,
yok) değerini saklar. Bu değeri saklamak için bellekte sadece 1 bit kullanılır, doğru veya yanlış
değerini bellekte 1 veya 0 değeri karşılar.
Tam Sayı Veri Tipleri
Programlama dillerinde tamsayıları temsil etmek için bu veri tipi kullanılır. Bir tamsayı veri tipinin
değerinin büyüklüğü bilgisayardan bilgisayara, programlama diline veya bellekte ayrılan yere göre
değişebilir. Tamsayının büyüklüğü ayrıca sayının işaretli (işaretli = negatif - pozitif, işaretsiz = sadece
pozitif) olup olmamasına göre de değişir.
1
http://engindutar.com/dersler/C/pdf/h02.pdf
1
Reel Sayı Tipleri :
Programlama dillerinde daha çok reel (ondalık, kesirli) sayıları göstermek için kullanılan bir veri
tipidir. Bu veri tipi bellekte kayan noktalı (floating point) şekilde saklanır. Kayan noktalı gösterimde E
harfinden sonra gelen sayı 10'un kuvveti şeklinde hesap edilmiştir.
Örneğin;
Kayan noktalı gösterimde virgülden (yani noktadan) sonra kaç basamak olacağına o sayının duyarlılığı
denir. Genelde bilgisayarlarda bu duyarlılık 6 hane olarak belirlenmiştir. Bu sayının virgülden sonraki
altı hanesini değil de kayan noktalı gösteriminde noktadan sonraki altı hanesidir.
Reel sayı veri tiplerinin C programlama dilinde tanımlanması aşağıdaki gibidir;
Karakter ve String Veri Tipleri:
Sayısal olmayan verilerin saklanması için karakter veri tipi kullanılır. Genelde programlama dillerinde
sayısal olmayan veriler bellidir (harfler, işaretler vb.) ve bunlar değişik karakter kümesinde tutulur. Bu
karakter kümelerinde her bir sembole karşılık bir sayısal değer karşılık gelir. Programlama dilleri
değişik karakter kümeleri kullanabilir.
Günümüzde en çok kullanılan karakter kümesi ASCII (American Standart Code for Informatin
Interchange) karakter kümesidir. Bu karakter kümesinden başka değişik karakter kümeleri de
(EBCDIC vb.) mevcuttur.
Bu karakter kümesinden bazı sembollerin sayısal karşılıkları aşağıdaki gibidir;
2
Bellekte bu karakterler yerine bu karakterlerin sayısal karşılıklarının ikili karşılığı şeklinde saklanır.
String veri tipi ise karakterlerin bir peş peşe sıralanmasıyla oluşan veri tipidir.
İşaretçiler
İşaretçi değişkenler sadece “bellek adresi” bilgisini saklayan değişkenlerdir. İstenilen değeri hafızadan
çağırmak için adresini bilmeniz yeterlidir.
Yanlış bellek bölgesine ulaşmak, kötü bir şekilde programın çökmesi ile sonuçlanabilir. Bunu
beyninize rastgele batırılan sivri bir iğne gibi düşünebilirsiniz. İşaretçileri hatalı kullanmak
bilgisayarın belleğini rastgele kurcalamak anlamına gelir.
Birleşik Veri Tipleri
Dizilerde farklı veri türlerini saklama imkânı yoktur. Yani öğrenci listesinde öğrenci isimleri metin,
öğrenci numaraları sayı türünde olsun diyemezsiniz. Tüm elemanların türü aynıdır. Bu eksiklik “yapı”
3
kullanımı ile giderilmektedir. Birçok programlama dili, değişik tiplere sahip olan birden fazla alt
bilgiden oluşan gruplar yaratılmasına izin verir. Yani, bu programlama dilleri kullanıcıların kendi veri
tiplerini tanımlamasına müsaade eder. Bir yapıda istediğiniz türde değişkenleri beraber tanımlayarak
tek isim altında kullanabilirsiniz.
Kullanıcının kendi veri tipini tanımlamasının avantajları şunlardır; Bir gruba ait (mesela öğrenci)
bilgilerin (ad, soyad, no vb.) bir arada tutulmasını, bunları hep beraber kolayca tanımlamayı, değer
atamayı ve karşılaştırmayı tek bir işlemle yapmayı sağlar.
Ad1 = "Ali"
Notu1 = 45
Ad2 = "Veli"
Notu2 = 55
Ad3 = "Mehmet"
Notu3 = 75
Bunun yerine artık şu şekilde yapabiliriz:
Ogrenci1.Ad = "Ali"
Ogrenci1.Notu = 45
Ogrenci2.Ad = "Veli"
Ogrenci2.Notu = 55
Ogrenci3.Ad = "Mehmet"
Ogrenci3.Notu = 75
Görüldüğü gibi farklı türlerde birbiri ile ilişkili yapı elemanları “Ad ve Notu” değişkenleri beraber, tek
bir isim olan “Ogrenci” yapısında toplanıyor.
Programcının kendi yaptığı değişkenlere “kullanıcı tanımlı veri türü – user defined variable” de denir.
Bileşik veri tiplerinin C programlama dilinde tanımlanması ve kullanılması aşağıdaki gibidir;
4
Veri Yapıları
Veri Yapıları, verilerin düzenlenme biçimini belirleyen yapıtaşlarıdır. Değişik algoritmalarda verilerin
diziler, yığıtlar, kuyruklar, ağaçlar ve çizgeler gibi veri yapıları şeklinde düzenlenmesi gerekebilir.
Diziler (Array)
Programlamada uzun ve benzer bilgilerle dolu değer listelerin oluşturulması “dizi - array” ile
yapılmaktadır. Veri yapısını aşağıdaki gibi ayrı değişken yapabileceğiniz gibi2:
Ad1 = "Ali"
Ad2 = "Veli"
Ad3 = "Mehmet"
Bunun yerine dizi kullanarak, tek değişken ile şu şekilde yapabilirsiniz:
Ad(1) = "Ali"
Ad(2) = "Veli"
Ad(3) = "Mehmet"
Dikkat edilirse, önceki örnekte 3 ayrı değişkenimiz
varken, sonrakinde ise tek değişken olan “Ad”
kullanılmıştır. Dizi sayesinde tek değişken ismi ile
birden fazla değer saklanabilmektedir.
StatikDiziler
Normalde bir değişkenin bir adı ve bir değeri olabilir. Dizi değişkenlerinin de bir adı vardır, ama
içinde aynı türde çok sayıda veri saklanabilir. Tanımlarken dizinin boyutunu belirtmemiz mecburidir.
Dizi boyutu tamsayı olarak belirtilmeli, negatif girilmemelidir.
Not: Programlama dillerinde genellikle ilk dizi elemanının indis numarası “0”dır.
Programdaki dizi değişkenlerinin tanımlandıkları satırlar çalıştırıldığında, ana bellekte dizi boyutunca
yer ayrılır. Değişken ile olan işlem bitince ayrılan bellek bölgesi silinir. Belli bir bellek alanı
ayrılmasından dolayı dizinin maksimum sınırı dışındaki diğer bellek bölgesine erişemeyiz.
Dizilere değer aktarma veya okuma işlemlerinde döngü komutları kullanılmaktadır. Hangi döngüyü
kullanılırsa kullanılsın, başlangıç ve bitiş değerleri iyi belirlenmelidir, yoksa program hata verip
kapanır. Sınırın altında veya üstünde indis vermemek gerekir.
ÇokBoyutluDiziler
Tablolama programlarındaki gibi satır ve
sütunlu hücrelerden oluşan dizilere; iki
boyutlu dizi denir. Yandaki resimde de
görüldüğü gibi herhangi bir hücrenin değerine
satır
ve
sütun
bilgisini
kullanarak
erişilebilmektedir. Matematikteki matrisler de
çok boyutlu dizilerdir.
Bir boyut daha eklendiğinde küp şekline benzeyen 3 boyutlu dizi elde edilir. Bu dizilerde satır ve
sütun bilgisinin yanında derinlik bilgisi de eklenir.
2
http://megep.meb.gov.tr/mte_program_modul/modul_pdf/481BB0027.pdf
5
DinamikDiziler
Çoğu dil sadece statik sınırlı dizi imkânı sunar, yani çalışma zamanında dizilerin eleman sayısının
sınırını değiştiremezsiniz. Eğer dizi büyük gelmiş ise dizi kısaltılamaz, ya da tam tersi uzatılamaz.
Statik dizi içi boş bile olsa hafızada yer kaplamaktadır.
Hafızayı etkin kullanmak için “dinamik dizi” kullanılabilir. İstenirse dizi boyutlandırılabilir, ya da
silenebilir.
Bağlı Listeler (Linked List)
Bağlı listelerde (linked list) Şekilde görüldüğü
gibi her eleman birbirine işaretçiler ile bağlıdır.
İşaretçinin en son gösterdiği ise “nil veya null”
adı verilen boş bir değerdir. “Nil” liste sonunu
belirtir. Asıl verileri yer değiştirerek
düzenlemek
yerine,
işaretçiler
tekrar
düzenlenerek yer değiştirme işlemi hızlı bir şekilde yapılır.
• Yeni bir işaretçi tanımlayalım:
TYPE isaretciAdi= ^KayitTuru;
• Hemen tanımlamanın altında da yapımızı “KayitTuru” tanımlayalım:
KayitTuru= RECORD
Adi: String[15];
Notu: integer;
Sonraki: isaretciAdi;
END;
Pascal dilinde bağlı liste örneği
PROGRAM bagliListeler;
TYPE
isaretciAdi= ^KayitTuru; {"KayitTuru" yapısının işaretcisi}
KayitTuru= RECORD {yapı veya veri kümesi}
Adi: String [15];
Notu: integer;
Sonraki: isaretciAdi; {sonraki kayıt}
END;
VAR
Dugum: isaretciAdi;16
6
Bir dizi içindeki bir elemanı sildiğinizde, hala bellekte yer kaplayan bir boş alan oluşur. Ayrıca işe
yaramayan bir “boşluk”, programda istenmeyen hatalara neden olabilir. Bağlı listelerde ise düğüm
silmek çok kolaydır:


Düğümlerdeki işaretçileri düzenleyin
Düğümü silin
Tek bağlı listelerin dezavantajı ilk kaydı bulmanın mümkün olmamasıdır. Yani siz geri yönde
gidemezsiniz. Hep sonraki kaydın bağını sakladığımız için bu mümkün değildir. “Ali” düğümü, “Veli”
düğümünü gösteriyor, ama “Veli” düğümünün önceki düğüm ile ilgili hiçbir ipucu yoktur.
ÇiftBağlıListeler()
İki işaretçi kullanılarak önceki ve sonraki düğümlerin adres bilgileri tutulabilir.
DaireselBağlıListeler
İlk ve son düğümün işaretçileri birbirini gösterebilir.
DaireselÇiftBağlıListeler
Hem dairesellik hem de çift bağlılık özelliklerine sahip listelerdir. İlk düğümden önceki düğüm son,
son düğümden sonraki düğüm de ilk düğümdür.
7
Yığın (Stack)
Elemanlarına erişim sınırlaması olan, liste uyarlı veri yapısı (LIFO listesi – Last In Last Out). Yığını
(stack), özel tek yönlü bağlı listelere benzetebiliriz. Ekleme ve silme işlemlerini sadece listenin en
başındakiler üzerinde yapabilirsiniz. Üst üste tabaklar gibi düşünebilirsiniz. Alttaki tabaklara ulaşmak
için mecburen üstteki tabakları kaldırmak zorundasınızdır. Yeni bir tabak gelince de yığının üstüne
koyarsınız.
Yığın veri yapısı, üç önemli metodu içinde barındırır3,4:



Push: Yığına eleman eklemek için kullanılır. Eklenecek
eleman yığının en sonuna eklenir.
Pop: Yığından eleman çıkarmak için kullanılır. Çıkarılan
eleman yığının en son elemanıdır. Herhangi bir elemanı
çıkarmak için o elemandan sonra eklenen elemanların
çıkarılması gerekir.
Top: Yığının en tepesindeki bilgiyi alır ancak stackten
çıkartmaz sadece okur.
Temel
olarak stack, bir array
veya Linked List üzerine inşa edilebilirler.
Örnek olarak bir dizi üzerine inşa edilen stack için bir değişken, dizide o anda kaç değer olduğunu
tutacak ve her pop işleminden sonra bu değer azaltılırken, her push işleminden sonra arttırılacaktır.
Yığının çalışma mantığını anlatan günlük hayatta karşılaştığımız birkaç örnek5;
•
•
Bir masa üzerine üst üste yerleştirilmiş kitaplar,
Marketlerde üst üste yığılı duran konserve kutuları,
Yığına eleman ekleme ve yığından eleman çıkarma işlemlerinin algoritmaları aşağıda verilmiştir.
Yığına ekleme (push) işleminin algoritması;
Eğer (Yığın dolu ise)
“Yığın dolu” mesajını yaz
Değilse
Veriyi yığına ekle
Yığın göstericiyi (Stack Pointer) 1 artır
Yığından eleman çıkarma (Pop) işleminin algoritması;
Eğer (Yığın boş ise)
“Yığın boş” mesajını yaz
Değilse
Yığın göstericiyi (Stack Pointer) 1 azalt
Yığından veriyi sil
Kuyruk
Elemanlarına erişim sınırlaması olan, liste uyarlı veri yapısıdır (FIFO listesi – First In First Out).
Kuyruk (queue) listelerinin iki kuralı vardır:
3
http://veriyapisi.blogspot.com/2012/09/ygnstack-veri-yaps.html
http://www.bilgisayarkavramlari.com/2007/05/04/stack-yigin/
5
http://cobanoglu.wikispaces.com/file/view/yigin_kuyruk_bc.pdf
4
8


Yeni eklenen bilgiler sadece sona eklenebilir,
Silinecek bilgi sadece baştan silinebilir.
Sinema kuyruğundaki insanları düşünün, ilk giren ilk kuyruktan
çıkar. Son gelen ise son çıkar. Kuyruğa girmek isterseniz en sona
gitmeniz gerekir, biletini alan müşteri ise en başta olduğundan
kuyruktan ayrılır.
Kuyruğun çalışma mantığını anlatan gündelik hayatta karşılaştığımız
birkaç örnek;
•
•
Bir bankamatik’ten para çekmek için bekleyen insanlar,
Bir durakta otobüse binmek için bekleyen insanlar,
Örnek olarak, dizi boyutu 4 olan doğrusal bir kuyruk yapısında sırasıyla aşağıdaki işlemler
gerçekleştiğinde kuyruk yapısındaki değişimler Tablo 12.1 de gösterilmiştir.
Ön değişkeni (işaretçisi), kuyruk yapısındaki eksilmeleri (kuyruktan çıkarılabilecek ilk elemanı), Son
değişkeni (işaretçisi) ise kuyruk yapısındaki eklemeleri gösterir. Bir eleman eklendiğinde, bu eleman
son değişkeninin gösterdiği adrese yerleştirilir ve son değişkeni bir sonraki adrese kayar. Bu örnekte,
doğrusal kuyruk yapısının ilk tanımlamaları eğer ön=0 ve son=-1 ise (son<ön) son değişkeninin en son
değeri (son=dizi boyutu -1) 3 dür ve bu durum dolu kuyruk şartını oluşturur. Kuyruk yapısında
başlangıçta hiçbir eleman yoktur. Tüm programlama dillerinde kuyruk yapısı dizi kavramı ile izah
edilir. Kuyruk yapıları doğrusal (kaymalı) veya dairesel olarak oluşturulabilirler. Aşağıdaki şekilde bu
kuyruk yapılarının şekilleri gösterilmiştir.
9
Kuyruk yapısında kullanılan dizilerin belli bir dizi
boyutu kısıtlaması vardır. Bu yüzden dizinin son
elemanı, dizinin ilk elemanı ile bitişikmiş (art arta) gibi
düşünülerek işlem yapılır. Yani diziyi düz bir masa
yerine yuvarlak bir masa gibi düşünmek gerekir.
Dairesel kuyruk yapısında boş kuyrukların ilk
tanımlamasında, ön ve son değişkenleri (işaretçileri)
aynı yerdedir (eşittir). Bu yapıda da kuyruğa bir eleman
eklendiğinde son değişkeninin değeri bir artırılır. Eğer
(ön=son+1) ise dolu kuyruk şartı gerçekleşir.
Kuyruğa eleman ekleme ve çıkarma işlemlerinin
algoritmaları aşağıda verilmiştir.
Kuyruğa eleman
algoritması;
ekleme
(Enqueue)
işleminin
Eğer (Kuyruk dolu ise)
“Kuyruk dolu” mesajını yaz
Değilse
Elemanı kuyruğa ekle
Son işaretçisini 1 artır (Son=son+1)
Kuyruktan eleman çıkarma (Dequeue) işleminin algoritması;
Eğer (Kuyruk boş ise)
“Kuyruk boş” mesajını yaz
Değilse
Ön işaretçisini 1 artır. (On=on+1)
İlk indisli elemanı kuyruktan al.
Ağaç
Bağlı listeler, yığıtlar ve kuyruklar doğrusal (linear) veri yapılarıdır. Ağaçlar ise doğrusal olmayan
belirli niteliklere sahip iki boyutlu veri yapılarıdır. Ağaçlardaki düğümlerden iki veya daha fazla bağ
çıkabilir. İkili ağaçlar (binary trees), düğümlerinde en fazla iki bağ içeren (0,1 veya 2) ağaçlardır.
Ağacın en üstteki düğümüne kök (root) adı verilir.
Genellikle yapay zekâ programlarında kullanılır. Mesela bir satranç oyunu olabilir. İlk hamle en
üstteki köktür. Yapılabilecek her hamlenin ihtimalleri dallara ayrılır. Karşı oyuncunun hareketine göre
de ihtimaller değişerek dallar oluşur. En son dal “şah – mat” ile biter
Şekilde görülen ağacın düğümlerindeki bilgiler
sayılardan oluşmuştur. Her düğümdeki sol ve sağ bağ
lar yardımı ile diğer düğümlere ulaşılır. Sol (leftptr)
ve sağ (rightptr) bağlar boş ("NULL" = "/" = "\") da
olabilir. Düğüm yapıları değişik türlerde bilgiler
içeren veya birden fazla bilgi içeren ağaçlar da
olabilir.
Doğadaki ağaçlar köklerinden gelişip göğe doğru yükselirken veri yapılarındaki ağaçlar kökü yukarıda
yaprakları aşağıda olacak şekilde çizilirler. şekil 4.2'deki ağaç, A düğümü kök olmak üzere 9
10
düğümden oluşmaktadır. Sol alt ağaç B kökü ile başlamakta ve sağ alt ağaç da C kökü ile
başlamaktadır. A'dan solda B'ye giden ve sağda C'ye giden iki dal (branch) çıkmaktadır.
Çizge
Belli bir şekli olmayan bağlı listelerdir. Basitçe bir graf düğüm olarak adlandırılan noktalar ve her biri
bu noktaları veya sadece noktanın kendisini birleştiren ve ayrıt olarak adlandırılan çizgiler
topluluğudur. Örnek olarak şehirleri düğüm (vertice) ve onları bağlayan yolları ayrıt (edge) olarak
gösteren yol haritaları verilebilir.
Bir grafı tanımlamak için öncelikle düğümlerin ve ayrıtların kümesini tanımlamamız gerekir. Daha
sonra hangi ayrıtların hangi düğümleri bağladığını belirtmeliyiz. Bir ayrıt her iki ucunda da bir düğüm
olacak şekilde tanımlandığından graftaki tüm ayrıtların uç noktalarını bir düğüm ile ilişkilendirmek
gerekir. Bu nedenle, her bir e ayrıt’ı için {v1, v2} kümesi tanımlarız. Bunun anlamı e ayrıt’ının v1 ve
v2 düğümlerini bağladığıdır. v1 = v2 olabilir. {v1, v2} kümesi δ(e) ile gösterilir ve düğümler
kümesinin bir alt kümesidir.
İlişkiler için sayısal değerler atanabilir. Böyle graflara ağırlıklı graf diyoruz. İlişkilerin sayısal
değerlerine bağlantı ağırlığı denir
Yönlü ilişki içeren graflara, yönlü graf diyoruz. Yönlü ilişkileri, graflarda yönlü oklarla temsil edilir
11
Komşuluk Matrisi: Düğümlerden düğümlere olan bağlantıyı gösteren bir kare matristir.
1,
0,
ğ ,
ğ ∈
Bitişiklik Matrisi: Düğümler ile kenarlar arasındaki bağlantı ilişkisini gösteren matristir. Matrisin
satır sayısı düğüm, sütun sayısı kenar sayısı kadar olur.
1,
0,
ğ ,
ğ
Düğüm Derecesi: Düğüme bağlı toplam uç sayıdır.
12
ğ
Genellikle “sinir ağları – neural network” kurulumunda kullanılır. Beyin de bu yöntemle işlem
yapmaktadır. Her düğüm (neuron), siniri (synapses) temsil eder. Programınız karmaşıklaştıkça bu
gelişmiş yöntemleri keşfederek algoritmalarınızı yeniden şekillendireceksiniz.
13
Download