Çift bağlantılı liste

advertisement
Listeler
İçerik
 Soyut
Veri Yapısı - Abstract Data Type (ADT)
 Liste SVY
 Liste SVY nın Dizi ile gerçekleştirilmesi
 Bağlantılı Listeler
 Temel İşlemler

Ekleme - Insert, Bul- find, sil-delete, yaz-print, etc.
 Bağlantılı


liste türevleri
Dairesel (Circular) bağlantılı listeler
Çift-yönlü (Doubly) bağlantılı listeler
Soyut Veri Yapısı
 Veri


tipi
Nesneler kümesi + işlemler kümesi
Örnek : integer
Tamsayılar
kümesi
işlemler: +, -, x, /
 Genelleştirilebilinir



mi?
(örnek prosedürler bir işlem kavramını genelleştirir)
Evet!
Soyut veri tipi


Yüksek-seviyede soyutlama high-level abstractions
(soyutlama aracılığıyla karmaşıklık kontrolü)
Kaysülleme (Encapsulation) / giydirme
Kapsülleme
SVT üzerindeki işlemler sadece uygun fonksiyonun
çağrılması ile yapılabilir.
 Tip tanımı ve bu tip üzerindeki işlemler, programın bir
bölümüne yerleştirilebilinir.
 Eğer SVT nin gerçekleştirilmesi değiştirmek
isteniyorsa
 Nereye bakacağımızı biliyoruz.
 Bir kısmını değiştirmekle programın başka
yerlerinde hata çıkmayacağından emin oluruz.
 SVT basit tipler gibi davranabiliriz: Alt plandaki
gerçekleştirilmesiyle ilgilenmemize gerek kalmayabilir.
 SVT  C++: class
 metot  C++: member function üye fonksiyonu

SVT…

Örnekler
 set – küme SVT
Elemanların
kümesi
işlemler: birleşim- union, kesişim-intersection, boyutu-size
and tersi-complement

queue – kuyruk SVT
Elemanların
art arda dizilmiş hali
işlemler: boş kuyruk oluştur-create empty queue, ekleinsert, incele-examine, sil-delete, ve yoket-destroy

İki SVT aynı değildir: Alt planda aynı modele sahip
olmasına rağmen işlemleri farklıysa.
 Örnek. Sadece birleşim ve bul işlemleri içeren setküme SVT farklıdır.
 Gerçekleştirmenin uygunluyu çalıştırılan işlemlere
çok bağlıdır.
Avantaj ve Dezavantajları


SVTlerinin kullanımı, gerçekleştirmesinden ayrıdır/
ayrılır.
Modülerdir: bir SVT için bir modül




SVT kodu farklı uygulamalar için tekrar kullanılabilir.
Bilgi gizleme



Belirli bir işi yapmak için tasarlanmış mantıksal birimdir.
Kullanıcı programlarını etkilemeden gerçekleştirme detayları
değiştirilebilir.
Hızlı prototiplemeye müsaittir.


Hata ayıklaması (debug) kolaydır.
Birden fazla kişinin aynı anda beraber çalışmasına uygundur.
Basit SVT gerçekleştirmeleri ile prototipini yap ve sonra
gerekirse ayarlama yap.
Verimlilik kaybı
Liste SVT
 Sıfır
veya birden fazla elemanların art arda
dizilmiş hali
A1, A2, A3, … AN
 N: liste uzunluğu
 A1: ilk eleman
 AN: son eleman
 Ai: i. Eleman / pozisyon
 If N=0, then listeyi boşalt
 Lineer olarak sıralanmış

Ai precedes (önce gelir) Ai+1
 A follows (takip eder) A
İşlemler
 printList:
listeyi yaz
 makeEmpty: boş liste oluştur
 find: listedeki bir elemanın pozisyonunu bul


liste: 34,12, 52, 16, 12
find(52)  3
 insert:

listeye bir eleman ekle
insert(x,3)  34, 12, 52, x, 16, 12
 remove:

listeden bir eleman sil
remove(52)  34, 12, x, 16, 12
 findKth:
Belirli bir pozisyondaki elemanı getir.
SVT Gerçekleştirmesi
 SVT

ini ifade edecek bir veri yapısı seç
Örnek: Diziler, kayıtlar vb.
 Each
operation associated with the ADT is
implemented by one or more subroutines
 Two standard implementations for the list ADT


