Download as pdf or txt
Download as pdf or txt
You are on page 1of 8

 Öncelikli Kuyruk Nedir?

Öncelikli kuyruklar (priority queues), terim anlamıyla gündelik yaşamda sık karşılaştığımız bir
olguyu belirler. Bazı durumlarda bir işi öteki işlerin hepsinden önce yapmak zorunda kalabiliriz.
Örneğin, bir fatura ödeme veznesinde kuyruğa girenler arasında öncelik sırası önde olanındır. Ancak,
bir kavşakta geçiş önceliği cankurtaranındır. Bir hava meydanına iniş sırası bekleyen uçaklar arasında,
öncelik sırası acil iniş isteyen uçağındır. Bir hastanede muayene önceliği ise durumu en acil olan
hastanındır.

Bilgisayarlarda öncelikli kuyrukların kullanımına örnek olarak printer ve işletim sistemi


verilebilir. Ağ yazıcılarında’da az sayfaya sahip belge önce yazılır. Çok sayfası olan bir belge
yazdırılmak üzere yazıcıya gönderilmiş ve hemen akabinde iki sayfalık bir belge daha yazdırılmak
istenmiş olabilir. İki sayfalık belgenin çıktısını almak için sayfalar dolusu belgenin yazdırma işleminin
bitmesi beklenmez. Arada bir bölümde iki sayfa yazdırılır. İşletim sisteminde ise en kısa zamanlı işlem
önce çalışır. Gerçek zamanlı işlemler de öncelik değerine sahiptir

Görüldüğü gibi, bir koleksiyon içinde öncelik sırasını farklı amaçlarla belirleyebiliriz. En basiti,
ilk gelen ilk çıkar dediğimiz FIFO (first in first out) yapısıdır. Ama bu yapı karşılaşılacak bütün
olasılıklara çözüm getiremez. Dolayısıyla, koleksiyonun öğelerini istenen önceliğe göre sıralayan bir
yapıya gereksinim vardır. Biraz genellemeyle, öncelikli kuyruklar yapısına da kuyruk diyeceğiz; ama
burada yüklenen anlamı FIFO yapısından farklı olabilir. Son giren de ilk çıkabilir, ilk giren de ilk
çıkabilir. Duruma göre değişmektedir. Önceliği en yüksek olan kuyruktan ilk çıkar. Soyut bir veri tipi
(ADT – Abstract Data Type) olarak öncelikli kuyruklarda sadece sayılar ya da karakterler değil,
karmaşık yapılar da olabilir. Örnek olarak bir telefon rehberi listesi, soyisim, isim, adres ve telefon
numarası gibi elemanlardan oluşmaktadır ve soyisme göre sıralıdır. Öncelikli kuyruklardaki
elemanların sıralarının elemanların alanlarından birisine göre olması da gerekmez. Elemanın kuyruğa
eklenme zamanı gibi elemanların alanları ile ilgili olmayan dışsal bir değere göre de sıralı olabilirler

Öncelikli kuyruklar, temel kuyruk işlemlerinin sonuçlarını elemanların gerçek sırasının


belirlediği veri yapılarıdır. Azalan ve artan sırada olmak üzere iki tür öncelik kuyruğu vardır. Artan
öncelik kuyruklarında (min heap) elemanlar herhangi bir yere eklenebilir ama sadece en küçük
eleman çıkarılabilir. Azalan öncelik kuyruğu (max heap) ise artan öncelik kuyruğunun tam tersidir.
Artan öncelik kuyruğunda önce en küçük eleman, sonra ikinci küçük eleman sırayla çıkarılacağından
dolayı elemanlar kuyruktan artan sırayla çıkmaktadırlar. Birkaç eleman çıkarıldıktan sonra ise daha
küçük bir eleman eklenirse doğal olarak kuyruktan çıkarıldığında önceki elemanlardan daha küçük bir
eleman çıkmış olacaktır.

Kuyruktaki her nesnenin karşılaştırılabilir bir öncelik değeri (key) vardır. Bazı sistemlerde
küçük değer önceliklidir, bazı sistemlerde de küçük değerler, küçük öncelikli olabilir. İlk nesne
kuyruğun başına konulur ve önceliği belirten bir key değeri atanır. Öncelikli kuyruklarda da diğer
kuyruklarda olduğu gibi ekleme ve silme işlemleri mevcuttur.

1
 Öncelikli Kuyruk Algoritması ve Çalışması

