MIT503 Veri Yapıları ve algoritmalar Veri Yapılarına Giriş Y. Doç. Yuriy Mishchenko
Veri yapıları ve veri tipleri Ders planı Neden veri yapıları Soyut veri yapıları ve uygulamaları Basit veri yapıları (sayılar, karakterler, diziler, matrisler) Bileşik/ileri veri yapıları (koleksiyonlar, haritalar, yığunlar, kuyruklar, bağlantılı listeler, hash tabloları)
Neden veri yapıları? Algoritma, bir matematik problemin çozümünün planıdır Algoritmalar, bir talimat listesiyle belirlenir ve birçok adım içerebilir Adımlar, algoritmanın durumunu güncelleştirir
Neden veri yapıları? Böyle çalışan hesaplamalara sonlu durum makinesi denir Alan Turing, Konrad Zuse, John von Neumann tarafından 1930-1950 yılları arasında geliştirilen kavramdir; hesaplama teoresi denir Sonlu durum mimarisi, Von Neumann mimarisi, Turing makinesi denebilir Modern bilgisayarların hepsi Von Neumann mimarisini kullanır ve Turing makinesilerdir
Von Neumann mimarisi Von Neumann mimarisi Bir program ve bir durum/veriler içerir Program, makinenin talimat listesidir Veri, makinenin durumunu tanımlar Talimatlar, makinenin durumunu güncelleştirmeyi çalışır Son talimatta makinenin durumu çözülecek problemin çözümüne eşit olmasını isteriz
Talimatları çalıştırırken makinenin durumu değişir Von Neumann mimarisi Talimatlar program F C A A B D E A B E durum problemin koşulu hesaplama sonucu Talimatları çalıştırırken makinenin durumu değişir
Veri yapıları C Veri yapıları nerede bu resime gelir? Veri yapıları, makinenin durumunu temsil eder Ayrıca veriler, algoritmanın durumunun temsile göre bir yapısı alır Matematiksel algoritmalar için veri yapıları matematiksel yapılarına çok benzer şekildedir Veri yapıları, verinin soyut özelliklerine göre belirli bir uygunlaması gerekir
Veri yapıları Veri yapıları için, biz soyut tanımı ve belirli uygulamasını ayrımı yaparız Soyut tanımı, veri yapısını ve onun genel özelliklerini tanımlamalı: Veri yapısı neyi temsil eder ? Veri yapısı hangi operasyonlara sahip olmalı ? Uygulanması, bir programlama dili yada bir algoritma şeklinde gerçekleşmesini tanımlamalı C
Basit veri yapıları En basit veri yapıları, matematiksel sayılardır
Basit veri yapıları Tamsayılar Toplama, çıkarma, çarpma, ve bölme operasyonları sağlar Daha büyük, daha küçük ve eşitlik operasyonlarını özer Önceki ve sonraki ardışıklık operasyonları saglar Programlama dillerinde “kesin” bir veri tipidir: Numaraları kesin olarak temsil eder – (int)2430, 2430 demektir (gerçekten) Programlama dillerinde byte, short, int, long veri tipları ile genellikle uygulanır Byte – 8 bit (1 byte), 0’dan 255’e bütün numaraları temsil eder Short – 16 bit (2 byte), 0’dan 65 535’e bütün numaraları temsil eder Int – 32 bit (4 byte), 0’dan 4 294 967 296’e numaraları temsil eder Long – 64 bit (8 byte), 0’dan 18 446 744 073 709 551 616’e temsil eder Hem işaretli hem de işaretsiz olabilir
Basit veri yapıları Gerçek sayılar Toplama, çıkarma, çarpma, ve bölme operasyonları sağlar Daha büyük, daha küçük ve eşitlik operasyonları sağlar Önceki, sonraki ardışıklık operasyonları yok Programlama dillerinde “kesin” bir veri tipi değildir: Numaraları yaklaşık olarak temsil eder – (float)2,4351 ≈ 2,44 “Mantis” ve “üs” kullanılır: 2.4351E15, 2.4351*1015 demektir; 2. 4351’e mantis denir ve 15’e üs denir Programlama dillerinde normalde float veya double veri tiplerle uygulanırlar Float – 32 bit (4 byte) bütün sayıları 3.4E38’e kadar Double – 64 bit (8 byte) bütün sayıları 1.8E308’e kadar Sadece işaretli sayıları belirtebilir
Basit veri yapıları Boolean (mantıksal) sayıları Karakterler Sadece 0 (yanlış) veya 1 (doğru) değerlerinde olabilir OR, AND, NOT, eşitlik operasyonları sağlar Normalde, mantiksal işlemler için kullanılır Karakterler Metinler temsil etmek için kullanılır Metinler, karakterlerin dizileridir Programlama dillerinde genellikle byte veya short tamsayı tipleri kullanılır Diziler içinde kullanılır, böylece metinleri temsil eder
Bileşik veri yapıları Diziler Programlamada çok önemli bir veri yapısıdır Sayıların veya nesnelerin koleksiyonları temsil eder Dizinin üyesi koyma, alma, ve arama operasyonlarını var Tipik olarak anahtarlı depolama sağlar Üyeleri koyma ve alma için anahtarlar kullanılır Tipik notasyon: “dizi[anahtar]=değer;” 1 2 3 4 5 6 7 8 anahtarlar a 123 b Yuri ders 3.5 503 ttt içerilen nesneler
Bileşik veri yapıları Dizilerin programlamada uygulanması 0-terminatörlü uygulanması C ve C++’nın zamanlarından bugüne kadar çok popülar bir opsiyon ama birçok güvenlik problem oluşturur; Dizinin boyutu belirli değil, Dizinin sonu özel bir sayı/karakter ile belirtilir (0-terminatör) Dizi, bazı durumda bilgisayarın belleğindeki yanındaki veriler ve bile programın kodu üstüne gelebilir (yürütme hatası) Birçok bugünkü güvenlik sorunların ana nedeni budur terminatör
Bileşik veri yapıları Dizilerin programlamada uygulanması Modern programlamada boyut belirteci alan dizi uygulanmaları kullanılır Birinci pozisyonda dizinin boyutu açıkça belirtilir Daha çok güvenli (yürütme hatası olamaz) 9 boyut belirteci
Bileşik veri yapıları Dizilerin programlamada uygulanması Diziler önceden tahsis edilen ve dinamik olarak tahsis edilen türleri Önceden tahsis edilen diziler için bilgisayarın belleği programın çalıştırmasından önce belirtilmelidir Dinamik olarak tahsis edilen diziler için bilgisayarın belleği programın çalıştırması zamanında (ne zaman ihtiyaç varsa) verilebilir
Bileşik veri yapıları A[][] = Matrisler İki üç boyutlu dizilerdir (sadece) 2 1 3 5 A[][] =
Bileşik veri yapıları A[][] = Seyrek matrisler Seyrek matrisler, çoğunlukla 0 içeren matrislerdir Seyrek matrisler belirtmek için sadece sıfırdan farklı sayılar bir listede depolanabilir Daha ekonomik: daha az bilgi bilgisayarın belleğinde depolamak gerekir 2 1 3 5 A[][] =
İleri veri yapıları Basit veri yapıları matematiksel sayılar temsil eder Tipik problemlerin çözümleri için çoğunlukla yeterlidir Daha ileri veri yapıları kolleksiyonları uygularlar Bir kolleksiyon, matematiksel kümeyi temsil eder Küme matematiğin en temel bir kavramdır, ve bilgisayar biliminde de çok önemlidir Kümeler, haritalar, yığınlar, kuyruklar, listeler, veri ağaçlar, graflar veri yapıları için bir vakıf sağlar
İleri veri yapıları Küme veri yapısı Normal matematiksel küme Nesnenin üyeliği operasyonu (nesne kümenin üyesi mi ?) Nesneyi kümeye ekleme operasyonu Nesneyi kümeden çıkartma operasyonu Yineleyici (iterator) nesnesi/özelliği (kümenin bütün nesneleri almak için iterator/yineleyici tekrar tekrar çağırılabilir) Boyut nesnesi/özelliği (kümenin boyutu) Programlama dillerinde her zaman dinamik veri yapısıdır – sürekli değiştirme ve güncelleştirme sağlamalı
İleri veri yapıları Fonksiyon (Map; Harita) Matematiksel fonksiyonu temsil eder (x → f(x)); bir parametreden bir sonuca fonksiyon haritası Parametrenin uygun olmasını kotrol etmek Sonuç mümkün olabileceğini kontrol etmek Bütün uygun parametrelerin kolleksiyonu göstermek Bütün mümkün sonucların kolleksiyonu göstermek Belirtilmiş parametre için sonucu hesaplamak Yeni bir parametre → sonuç bağlantısı belirtmek
İleri veri yapıları Yığınlar Yığınlar (stack) özel veri yapıları; sıralı girdi depolama için kullanılır Sıralı girdi dizi, metin satırı, kaset girdi demektir Last-İn-First-Out (LİFO) ve First-İn-First-Out (FİFO yada kuyruk yada queue) iki tür var girdi v e r i y a p ı
İleri veri yapıları Last-in-first-out (LİFO) ve First-in-first-out (FİFO) yığınların farkı girdi 1 1 girdi 2 LİFO 2 1 girdi 3 3 2 1 çıktı 3 2 1 1 girdi 1 2 girdi 1 2 FİFO 3 girdi 1 2 3 1 2 3 çıktı
İleri veri yapıları Genellikle yığınlar sonlu bellektir Kısmen dolu yığınlara “underflowed” (terim) denir Dolu üzerinde yığınlara “overflowed” (terim) denir “Stack overflow” yaygın bir güvenlik hatası ve açığıdır 0-terminatörlü diziler gibi, yığın boyutunu aşsa, bilgisayar belleğindeki diğer veriler yada program kodu üstüne yazdırmaya yol açabilir; Bu bir yürütme hatası ve hakkerlere açığıdır s t a c k sys veri hata yığın deposu yürüten kod (haker saldırısı) “stack overflow” yürüten kodu uzerinde habis veriyi yazabilir
İleri veri yapıları Yığınların operasyonları PUSH – (itmek) nesne eklemek POP – nesne alıp silmek EMPTY – yığında nesneler olmasına kontrol etmek (bu “boş mu ?” sorusuna cevap verir) EMPTY PUSH 1 1 PUSH 2 2 1 PUSH 3 3 2 1 POP 3 2 1
İleri veri yapıları Kuyruklar Kuyruklar (queue) yığınlar gibi sıralı girdi için kullanılır FİFO yığınlarına eşit ama farklı terimleri kullanır: “push” ve “pop” yerine “queue” ve “dequeue” kullanır Öncelikli kuyruklar (priority queues) önemli özel bir veri yapısı Nesnelerin hepsi için bir “öncelik” atanır “Queue”/”Push” önceki gibi çalışır “Dequeue”/”Pop”, en yüksek öncelikle nesneyi verir
Daha yüksek önceliğe nesnesi önüne gidiyor İleri veri yapıları Öncelikli kuyruk öncelik nesne queue (a,1) a queue (b,2) kuyruk a b queue (c,0) c a b dequeue b c a Daha yüksek önceliğe nesnesi önüne gidiyor
İleri veri yapıları Öncelikli kuyrukların operasyonları ADD – yeni nesne eklemek POLL – nesne alıp silmek PEEK – nesne silmeden almak EMPTY – kuyrukta nesneler olmasına kontrol etmek (bu “boş mu ?” sorusuna cevap verir)
İleri veri yapıları Bağlantılı listeler Bağlantılı listeler (linked lists) programlamada çok önemli veri yapısıdır Birçok ileri veri yapıları için bağlantılı listeler ya da karma tablolar (hash tables) kullanılır
İleri veri yapıları Bağlantılı listenin ana fikri: nesne nesne nesne Her nesnede sonraki nesneye işaretçi var işaretçiler İşaretçiler takip eden bütün listesi bilgisayar belleğinden çekilebilir Her nesnede sonraki ve önceki nesneye işaretçi var (daha hızlı arama sağlar, iki yönlü arama) işaretçiler
İleri veri yapıları Bağlantılı listelerin operasyonları Arama – listede bir nesne bulmak; listenin birinci nesnesiyle başlayınca gereken nesneyi bulmaya kadar işaretçileri takip ederiz Ekleme – yeni nesne eklemek; yeni nesne listenin sonuna ekleyip ona yeni işaretçi yapıyoruz Silme – var olan nesne silmek; silme için belirtilen nesneyi silip yanındaki işaretçileri güncelleştirmeliyiz
İleri veri yapıları Bağlantılı liste ekleme ve silmesi Ekleme nesne nesne nesne Yeni nesne sonuna ekleyip bir daha işaretçi oluşturuyoruz işaretçiler Silme nesne nesne nesne Belirtilen nesneyi silip yanındaki işaretçileri güncelleştiriyoruz
İleri veri yapıları Karma (Hash) Tabloları Hash tabloları programalamada çok önemli veri yapısıdır Hash tabloları, hızlı erişim anahtarlı dizileridir Bağlantılı listeler gibi, ileri programlamada birçok veri yapıların uygulanması için temel bir yapısıdır
İleri veri yapıları Hash tablosu nedir? Veri deposu (bilgisayar belleği) Anahtar - nesne N 1. “Anahtar” kullanarak bilgisayar belleğinde depolama adresini hesaplarız – “bellekte depo adresi = H(anahtar)” H’ye “hash fonksiyon” denir Ana özelliği – herhangi farklı bir anahtar için büyük ihtimalle farklı bir adres verecek (adreslerin benzersizliği)
İleri veri yapıları Hash tablosu nasıl çalışıyor ? Veri deposu (bilgisayar billeği) Anahtar - nesne a c b e g h d f x N m l ı z n k 2. Hash fonksiyonu farklı nesneleri farklı depolama adresleri vermelidir İkinci özelliği – hash fonksiyonu bütün kullanılabilir adresleri büyük ihtimalle kullanacak (adreslerin düz dağıtlanması)
İleri veri yapıları Hash tablosu nasıl çalışıyor ? Veri deposu (bilgisayar billeği) Anahtar ? a c b e g h d f x N m l ı z n k 3. Bellekten nesne almak için, “anahtar”a göre depolama adresini hesaplayıp nesne hemen hemen alabiliriz Nesne almak için hash tabloları tek operasiyon gerekir – anahtara göre adresini hesaplamak. Bunun için N nesneli diziden bir nesne almak için O(1) operasiyon lazım. Genel N nesneli dizi yada bağlantılı listeler için ortalama O(N) operasiyon gerekir.
Gerçek hayatta karşılaşılan anahtarlar AZ var !!! İleri veri yapıları Hash fonksiyonu, mümkün anahtarların hepsini daha küçük bellek adreslerin kümesine yansıtmalı Örneğin, anahtar uzun metinler olabilirler; 10 karakterli metin zaaten 6E17 olanakları yapar; bilgisayarın belleğin boyutu sadece 1GB=1E9 bit’tir ? Mümkün anahtarlar - ÇOK Kullanılabilir bellek adresleri - AZ Gerçek hayatta karşılaşılan anahtarlar AZ var !!! Hash fonksiyonu anahtaradres
Gerçek hayatta karşılaşılan anahtarlar AZ var !!! İleri veri yapıları Genellikle, bütün mümkün anahtarlar gerçek hayatta karşılaşılamaz; Bunun için gerçek sorun yok, ve böyle “hash” haritaları yapılabilir. Ancak zor bir matematiksel problemdir. Mümkün anahtarlar - ÇOK Kullanılabilir bellek adresleri - AZ Gerçek hayatta karşılaşılan anahtarlar AZ var !!! Hash fonksiyon anahtaradres
Not: tipli ve tipsiz veri yapıları Tipli ve tipsiz kolleksiyonlar Kolleksiyonda genel türlü nesneler içerilebilirse (örneğin aynı kolleksiyonda tamsayılar, gerçek sayılar, karakterler, vb olablirse), böyle kolleksiyona tipsiz denir Tipli kolleksiyonda sadece belirli tipten nesneler içerilebilir Örneğin: Kolleksiyonda içerilen nesnelerin hepsi tamsayı olmalı Programlamada bunun gibi ifadeler bazen görülebilir Set<String> - sadece karakterler (String) içeren bir küme (Set) Map<String,Integer> - sadece karakterlerden (String) tamsayılara (Integer) bir harita (fonksiyon) Hash<String,String> - sadece karakterlerden (String) karakterlere (String) bir hash tablosu (Hash) Bir yerde görecekseniz, demek bu.
Basit ve ileri veri yapıları Algoritma/programlama daki veri yapıları genellikle matematiksel yapılarına yakın Basit veri yapıları normal sayıları temsil eder Basit sorunlar/algoritmalar için uygundur Bileşik veri yapıları diziler ve matrisleri temsil eder Biraz daha ilerli sorunlar/algoritmalar da yardım ederler İleri veri yapıları nesnelerin kolleksiyonları temsil eder Çok ilerli veya veri işleme yapan algoritmalarda kullanılır Bağlantılı listeler ve hash tabloları önemli veri yapılarıdır ve programlamada birçok veri yapılarının uygulanması için temel araçlardır Veritabanları, ağaçlar, graflar, vb ileri veri yapıları için kullanılır