Array-based
Linked list
Dizi Gerçekleştirmesi
 Elemanlar
art arda bir şekilde kaydediliyor.
Dizi Gerçekleştirmesi...
 Listenin
maksimum boyutunun bilinmesini
gerektirir

Yer israfı
doğrusal
 findKth:
sabit
 insert ve delete: yavaş
 printList

ve find:
örnek 0. pozisyona ekleme (yeni eleman)
Öncelikle
yer açmak için bütün dizinin bir hücre
kaydırılmasını gerektirir.

örnek 0. pozisyonda silme
Bütün

elemanların bir hücre yukarı kaydırılması gerekir
Ortalama olarak her iki işlemde de listenin yarısının
yer değiştirmesi gerekir.
İşaretçi Gerçekleştirmesi (Bağlantılı
Liste)
 Liste


de elemanlar art arda depolanmayacaksa
bağlantılı liste kullanılabilir
Hafızada art arda olmasına gerek olmayan yapılardır.
 Her düğüm bir eleman ve kendisinden sonra gelen
düğümüm adresini içeren bir işaretçi barındırır.
Son hücre bir sonraki bağlantı olarak NULL değerini gösterir.
 Dizi gerçekleştirmesi ile karşılaştırılırsa,
İşaretçi uygulaması gerektiği kadar alan kullanır
Fakat herbir hücrede işaretçi için alan tutar.
Bağlantılı Listeler
A
B
C

Baş
Bağlanmış düğümler serisine bağlantılı liste denir
 Her düğüm en az aşağıdakileri içerir.



Veri (herhangi bir tiple olabilir)
Listedeki bir sonraki düğüme olan işaretçi
Baş: İlk düğüme olan işaretçidir
 Son düşüm NULL’ a işaret edernode

A
veri
işaretçi
Basit bir Bağlantılı Liste Sınıfı
 İki
sınıf kullanılır : Node ve List
 Node sınıfını düğümler için tanımla


data: double-tipinde veri
next: listedeki bir sonraki düğüme işaretçi
class Node {
public:
double
Node*
};
data;
next;
// data
// pointer to next
Basit bir Bağlantılı Liste Sınıfı

List sınıfı aşağıdakiler içerir


head: listedeki ilk düğüme olan işaretçi.
İlk başta liste boş olduğu için, head, NULL değerini alır.
List üzerindeki işlemler
class List {
public:
List(void) { head = NULL; }
~List(void);
// constructor
// destructor
bool IsEmpty() { return head == NULL; }
Node* InsertNode(int index, double x);
int FindNode(double x);
int DeleteNode(double x);
void DisplayList(void);
private:
Node* head;
};
Basit bir bağlantılı liste sınıfı
 List





işlemleri
IsEmpty: listenin boş oluş olmadığını belirle.
InsertNode: belirlenen bir pozisyona yenib ir
düğüm ekle
FindNode: verilen bir değere sahip düğümü bul
DeleteNode: verilen bir değere sahip düğümü sil
DisplayList: listedeki bütün düğümleri listele
Yeni bir düğüm ekleme

Node* InsertNode(int index, double x)

index’inci elemandan sonra verisi x’e eşit olan düğümü ekle

Eğer ekleme başarılı ise, eklenmiş düğümü dönder yoksa,
return NULL.
(örnek., index = 0 iken, düğümü ilk eleman olarak ekle;
index = 1 iken, ilk elemandan sonra düğüm ekle.)
(Eğer index < 0 veya > liste uzunluğu ise , ekleme başarısız olacak.)

Adımlar
1.
2.
3.
4.
index’inci elemanı bul
Yeni düğüm için hafızada yer ayır
Yeni düğüm kendisinden sonrakini gösterecek
Yeni düğümden önceki yeni düğümü
gösterecek
index’inci
eleman
newNode
Yeni bir düğüm ekleme

InsertNode ‘ da karşılaşılan durumlar
Boş listeye ekle
2. En öne ekle
3. En sona ekle
4. Ortaya ekle
1.

Gerçekte iki temel durum vardır.


