Bir algoritmanın sahip olması gereken temel özellikleri: Girdi ve Çıktı Bilgisi: Algoritmalarda girdi ve çıktı bilgileri olmalıdır. Girdi bilgisi algoritmaya dışarıdan verilirken, çıktı bilgisi ise algoritma içerisinde üretilir. Bu bilgiler, algoritma için tanımlı veri kümesine ait olmalıdır. Açıklık: Algoritmayı oluşturan adımlar doğru ve kesin bir şekilde tanımlanmalıdır. Doğruluk: Farklı girdi bilgileri ile çalışabilen algoritmalar, her girdi için doğru bir çıktı üretmelidir. Sonluluk: Algoritmaların daima bir sonu olmalıdır. Girilen veri boyutundan bağımsız bir şekilde, algoritma adımları farklı bir aşamaya geçebilmeli veya sonlanmalıdır. Algoritma adımları gerçekleştirilirken, algoritma sonsuz döngüye girmemelidir. Verimlilik: Algoritmayı oluşturan adımlar, yapılan iş için kabul edilebilir bir süre içerisinde tamamlanmalıdır. Genellik: Bir algoritma, aynı türdeki problemlerin hepsine uygulanabilir olmalıdır. * Banka hesabımızdan nakit para temin etmemizi sağlayan ATM’den para çekme algoritmasının adımları: Hesabın bulunduğu bankaya ait bir ATM’ye gidilir. ATM önündeki bekleme kuyruğunu girilir. İşlem sırası gelene kadar kuyrukta beklenir. İşlem sırası geldiğinde, bankamatik kartı ATM’nin kart haznesine takılır. Bankamatik kartına ait parola girilir ve “Giriş” tuşuna basılır. Para çekme menüsüne erişilir. Çekilecek nakit tutarı belirlenir ve “Devam” tuşuna basılır. ATM, bankamatik kartını kart haznesinden çıkartır. Bankamatik kartı ATM’den geri alınır. ATM, nakit parayı para haznesine doldurur. Nakit para ATM’den alınır. Para çekme işlemi tamamlanarak, işlem kuyruğundan çıkılır. ATM’den para çekme algoritmasının yukarıda gösterilen adımlarında, bir kişinin para çekmek için yapması gerekenler listelenmiştir. Bu örnek doğrultusunda, bir algoritmayı oluşturan temel bileşenlerin, yapılacak işe yönelik açıklama ve işin yapılmasında izlenecek adımlar olduğu söylenebilir. Açıklama kısmında işin tanımı yapılır ve işle ilgili detaylar bildirilir. Adımlar kısmında ise işin başlangıcından sonuna kadar takip edilecek işlemler belirtilir. * * Algoritma Gösterim Yöntemleri: Algoritmaların tanımlanmasında ve gösteriminde kullanılan başlıca yöntemler: Bu yöntemlerden başlıcaları konuşma dili ile gösterim, akış şeması ile gösterim ve sözde kod (pseudocode) ile gösterimdir. * Konuşma dili ile algoritmalar gösterme: Bir algoritmanın açıklaması ve algoritmada yer alan adımlar, konuşma dili kuralları çerçevesinde ifade edilebilir. Bu gösterim yönteminde, algoritma açık ve kesin bir dille tanımlanır. Algoritmada yer alan adımlar liste halinde yazılır. Açık ve kesin bir dille algoritmasından sonra algoritmada yer alan adımların liste halinde yazıldığı algoritma gösterim yöntemine konuşma dili yöntemi denir. * Akış şeması ile algoritma gösterme: Akış şeması, algoritmaların gösteriminde kullanılan faydalı bir yöntemdir. Bir akış şemasında algoritma adımlarını ifade eden kutucuklar, adımlar arası geçişleri gösteren oklar, karar verme mekanizmaları olarak kullanılan şekiller bulunabilir. Akış şeması, bir algoritmanın görsel halini ifade eder. Görsellik, algoritmaların daha kolay anlaşılabilmesine olanak sağlar. Programcılar ve çözümleyiciler tarafından yaygın olarak kullanılan akış şemalarını oluşturmak için birçok farklı çizim yazılımı bulunmaktadır. Veri Akışı Çizimi: Sisteme bütün olarak bakmayı sağlayan ve sistemin nasıl çalıştığını gösteren analiz yönetimidir. * Sözde kod ile algoritma gösterme: Sözde kod (pseudocode), bir algoritma veya program oluşturulurken kullanılan, konuşma diline benzer bir yapıya sahip, programlama dillerinin detaylarından uzak bir anlatım şeklidir. Algoritmaların sözde kod ile gösterimi, oldukça yaygın ve etkili bir yöntemdir. Sözde kodlarda bir programlama diline benzeyen ifadeler kullanılsa da bu ifadelerin bilgisayar tarafından anlaşılması mümkün değildir. Sözde kodlar, programlama mantığı ile konuşma dili cümlelerinin harmanlanma- sından meydana gelir ve herkes tarafından rahatlıkla anlaşılabilir. Sözde kodu okuyan bir kişi, programlama dillerinin detaylarına takılmadan, algoritmanın çalışma mantığını kavrayabilir. * * Algoritmaların Sınıflandırılması Özyinelemeli algoritması: Kendisini doğrudan veya dolaylı olarak çağıran algoritmalara özyinelemeli algoritma adı verilir. Bu algoritmalarda, problemler daha küçük ve basit parçalara indirgenir. Küçük parçalar için oluşturulan çözümlerin birleştirilmesiyle ana problemin çözümü elde edilir. * Geri izlemeli algoritmaları (Backtracking Algorithms): Geri izlemeli algoritmalar, genellikle optimizasyon problemlerinde kullanılan, problem çözümünde tüm olasılıkları deneyen algoritmalardır. Bu algoritmalarda çözüm kademeli şekilde oluşturulur. Algoritma çözüm aşamasında ilerlerken, olası çözüm yollarının hepsini deneyerek bir sonraki adıma geçmeye çalışır. Algoritmanın denediği çözüm yolundan sonuç alınamazsa, algoritma bir önceki adımda bulunan diğer olası çözüm yollarına geri döner. -Sudoku: 9 x 9’luk bir tablonun her satır ve sütununda 1’den 9’a kadar sayıların olması gerekmektedir. Bazı değerlerin dolu olarak verildiği bulmaca nasıl çözülür? -Sekiz Vezir Problemi: Sekiz vezir, bir satranç tahtasına birbirlerine hamle yapamayacak şekilde nasıl yerleştirilir? -Sırt Çantası Problemi: Elimizde kapasitesi belirli bir sırt çantası, ağırlığı ve değeri belirli nesneler vardır. Sırt çantasına hangi nesneler doldurulduğunda, çantaya konan nesnelerin toplam değeri en fazla olur. Sırt çantası problemi, kapasitesi belirli bir sırt çantasına, ağırlıkları ve değerleri bilinen nesneleri toplam değer en fazla olacak şekilde doldurmayı sorgulayan bir optimizasyon problemidir. * Böl ve yönet algoritması (Divide and Conquer Algorithms): Böl ve yönet algoritmaları, problemlerin mümkün olan en küçük alt parçalara ayrıldığı, her bir alt parçanın diğerlerinden bağımsız şekilde çözüldüğü algoritmalardır. Problemin genel çözümü elde edilirken alt parçalara ait çözümler belirli bir sırayla bir araya getirilir. Böl ve yönet algoritmaları, genellikle üç ana aşamadan meydana gelmektedir: Bölme (Divide): Problemin daha küçük parçalara ayrıldığı aşamadır. Problem daha alt parçalara bölünemeyecek hale gelene kadar, özyinelemeli bir yaklaşımla bölme işlemi gerçekleştirilir. Yönetme (Conquer): Problemin alt parçalarının, birbirlerinden bağımsız olarak çözüldüğü aşamadır. Birleştirme (Merge): Problemin alt parçalarına ait çözümlerin, özyinelemeli bir yaklaşımla birleştirildiği aşamadır. * Dinamik programlama (Divide and Conquer Algorithms): Dinamik programlama, karmaşık problemleri küçük parçalar halinde çözen, elde edilensonuçları bilgisayar hafızasında bir veri yapısında saklayan, genel çözümü elde ederken de veri yapılarında saklanan sonuçları kullanan bir programlama yöntemidir. Bir problemin dinamik programlama ile çözülebilmesi için problemin alt parçalara ayrılabilmesi ve genel çözümün bu alt parçalardan oluşturulabilmesi gerekmektedir. Dinamik programlama yaygın olarak optimizasyon problemlerinde kullanılır. * Kaba kuvvet algoritması (Brute Force Algorithms): Bir problemin çözümü aşamasında, kabul edilebilir bir çözüm elde edene kadar tüm olasılıkları deneyen algoritmalara kaba kuvvet algoritmaları denir. Kaba kuvvet algoritmaların dezavantajları: Kaba kuvvet algoritmaları, genellikle problemin tanımından yola çıkarak en basit çözüm yolunu uygular ve rahatlıkla kodlanır. Fakat bu algoritmalarda çok fazla işlem yapılır ve çözüm yolu optimumdan uzaktır. Problemdeki veri hacmi büyüdükçe, kaba kuvvet algoritması ile çözüm şansı da azalır. * Açgözlü algoritma (Greedy Algorithms): Bir problem için mümkün olan en doğru çözümü hede eyen algoritmalara açgözlü algoritmalar adı verilir. Açgözlü algoritmalarda yerel olarak optimum sonuç elde edilirken, bulunan sonuç her zaman için en iyi çözüme karşılık gelmeyebilir. Açgözlü algoritmalar ile problem çözümündeki temel yaklaşım, problemin küçük bir alt kümesi için çözüm oluşturmak ve bu çözümü problemin geneline yaymaktır. Algoritma içerisinde yapılan bir seçim, o an için doğru olsa bile sonraki seçimlerde olumsuz etki yapabilir. * * Algoritma ile Problem Çözme: Temel olarak bir algoritma tasarım ve analizi yapılırkenki işleyiş aşamaları aşağıdaki gibidir; 1- Problemi anlama-> 2 2- Algoritma tasarım tekniğine karar verme-> 3 3- Algoritmayı tasarla-> 4, 2, 3 4- Doğruluğunu kanıtla-> 5, 2, 3 5- Algoritmayı analiz et-> 6 6- Algoritmanın kodunu yaz. * Algoritma tasarımı yaparken problem çok karmaşık ve çözümü uzun sürüyorsa: Kullanacağımız bilgisayarın işlemci hızı, hafıza kapasitesi vb. özellikleri tasarlayacağımız algoritmada etkilidir. Problemimiz çok karmaşık ve çözümü uzun süre gerektiriyorsa paralel programlama yöntemlerini kullanmaya karar verebiliriz. Problemimizi küçük parçalara böldükten sonra her bir parçayı ayrı bir bilgisayarda çözüp sonuçları birleştirerek asıl sonucu elde edebiliriz. Böylece problemimizi çok daha hızlı bir şekilde çözmüş oluruz * Üç tane sayının ortalamasını hesaplayan bir algoritmayı sözde kod ifade: Üç tane sayının ortalamasını hesaplayan bir algoritma tasarlayıp sözde kod ile ifade: – Sayıların değerlerini sayı1, sayı2 ve sayı3 olarak belirle – Ortalama = (sayı1 + sayı2 + sayı3) / 3 – Kullanıcıya ortalama değerini göster * Algoritma tasarlama süreci: Algoritmanın tasarımı ve analizi yapılırken problemi anlama aşamasından sonraki aşamadır. Problemi anladıktan sonraki aşamada gelmektedir. Algoritmaları tasarlarken diziler, kuyruklar, ağaçlar vb. veri yapılarından faydalanabiliriz. Veri yapısını seçerken mutlaka avantajlarını ve dezavantajlarını dikkate almalıyız. Ayrıca kullanacağımız programlama dili de algoritma tasarımında değerlendirmemiz gereken hususlardan biri olmalıdır. Nesne tabanlı bir dil kullanacaksak, tasarımlarımız da bu dile uygun olmalıdır. * Tasarladığımız algoritmayı göstermenin diğer bir yöntemi de akış diyagramı kullanmaktır. Akış diyagramları ile daha çok basit algoritmaları rahatlıkla gösterebiliriz. Ancak karmaşık algoritmalar akış diyagramı ile gösterime çok uygun olmayabilir. * Algoritma tasarlandıktan sonra doğruluğunu test: Algoritmayı tasarladıktan sonra, algoritmamızın bütün girişler için doğru sonucu vereceğini doğrulamamız gerekmektedir. Bu işlem bazı algoritmalar için nispeten kolay olmakla birlikte bazı algoritmalar için karmaşık bir süreç gerektirmektedir. Bir algoritmanın hatalı çalıştığını gösterebilmek için sadece bir tane yanlış sonuç yeterlidir, ancak doğru çalıştığını ispatlamak için bütün verilerde doğru çalıştığını teyit etmek gerekir. Örnek ola- rak sıralama algoritmasını ele alalım. Problemimizin kısıtlarını da düşünerek, tasarladığımız algoritmanın farklı eleman sayısı ve farklı elemanları sıralamak istediğimizde doğru sonucu vermesi gerekmektedir. Daha önce belirttiğimiz özel durumları da tasarımda göz önünde bulundurmalıyız. Örneğin, bölme işlemi yapan algoritmanın, sıfıra bölüm için tanımsız sonucunu vereceği de kontrol edilmelidir. * Algoritma kodunu yazmadan önceki son işlem: Hazırladığımız algoritmanın kodunu yazmaya başlamadan önceki son işlemimiz algoritmayı analiz etmektir. Algoritmanın çalışma zamanı, başka bir ifadeyle, algoritma karmaşıklık düzeyi ve hafıza gereksinimleri analiz edilmelidir. * * Algoritma Tasarlama Teknikleri: Elimizde n tane elemandan oluşan bir dizi olduğunu düşünelim. Bu dizinin içerisindeki en büyük elemanı şu şekilde buluruz: Bu problemde ilk akla gelen çözüm bütün elemanlara tek tek bakıp en büyük olan elemanı bulmak olabilir. Bu işlemi şu şekilde yapabiliriz. Başlangıçta, dizinin ilk elemanını en büyük kabul ederiz. Daha sonra, en büyük kabul ettiğimiz değeri sırasıyla dizinin bütün elemanlarıyla karşılaştırırız. Herhangi bir sıradaki elemanın değeri, en büyük kabul ettiğimiz değerden büyükse en büyük eleman değerimizi güncelleriz. Dizinin sonraki elemanlarını karşılaştırırken güncellenmiş en büyük değerimizi kullanırız. Dizinin sonuna geldiğimizde ise dizinin tamamı açısından en büyük elemanı bulmuş oluruz. * Döngü-Tekrarlama Algoritmaları: Algoritmaları temel olarak iki gruba ayırabiliriz. Bunlar döngü (tekrarlama) algoritmaları ve özyinelemeli fonksiyon algoritmalarıdır. Döngü algoritmalarında, problemin çözümünü döngü içerisindeki tekrarlarla buluruz. Özyinelemeli fonksiyon algoritmalarında ise yazdığımız fonksiyon kendi içerisinde yine kendini çağırarak sonuca ulaşır. Her iki grubun da kendine has özellikleri vardır. * Küçült-Fethet (Decrease&Conquer) Yöntemi ile Algoritma Tasarlama: Bu algoritma tasarım yönteminde, problemin tamamının çözümüyle küçük bir parçasının çözümü arasında bir bağlantı vardır. Problemin çözümü aşağıdan yukarıya ya da yukarıdan aşağıya olabilir. Tanıma bakacak olursak problemin özyinelemeli fonksiyon uygulaması ile çözüleceğini düşünsek de döngü-tekrar algoritmaları ile de çözüme ulaşabiliriz * Özyinelemeli Fonksiyon Algoritmaları ve Böl & Fethet (Divite & Conquer) Yöntemi ile Algoritma Tasarımı: Böl-Fethet yöntemi en iyi bilinen algoritma tasarım yöntemlerinden biridir. Böl-Fethet yöntemindeki algoritmalar aşağıdaki gibi isleyiş yapısına sahiptir: 1. Öncelikli olarak problem genellikle eşit büyüklükteki alt parçalara ayrılır. 2. Her bir alt problem, genellikle özyinelemeli fonksiyon aracılığı ile çözülür. 3. Bütün alt problemlerin çözümü birleştirilerek genel sonuç elde edilir. Örnek olarak problemimizin dört parçadan oluştuğunu varsayalım. Her bir alt problem teker teker çözülür. Alt problemlerin çözümünden sonra elimizdeki dört çözüm birleştirilir ve ana çözümü elde etmiş oluruz. * * Kaynak: anadolu.edu.tr]]>