Bilindiği üzere normalde sıralar (queue) ilk giren ilk çıkar (FIFO , first in first out) mantığı ile çalışırlar.
Yani bir bilet sırasında olduğu gibi sıraya ilk giren kişi hizmete ilk ulaşan, son giren kişi ise son ulaşan
kişidir.

Öncelik sırasında (rüçhan sırası, priority queue) ise bu sırada bekleyenlerden en öncelikli olan kişinin
ilk erişmesi beklenir. Bu durumu bir örnek üzerinden anlatmak gerekirse sırada bekleyen kişiler ve
öncelikleri aşağıdaki şekilde verilmiş olsun:

Kişi No Öncelik

1 5

2 3

3 1

4 2

5 4

Yukarıdaki tabloda kişi numaraları ve öncelikleri sıralanmıştır. Bu listeye göre sırada bekleyenlerden
ilk çıkması gereken kişi en yüksek önceliğe sahip olan 1 numaralı kişidir. Ardından 4 önceliğine sahip 5
numaralı kişi sıradan çıkar. Sıradan önceliklerine göre çıkanları sıralayacak olursak : 1,5,2,4,3 numaralı
kişilerdir.

Öncelik sırasının işlenmesini aslında sırada bekleyen kişilerin önceliklerine göre sıralanması (Sort) ve
ardından normal bir sıra (queue) gibi veri yapısının işlenmesi olarak düşünebiliriz. Örneğin yukarıdaki
durumda öncelik sırasına göre sırayı yeniden düzenleyecek olursak :

Kişi No Öncelik

1 1

5 2

2 3

4 4

3 5

Sıralamasını elde etmiş oluruz ki bu da zaten beklemekte olan kişilerin çıkış sırasıdır.

2
Öncelik sıralarında aynı önceliğe sahip kişilerin nasıl sıradan çıkacakları da ayrıca bir problem olarak
görülebilir. Bu noktadaki en klasik çözüm geliş sırasında göre öncelik vermektir. Örneğin yukarıdaki
durumda 3 önceliğine sahip bir kişi daha olsaydı:

Kişi No Öncelik

1 5

2 3

3 1

4 2

5 4

6 3

Bu durumda öncelik sıralamasına göre hangi 3 önceliğine sahip olan kişinin (2. Kişi veya 6. Kişi)
belirlerken önce gelenin önce çıkması ilkesi korunabilir. Bu durumda beklemekte olan kişiler aşağıdaki
sırada sıralanabilir:

Kişi No Öncelik

1 1

5 2

2 3

6 3

4 4

3 5

Öncelik sıraları bilgisayar bilimlerinin veri yapısı konusunda kullanılan bir kavram olmasına karşılık
uygulama alanları oldukça geniştir. Örneğin işletim sistemlerinde kullanılan en kısa iş ilk (shortest job
first)işlemci zamanlama (CPU scheduling) algoritması tam bir öncelik sırası örneğidir. Bekleme
sırasındaki (Ready queue) işlemlerin (process) çalıştırılma sırası uzunluklarına göre önceliğe sahiptir.

3
 Huffman Algoritması

Huffman kodlaması, girilen veriyi sıkıştırmak amacıyla kullanılan bir sıkıştırma algoritmasıdır. David A.
Huffman tarafından 1952 yılında geliştirilmiştir.

Günlük hayatta bize gösterilen verilerde her karakterin 8 bitlik ASCII karşılığı vardır. Her bir karakter
bellekte 8 bitlik değer ile saklanmaktadır. Ancak bu durum bellek sıkıntısı olan uygulamalar için sıkıntı
yaratmaktadır.

Huffman’ın geliştirdiği algoritmada, veri içerinde kullanılan her bir karakterin belli bir frekansı
(kullanım sıklığı) vardır. Bir karakterin frekansı ne kadar fazla ise bellekte yer aldığı alan o kadar
fazladır. Bu sebepten ötürü Huffman, frekansı büyük olan karakterlerin bellekte 8 bit yerine daha az
bitle saklanması durumunda yerden kazanılabileceğini düşünmüş ve algoritmasını geliştirmiştir.

Algoritma şu basamakları takip ederek uygulayabiliriz:

1. Karakterler kodlanmadan önce veri içerisindeki her karakter tek tek taranır, frekansları
belirlenir.
2. Karakterler frekanslarına göre azalan ya da artan sırada sıralanırlar. (Sıralama için sıralama
algoritmalarından herhangi biri kullanılabilir.

3. Sıralamanıza göre en küçük 2 frekanslı karakter alınarak ikili ağaç oluşturulur. Frekansları
toplamı kök düğüme yazılır.

4. Sonra tekrar sıralama yapılır (ağaçları sıralarken kök düğümdeki değer önemsenir), en küçük
2 birimden tekrar ikili ağaç oluşturulur.
5. Sıralama işlemi sırada sadece ve sadece tek bir ağaç kalana kadar devam eder.

4
Ağaçta dikkat edilmesi noktalardan biri yaprakların hepsinde harf vardır. Harfler arada
dallarda yer almamaktadır.
6. Ağaç oluşturulduktan sonra ağacın kollarına numaralar verilir. Her kök düğümden çıkan sol
dala 1, sağ dala 0 ya da sol dala 0, sağ dala 1 verilir. Kök düğümden yapraklara inerken her dal
üstündeki karakter okunur, böylece karakterin yeni değeri ortaya çıkar.

Örnek olarak yukarıdaki ağaçta yer alan örneklerin yeni değerleri:


'g' 00
'o' 01
'p' 1110
'h' 1101
'e' 101
'r' 1111
's' 1100
' ' 100
7. Yukarıdaki gibi kodları elde ettikten sonra veri içerisindeki tüm veriler baştan okunur. Her
karaktere karşılık gelen kod yerine yerleştirilir. Böylece veri verimizin boyutunu düşürmüş
olduk.

5
 Huffman Algoritması Örnek Kodu

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace Huffman
{
class Node
{
public int frequency;
public string data;
public Node leftChild, rightChild;

public Node(string data, int frequency)


{
this.data = data;
this.frequency = frequency;
}

public Node(Node leftChild, Node rightChild)


{
this.leftChild = leftChild;
this.rightChild = rightChild;

this.data = leftChild.data + ":" + rightChild.data;


this.frequency = leftChild.frequency + rightChild.frequency;
}
}

class Program
{
static void Main(string[] args)
{
IList<Node> list = new List<Node>();

//int[] array = new int[]{45, 13, 12, 16, 9, 5};


int[] array = new int[] { 18, 25, 21, 17, 5, 14 };

for (int i = 0; i < array.Length; i++)


{
list.Add(new Node("S" + (i + 1), array[i]));
}

Stack<Node> stack = GetSortedStack(list);

while (stack.Count > 1)


{
Node leftChild = stack.Pop();
Node rightChild = stack.Pop();

Node parentNode = new Node(leftChild, rightChild);

stack.Push(parentNode);

stack = GetSortedStack(stack.ToList<Node>());
}

Node parentNode1 = stack.Pop();

GenerateCode(parentNode1, "");

6
DecodeData(parentNode1, parentNode1, 0, "0010011101001111");
//DecodeData(parentNode1, parentNode1, 0, "100");

Console.ReadKey();
}

public static Stack<Node> GetSortedStack(IList<Node> list)


{
for (int i = 0; i < list.Count; i++)
{
for (int j = 0; j < list.Count; j++)
{
if (list[i].frequency > list[j].frequency)
{
Node tempNode = list[j];
list[j] = list[i];
list[i] = tempNode;
}
}
}

Stack<Node> stack = new Stack<Node>();

for (int j = 0; j < list.Count; j++)


stack.Push(list[j]);

return stack;
}

public static void GenerateCode(Node parentNode, string code)


{
if (parentNode != null)
{
GenerateCode(parentNode.leftChild, code + "0");

if (parentNode.leftChild == null && parentNode.rightChild == null)


Console.WriteLine(parentNode.data + "{" + code + "}");

GenerateCode(parentNode.rightChild, code + "1");


}
}

public static void DecodeData(Node parentNode, Node currentNode, int pointer, string
input)
{
if (input.Length == pointer)
{
if (currentNode.leftChild == null && currentNode.rightChild == null)
{
Console.WriteLine(currentNode.data);
}

return;
}
else
{
if (currentNode.leftChild == null && currentNode.rightChild == null)
{
Console.WriteLine(currentNode.data);
DecodeData(parentNode, parentNode, pointer, input);
}
else
{

7
if (input.Substring(pointer, 1) == "0")
{
DecodeData(parentNode, currentNode.leftChild, ++pointer, input);
}
else
{
DecodeData(parentNode, currentNode.rightChild, ++pointer, input);
}
}
}
}
}
}

You might also like