İlk düğüm olarak ekleme (Durum 1 and Durum 2)
Ortaya veya sona ekleme (Durum 3 and Durum 4)
Yeni bir düğüm ekleme
Node* List::InsertNode(int index, double x) {
if (index < 0) return NULL;
Try to locate
index’th node. If it
doesn’t exist,
return NULL.
int currIndex =
1;
Node* currNode =
head;
while (currNode && index > currIndex) {
currNode
=
currNode->next;
currIndex++;
}
if (index > 0 && currNode == NULL) return NULL;
Node* newNode =
newNode->data =
if (index == 0) {
newNode->next
head
}
else {
newNode->next
currNode->next
}
return newNode;
}
new
x;
Node;
=
=
head;
newNode;
=
=
currNode->next;
newNode;
Yeni bir düğüm ekleme
Node* List::InsertNode(int index, double x) {
if (index < 0) return NULL;
int currIndex =
1;
Node* currNode =
head;
while (currNode && index > currIndex) {
currNode
=
currNode->next;
currIndex++;
}
if (index > 0 && currNode == NULL) return NULL;
Node* newNode =
newNode->data =
if (index == 0) {
newNode->next
head
}
else {
newNode->next
currNode->next
}
return newNode;
}
new
x;
Node;
=
=
head;
newNode;
=
=
currNode->next;
newNode;
Create a new node
Yeni bir düğüm ekleme
Node* List::InsertNode(int index, double x) {
if (index < 0) return NULL;
int currIndex =
1;
Node* currNode =
head;
while (currNode && index > currIndex) {
currNode
=
currNode->next;
currIndex++;
}
if (index > 0 && currNode == NULL) return NULL;
Node* newNode =
newNode->data =
if (index == 0) {
newNode->next
head
}
else {
newNode->next
currNode->next
}
return newNode;
}
new
x;
Node;
Insert as first element
head
=
=
head;
newNode;
=
=
currNode->next;
newNode;
newNode
Yeni bir düğüm ekleme
Node* List::InsertNode(int index, double x) {
if (index < 0) return NULL;
int currIndex =
1;
Node* currNode =
head;
while (currNode && index > currIndex) {
currNode
=
currNode->next;
currIndex++;
}
if (index > 0 && currNode == NULL) return NULL;
Node* newNode =
newNode->data =
if (index == 0) {
newNode->next
head
}
else {
newNode->next
currNode->next
}
return newNode;
}
new
x;
Node;
=
=
head;
newNode;
Insert after currNode
currNode
=
=
currNode->next;
newNode;
newNode
Bir düğüm bulma
 int
FindNode(double x)

Listede verisi x olan düğümü ara.

Eğer böyle bir düğüm varsa pozisyonunu dönder,.
Yoksa, return 0.
int List::FindNode(double x) {
Node* currNode
=
head;
int currIndex
=
1;
while (currNode && currNode->data != x) {
currNode
=
currNode->next;
currIndex++;
}
if (currNode) return currIndex;
return 0;
}
Düğüm silme

int DeleteNode(double x)
 Listeden verisi x from the list.


Adımlar

İstenen düğümü bul (FindNode işlemine benzer)

Bunulan düğümün işgal ettiği hafızayı boşalt (gözden çıkar)
Bulunan düğümün öncekisi, bulunan düğümün sonrakisini
gösterir şekilde ayarla.


Böyle bir düğüm varsa , pozisyonunu dönder. Yoksa, return 0.
InsertNode, gibi iki özel durum vardır.


İlk düğümü sil
Ortadaki veya sonraki düğümü sil.
Düğüm silme
int List::DeleteNode(double x) {
Try to find the node
Node* prevNode =
NULL;
its value equal to x
Node* currNode =
head;
int currIndex =
1;
while (currNode && currNode->data != x) {
prevNode
=
currNode;
currNode
=
currNode->next;
currIndex++;
}
if (currNode) {
if (prevNode) {
prevNode->next =
currNode->next;
delete currNode;
}
else {
head
=
currNode->next;
delete currNode;
}
return currIndex;
}
return 0;
}
with
Düğüm silme
int List::DeleteNode(double x) {
Node* prevNode =
NULL;
Node* currNode =
head;
int currIndex =
1;
while (currNode && currNode->data != x) {
prevNode
=
currNode;
currNode
=
currNode->next;
currIndex++;
prevNode currNode
}
if (currNode) {
if (prevNode) {
prevNode->next =
currNode->next;
delete currNode;
}
else {
head
=
currNode->next;
delete currNode;
}
return currIndex;
}
return 0;
}
Düğüm silme
int List::DeleteNode(double x) {
Node* prevNode =
NULL;
Node* currNode =
head;
int currIndex =
1;
while (currNode && currNode->data != x) {
prevNode
=
currNode;
currNode
=
currNode->next;
currIndex++;
}
if (currNode) {
if (prevNode) {
prevNode->next =
currNode->next;
delete currNode;
}
else {
head
=
currNode->next;
delete currNode;
}
return currIndex;
}
head currNode
return 0;
}
Bütün elemanları yazdırma
 void


