Veriden Yapıya: Veri Organizasyonunu Anlamak
Bu bölümde, veri yapılarının iç mekanizmasını inceleyerek
verinin nasıl saklandığını ve nasıl yönetildiğini öğreneceksin.
Hazır yapıları kullanmak yerine,
veri organizasyonu ve erişim mantığını adım adım simüle edeceksin.
Veri Yapısı Gerçekte Nedir? Veri → Organizasyon → Erişim
Programlama sırasında sürekli veri ile çalışırız. Ancak veriyi yalnızca saklamak yeterli değildir.
Asıl önemli olan, bu veriyi nasıl organize ettiğimiz ve ona nasıl eriştiğimizdir.
Aynı veriyi farklı şekillerde düzenlemek, işlemlerin hızını ve verimliliğini doğrudan etkiler.
Bu nedenle veri yapıları, verinin nasıl saklanacağını ve nasıl kullanılacağını belirleyen sistemlerdir.
Organizasyon MantığıBir veri yapısı, veriyi rastgele tutmaz. Belirli kurallara göre düzenler.
Bu kurallar, verinin nasıl ekleneceğini, nasıl silineceğini ve nasıl okunacağını belirler.
Örneğin bazı yapılarda veri sırayla tutulur, bazı yapılarda ise belirli bir önceliğe göre organize edilir.
Bu farklı yaklaşımlar, farklı problemlerin çözümü için optimize edilmiştir.
Davranış FarkıVeri yapıları sadece veri tutmaz; aynı zamanda belirli davranışlar sergiler.
Bu davranışlar, verinin nasıl hareket ettiğini belirler.
Örneğin bir yapı, son eklenen veriyi önce çıkarabilir; başka bir yapı ise ilk eklenen veriyi önce çıkarabilir.
Bu davranış farkı, veri yapılarının en önemli özelliklerinden biridir.
Neden Önemli?Doğru veri yapısını seçmek, algoritmanın performansını doğrudan etkiler.
Aynı problem, farklı veri yapıları kullanılarak çok daha hızlı ya da çok daha yavaş çözülebilir.
Bu nedenle veri yapıları, sadece teorik bir konu değil; gerçek dünyadaki performansın temelidir.
Unutma: Veri yapısı seçimi, çözümün kalitesini belirler.
Veri Yapıları Nasıl Çalışır? Sakla → Eriş → Güncelle
Veri yapıları dışarıdan bakıldığında sadece veri tutan yapılar gibi görünür. Ancak gerçekte bu yapılar, belirli kurallara göre çalışan sistemlerdir.
Her veri yapısı, verinin nasıl saklanacağını, nasıl erişileceğini ve nasıl güncelleneceğini tanımlar.
Bu nedenle veri yapıları, sadece bir depolama alanı değil; kontrollü bir veri yönetim mekanizmasıdır.
Saklama MantığıBir veri yapısı çalışmaya başladığında, veriyi belirli bir düzen içerisinde saklar.
Bu düzen, verinin rastgele dağılmasını engeller ve belirli bir yapı içerisinde tutulmasını sağlar.
Örneğin bazı yapılarda veri sıralı tutulurken, bazı yapılarda bağlantılar üzerinden erişilir.
Bu saklama şekli, veri yapısının nasıl davranacağını belirler.
Erişim MantığıVeriye ulaşma şekli, veri yapılarının en önemli özelliklerinden biridir.
Bazı yapılarda istediğin veriye doğrudan ulaşabilirsin, bazı yapılarda ise adım adım ilerlemen gerekir.
Bu fark, işlemlerin hızını ve performansını doğrudan etkiler.
Bu nedenle erişim mantığı, veri yapısı seçiminde kritik bir rol oynar.
Güncelleme MantığıVeri yapıları sadece veri saklamaz, aynı zamanda bu veriyi değiştirir.
Yeni veri eklemek, veri silmek veya mevcut veriyi güncellemek, her veri yapısında farklı kurallara göre gerçekleşir.
Bu işlemler sırasında yapı korunur ve veri düzeni bozulmaz.
Bu nedenle veri yapıları, veri üzerinde kontrollü değişim sağlar.
Sistemsel Bakış AçısıVeri yapılarını anlamak, onları bir kutu gibi görmek değil; içlerinde çalışan sistemi anlamaktır.
Bu bakış açısı sayesinde, bir yapının neden hızlı ya da yavaş olduğunu analiz edebilirsin.
Artık veri yapıları sadece bir kavram değil; kontrol edilebilir ve analiz edilebilir sistemlerdir.
Unutma: Bir veri yapısını anlamak, onun nasıl çalıştığını çözmektir.
Veri Yapılarının Türleri Doğrusal → Hiyerarşik → Bağlantılı
Veri yapıları, veriyi saklamak için kullanılır; ancak her yapı bunu farklı bir şekilde gerçekleştirir.
Bazı yapılar veriyi sıralı tutar, bazıları hiyerarşik bir düzen oluşturur, bazıları ise elemanlar arasında bağlantılar kurar.
Bu farklı yaklaşımlar, farklı problemlerin çözümü için geliştirilmiştir.
Bu nedenle veri yapıları, nasıl organize edildiklerine göre sınıflandırılır.
1. Doğrusal Yapılar (Linear)Bu tür yapılarda veriler, belirli bir sıraya göre dizilir.
Her eleman, bir önceki ve bir sonraki eleman ile ilişkilidir.
Veri üzerinde işlem yapmak genellikle sırayla ilerlemeyi gerektirir.
Bu kategoriye giren yapılar, en temel veri organizasyonu modellerini temsil eder.
Örnek olarak: Array, Stack ve Queue gösterilebilir.
2. Hiyerarşik Yapılar (Tree)Bu yapılarda veri, bir ağaç yapısı gibi organize edilir.
Her eleman bir üst elemana bağlıdır ve alt elemanlar oluşturabilir.
Bu yapı sayesinde veri, katmanlı bir şekilde temsil edilir.
Bu tür yapılar, özellikle arama ve organizasyon işlemlerinde kullanılır.
3. Bağlantılı Yapılar (Graph)Bu yapılarda elemanlar, birbirine bağlantılar ile bağlanır.
Her eleman, birden fazla elemana bağlı olabilir.
Bu yapı sayesinde karmaşık ilişkiler modellenebilir.
Bu tür yapılar, ağ sistemleri ve ilişki analizlerinde kullanılır.
Neden Bu Ayrım Önemli?Her veri yapısı, belirli bir problem türü için optimize edilmiştir.
Doğru veri yapısını seçmek, işlemleri daha hızlı ve verimli hale getirir.
Yanlış yapı seçimi ise, gereksiz karmaşıklık ve performans kaybına neden olabilir.
Bu nedenle veri yapılarının türlerini anlamak, doğru çözümü bulmanın ilk adımıdır.
Stack (Yığın) Veri Yapısı: Son Giren İlk Çıkar (LIFO) Push → Pop → Üstten Erişim
Stack veri yapısı, elemanları belirli bir kurala göre yönetir: son giren eleman ilk çıkar.
Bu davranış, LIFO (Last In, First Out) olarak adlandırılır.
Stack içerisinde yeni elemanlar her zaman en üste eklenir ve çıkarma işlemi de yalnızca bu üst noktadan yapılır.
Bu nedenle stack, yalnızca tek bir giriş ve çıkış noktasına sahip bir yapı olarak çalışır.
Temel İşlemlerStack veri yapısı üç temel işlem ile çalışır.
Push: Yeni bir elemanı stack’in üstüne ekler.
Pop: Stack’in en üstündeki elemanı çıkarır.
Peek: En üstteki elemanı silmeden görüntüler.
Tüm işlemler yalnızca üst eleman üzerinden gerçekleşir.
Simülasyon MantığıSimülasyon sürecinde, stack yapısını bir liste gibi düşünebiliriz.
Ancak bu listeye rastgele erişim yoktur; yalnızca son eleman üzerinden işlem yapılır.
Yeni eleman eklendiğinde, listenin sonuna eklenir.
Eleman çıkarıldığında ise, listenin sonundaki eleman alınır.
Bu yapı sayesinde, veri her zaman kontrol edilebilir bir sırada tutulur.
Nerelerde Kullanılır?Stack veri yapısı, birçok gerçek dünya probleminde kullanılır.
Örneğin: geri alma işlemleri (undo), tarayıcı geçmişi, fonksiyon çağrı yönetimi gibi sistemlerde stack mantığı kullanılır.
Bu nedenle stack, temel ama oldukça güçlü bir veri yapısıdır.
Stack simülasyonu
Stack yapısında tüm işlemler, yalnızca en üst eleman üzerinden gerçekleşir.
- Yeni eleman üstten eklenir (push)
- En üstteki eleman çıkarılır (pop)
- Üst eleman görüntülenebilir (peek)
// Stack simülasyonu
function createStack() {
let stack = [];
return {
push(value) {
stack.push(value);
},
pop() {
if (stack.length === 0) return null;
return stack.pop();
},
peek() {
return stack[stack.length - 1];
},
isEmpty() {
return stack.length === 0;
}
};
}
// Test
const myStack = createStack();
myStack.push(10);
myStack.push(20);
myStack.push(30);
console.log(myStack.peek()); // 30
Queue (Kuyruk) Veri Yapısı: İlk Giren İlk Çıkar (FIFO) Ekle → Beklet → Baştan Çıkar
Queue veri yapısı, elemanları belirli bir sıraya göre işler: ilk giren eleman ilk çıkar.
Bu davranış FIFO (First In, First Out) olarak adlandırılır.
Queue yapısında yeni elemanlar sona eklenir, çıkarma işlemi ise her zaman baştan yapılır.
Bu nedenle queue, iki uçtan çalışan bir yapı olarak düşünülebilir: biri ekleme, diğeri çıkarma noktasıdır.
Temel İşlemlerQueue veri yapısı üç temel işlem ile çalışır.
Enqueue: Yeni elemanı kuyruğun sonuna ekler.
Dequeue: Kuyruğun başındaki elemanı çıkarır.
Front: Başta bulunan elemanı silmeden görüntüler.
Tüm akış, sırayı koruyacak şekilde ilerler.
Simülasyon MantığıSimülasyonda queue yapısını bir liste gibi düşünebiliriz, ancak bu listeye erişim iki uçtan gerçekleşir.
Yeni elemanlar listenin sonuna eklenir.
Eleman çıkarıldığında ise listenin başındaki eleman alınır.
Bu yapı sayesinde, veriler geliş sırasına göre işlenir.
Nerelerde Kullanılır?Queue veri yapısı, sıra mantığının önemli olduğu sistemlerde kullanılır.
Örneğin: görev planlama sistemleri, yazıcı kuyrukları, işlem sıralama yapıları gibi alanlarda yaygındır.
Bu nedenle queue, veri akışını düzenlemek için kritik bir yapıdır.
Queue simülasyonu
Queue yapısında veri, giriş sırasına göre işlenir.
- Elemanlar sona eklenir (enqueue)
- Elemanlar baştan çıkarılır (dequeue)
- İlk eleman görüntülenebilir (front)
// Queue simülasyonu
function createQueue() {
let queue = [];
return {
enqueue(value) {
queue.push(value);
},
dequeue() {
if (queue.length === 0) return null;
return queue.shift();
},
front() {
return queue[0];
},
isEmpty() {
return queue.length === 0;
}
};
}
// Test
const myQueue = createQueue();
myQueue.enqueue(10);
myQueue.enqueue(20);
myQueue.enqueue(30);
console.log(myQueue.front()); // 10
console.log(myQueue.dequeue()); // 10
console.log(myQueue.dequeue()); // 20
Linked List (Bağlantılı Liste): Node Tabanlı Veri Yapısı Node → Bağlantı → Zincir
Linked List veri yapısı, veriyi sıralı olarak tutar; ancak bunu bir array gibi index üzerinden yapmaz.
Bunun yerine her eleman, bir sonraki elemana işaret eden bir yapı içerir.
Bu yapı sayesinde veri, birbirine bağlı düğümler (node) şeklinde saklanır.
Bu nedenle linked list, veriyi indeksle değil, bağlantılarla yöneten bir yapı olarak çalışır.
Node YapısıLinked list içerisindeki her eleman bir node olarak adlandırılır.
Bir node iki temel parçadan oluşur: veri ve bir sonraki node’a referans.
Bu referans sayesinde, her node bir sonrakine bağlanır ve zincir benzeri bir yapı oluşur.
Listenin ilk elemanı başlangıç noktasıdır ve tüm yapı buradan takip edilir.
Erişim MantığıLinked list içerisinde bir elemana ulaşmak için, başlangıçtan itibaren ilerlemek gerekir.
Yani doğrudan erişim yoktur; her node sırayla ziyaret edilir.
Bu durum, erişim işlemlerini daha yavaş hale getirebilir.
Ancak bu yapı, veri ekleme ve silme işlemlerinde büyük avantaj sağlar.
Simülasyon MantığıSimülasyonda her node, bir nesne gibi düşünülebilir.
Bu nesne, kendi verisini ve bir sonraki node’un referansını tutar.
Yeni bir node eklendiğinde, mevcut bağlantılar güncellenir.
Bu yapı sayesinde, veri fiziksel olarak taşınmadan bağlantılar üzerinden yönetilir.
Neden Önemli?Linked list, dinamik veri yönetimi için önemli bir yapıdır.
Özellikle veri sık sık eklenip çıkarılıyorsa, array’e göre daha verimli olabilir.
Bu nedenle linked list, veri organizasyonu konusunda farklı bir bakış açısı sunar.
Linked List simülasyonu
Linked list yapısında her eleman, bir sonraki elemana bağlıdır.
- Her eleman bir node’dur
- Node veri ve bağlantı içerir
- Bağlantılar zincir oluşturur
- İşlemler bağlantılar üzerinden yapılır
// Linked List simülasyonu
function createLinkedList() {
let head = null;
function createNode(value) {
return {
value: value,
next: null
};
}
return {
append(value) {
const newNode = createNode(value);
if (!head) {
head = newNode;
return;
}
let current = head;
while (current.next) {
current = current.next;
}
current.next = newNode;
},
print() {
let current = head;
while (current) {
console.log(current.value);
current = current.next;
}
}
};
}
// Test
const list = createLinkedList();
list.append(10);
list.append(20);
list.append(30);
list.print();
// 10 → 20 → 30
Tree (Ağaç Yapısı): Hiyerarşik Veri Organizasyonu Root → Child → Traversal
Tree veri yapısı, veriyi doğrusal bir sırada tutmaz. Bunun yerine katmanlı ve hiyerarşik bir yapı oluşturur.
Bu yapı sayesinde her eleman, belirli bir üst elemana bağlıdır ve altında başka elemanlar barındırabilir.
Bu nedenle tree, veriyi ilişkisel ve hiyerarşik olarak organize eden bir sistemdir.
Temel Yapı: Root ve ChildTree yapısının başlangıç noktası root olarak adlandırılır.
Root, yapının en üstünde bulunur ve tüm diğer elemanlar bu noktadan dallanır.
Root’tan çıkan her bağlantı, bir child (alt eleman) oluşturur.
Bu child elemanlar, kendi alt elemanlarını oluşturabilir ve yapı bu şekilde büyür.
Böylece veri, ağaç benzeri bir yapı içerisinde organize edilir.
Traversal (Gezinme) MantığıTree yapısında veriye ulaşmak için, belirli bir gezme (traversal) yöntemi kullanılır.
Bu süreçte sistem, node’lar arasında belirli bir sıraya göre ilerler.
En yaygın traversal yöntemleri şunlardır:
Pre-order: Önce mevcut node, sonra alt node’lar
In-order: Sol → mevcut → sağ
Post-order: Önce alt node’lar, sonra mevcut node
Bu yöntemler, verinin farklı şekillerde işlenmesini sağlar.
Simülasyon MantığıSimülasyonda her node, bir değer ve child listesi içerir.
Bu child listesi sayesinde, node’lar arasında hiyerarşik bağlantılar kurulur.
Gezinme işlemleri, bu bağlantılar üzerinden gerçekleştirilir.
Bu yapı sayesinde, veri sadece saklanmaz; aynı zamanda ilişkisel olarak organize edilir.
Neden Önemli?Tree yapıları, gerçek dünyadaki birçok sistemin temelini oluşturur.
Örneğin: dosya sistemleri, organizasyon şemaları, kategori yapıları gibi sistemler tree mantığı ile çalışır.
Bu nedenle tree, veri organizasyonunun en güçlü modellerinden biridir.
Tree simülasyonu
Tree yapısında veri, hiyerarşik bir yapı içerisinde organize edilir.
- Root başlangıç noktasıdır
- Her node child node’lar içerebilir
- Traversal ile tüm yapı gezilir
// Tree simülasyonu
function createNode(value) {
return {
value: value,
children: []
};
}
// Tree oluştur
const root = createNode(1);
const child1 = createNode(2);
const child2 = createNode(3);
root.children.push(child1, child2);
child1.children.push(createNode(4));
child1.children.push(createNode(5));
child2.children.push(createNode(6));
// Pre-order traversal (DFS)
function traverse(node) {
console.log(node.value);
for (let child of node.children) {
traverse(child);
}
}
// Çalıştır
traverse(root);
// 1 → 2 → 4 → 5 → 3 → 6
Graph (Graf): Çok Yönlü Bağlantı ve İlişki Modeli Node ↔ Edge ↔ Traversal
Graph veri yapısı, veriyi ne sadece sıralı (linear) bir şekilde, ne de hiyerarşik (tree) bir yapı içerisinde tutar.
Bunun yerine elemanlar arasında çok yönlü ve serbest bağlantılar kurar.
Bu yapı sayesinde her node, birden fazla node ile doğrudan bağlantı kurabilir.
Bu nedenle graph, karmaşık ilişkileri modellemek için kullanılan en güçlü veri yapılarından biridir.
Temel Yapı: Node ve EdgeGraph veri yapısı iki temel bileşenden oluşur: node (düğüm) ve edge (bağlantı).
Node, veriyi temsil eder; edge ise node’lar arasındaki ilişkiyi tanımlar.
Bir node, birden fazla edge aracılığıyla farklı node’lara bağlanabilir.
Bu yapı sayesinde veri, ağ (network) şeklinde organize edilir.
Traversal (Gezinme) MantığıGraph yapısında veriye ulaşmak için, node’lar arasında gezilmesi gerekir.
Bu gezme işlemi traversal olarak adlandırılır ve iki temel yöntem ile gerçekleştirilir:
DFS (Depth-First Search): Bir dal boyunca mümkün olduğunca derine iner.
BFS (Breadth-First Search): Önce aynı seviyedeki node’ları ziyaret eder.
Bu yöntemler, graph üzerinde farklı keşif stratejileri sunar.
Simülasyon MantığıSimülasyonda graph yapısı, genellikle bir adjacency list (komşuluk listesi) ile temsil edilir.
Bu listede her node, kendisine bağlı node’ların bir listesini tutar.
Traversal işlemleri sırasında, ziyaret edilen node’lar takip edilir ve tekrar ziyaret edilmesi engellenir.
Bu yapı sayesinde, graph üzerinde kontrollü ve sistemli bir keşif yapılır.
Neden Önemli?Graph veri yapısı, gerçek dünyadaki birçok karmaşık sistemin temelini oluşturur.
Örneğin: sosyal ağlar, harita sistemleri, öneri algoritmaları ve ağ analizleri graph yapısı ile modellenir.
Bu nedenle graph, veri yapıları arasında en esnek ve en güçlü modellerden biridir.
Graph simülasyonu
Graph yapısında her node, birden fazla node ile bağlantı kurabilir.
- Node veri noktasıdır
- Edge bağlantıyı temsil eder
- Traversal ile yapı keşfedilir
- Visited kontrolü tekrarları engeller
// Graph simülasyonu (Adjacency List)
function createGraph() {
const graph = {};
function addNode(node) {
if (!graph[node]) {
graph[node] = [];
}
}
function addEdge(a, b) {
graph[a].push(b);
graph[b].push(a); // undirected graph
}
function dfs(start, visited = new Set()) {
if (visited.has(start)) return;
console.log(start);
visited.add(start);
for (let neighbor of graph[start]) {
dfs(neighbor, visited);
}
}
return {
addNode,
addEdge,
dfs,
graph
};
}
// Test
const g = createGraph();
g.addNode("A");
g.addNode("B");
g.addNode("C");
g.addNode("D");
g.addEdge("A", "B");
g.addEdge("A", "C");
g.addEdge("B", "D");
g.dfs("A");
// A → B → D → C
BFS (Breadth-First Search): Genişlik Öncelikli Keşif Seviye Seviye → Queue → Yayılım
BFS (Breadth-First Search), graph üzerinde gezinirken derine inmek yerine geniş alana yayılmayı tercih eder.
Bu yaklaşımda sistem, önce mevcut node’un tüm komşularını ziyaret eder.
Daha sonra bir sonraki seviyeye geçerek aynı işlemi tekrar eder.
Bu nedenle BFS, veriyi katman katman keşfeden bir algoritmadır.
Queue KullanımıBFS algoritmasının temelinde queue veri yapısı bulunur.
Ziyaret edilecek node’lar, sırayla queue içerisine eklenir.
Her adımda queue’nun başındaki node alınır ve işlenir.
Bu yapı sayesinde, node’lar giriş sırasına göre işlenir.
Traversal MantığıBFS sırasında her node, yalnızca bir kez ziyaret edilir.
Bu nedenle ziyaret edilen node’lar takip edilir ve tekrar eklenmeleri engellenir.
Bu kontrol, sonsuz döngü oluşmasını önler.
Bu süreç, tüm node’lar keşfedilene kadar devam eder.
Neden Önemli?BFS algoritması, en kısa yol problemleri gibi birçok alanda kullanılır.
Çünkü BFS, hedef node’a en kısa adım sayısı ile ulaşmayı garanti eder.
Bu nedenle BFS, graph algoritmaları içerisinde kritik bir yere sahiptir.
BFS simülasyonu
BFS algoritması, node’ları sırayla ve katman katman işler.
- Queue veri yapısı kullanılır
- Komşular sırayla eklenir
- İlk giren node önce işlenir
- Visited kontrolü yapılır
// BFS simülasyonu
function bfs(graph, start) {
const visited = new Set();
const queue = [start];
visited.add(start);
while (queue.length > 0) {
const node = queue.shift();
console.log(node);
for (let neighbor of graph[node]) {
if (!visited.has(neighbor)) {
visited.add(neighbor);
queue.push(neighbor);
}
}
}
}
// Test
const graph = {
A: ["B", "C"],
B: ["A", "D"],
C: ["A"],
D: ["B"]
};
bfs(graph, "A");
// A → B → C → D