DisplayList(void)
Bütün düğümlerin verilerini yazdır
Listedeki düğüm sayısını yazdır.
void List::DisplayList()
{
int num
=
0;
Node* currNode
=
head;
while (currNode != NULL){
cout << currNode->data << endl;
currNode
=
currNode->next;
num++;
}
cout << "Number of nodes in the list: " << num << endl;
}
Listeyi yoketme

~List(void)
destructor u kullanarak liste tarafından işgal edilen hafızayı
serbest bırak.
 Listedeki her bir düğümü birer birer sil.
List::~List(void) {
Node* currNode = head, *nextNode = NULL;
while (currNode != NULL)
{
nextNode
=
currNode->next;
// destroy the current node
delete currNode;
currNode
=
nextNode;
}
}

6
7
5
Number of nodes in the list: 3
5.0 found
4.5 not found
6
5
Number of nodes in the list: 2
result
List ‘ in kullanımı
int main(void)
{
List list;
list.InsertNode(0, 7.0);
list.InsertNode(1, 5.0);
list.InsertNode(-1, 5.0);
list.InsertNode(0, 6.0);
list.InsertNode(8, 4.0);
// print all the elements
list.DisplayList();
if(list.FindNode(5.0) > 0)
else
if(list.FindNode(4.5) > 0)
else
list.DeleteNode(7.0);
list.DisplayList();
return 0;
}
//
//
//
//
//
successful
successful
unsuccessful
successful
unsuccessful
cout
cout
cout
cout
<<
<<
<<
<<
"5.0
"5.0
"4.5
"4.5
found" << endl;
not found" << endl;
found" << endl;
not found" << endl;
Bağlantılı Liste Çeşitleri
 Dairesel

(Çevrimsel) bağlantılı listeler
Son düğüm listedeki ilk düğümü işaret eder
A
Head

B
C
Listeyi gezmeyi ne zaman bitireceğimizi nasıl
bileceğiz? (İpucu: current node işaretçisinin kafa
(baş) ı işaret edip etmediğini kontrol et.)
Bağlantılı Liste Çeşitleri
 Çift


bağlantılı liste (Doubly linked lists)
Herbir düğüm hem öncekini hem sonrakini işaret
eder.
İki NULL vardır: listenin ilk ve son düğümlerinde
Avantajı: verilen düğümde, öncekini ziyaret etmek
kolaydır. Listeleri ters yönde gezmek kolayıdır.

A
Head
B
C

Dizi ve Bağlantılı Listeler

Bağlantılı listelerin kodlaması ve yönetimi dizilerden
daha zordur fakat kendine has avantajları vardır.

Dinamik: bir bağlantılı liste kolaylıkla büyüyebilir ve
daralabilir.
Listede
kaç düğüm olması gerektiğini bilmemize gerek yoktur.
Gerektikçe hafızada oluşturulur.
Buna karşılık C++ ‘ da dizi boyutu derleme zamanında sabittir.

Kolay ve hızlı ekleme ve silme
Dizide
ekleme ve silme için geçici değişkenlere kopyalamak ve
boşluk açmak veya boşluğu silmek gerekir.
Bağlantılı listede ise düğümlerin hareket etmesine gerek yoktur.
Sadece işaretçilerin ayarları değiştirilir.
Örnek: Polinomial SVT
Tek- değişkenli polinomial için SVT
 Dizi gerçekleştirmesi

N
f ( x)   ai x i
i 0
Polinomial SVT …


Eğer Aj katsayıları sıfırdan farklı ise kabul
edilebilirdir, diğer durumda istenmez.
Örnek: Çarp
P1 ( x)  10 x1000  5 x14  1
P2 ( x)  3x1990  2 x1492  11x  5
Zamanın
çoğu sıfırların çarpımı için ve var olmayan
parçaların çarpımı için harcanır.
 Bağlantılı

liste kullanılarak uygulanması
Herbir terim bir hücrede tutulur ve üstel değerlerin
azalmasına göre sıralanır.
Download