Ağaclar

Ağaclar alqoritmlərdə əsas verilən strukturlarından biridir və müxtəlif məsələlərdə tez-tez rast gəlinir.

Ağac — əlaqəli, dövrəsiz, istiqamətsiz qrafdır.

Bir G = (V, E) qrafı aşağıdakı xüsusiyyətləri ödəyirsə, ona ağac deyilir:

  • Əlaqəli — qrafdakı istənilən iki zirvə arasında yol mövcuddur.

  • Dövrəsiz — qraf heç bir dövr (cycle) ehtiva etmir.

zirvəli ağacda həmişə dəqiq olaraq n - 1 kənar (edge) olur.

Ağacın Əsas Xüsusiyyətləri

1. Əlaqəlilik və Yolların Təkliyi

Ağacda istənilən iki zirvə arasında unikal (tək) yol mövcuddur.

2. Kənarların Sayı

Hər hansı ağac üçün:

|E| = |V| - 1

3. Dövr yoxdur

Ağaca əlavə edilən istənilən kənar mütləq dövr yaradır.

4. Kök (kök verilmiş ağac üçün)

Əgər bir zirvə kök kimi seçilərsə, ağac kökdən övladlara doğru istiqamətlənmiş olur. Bu, rekursiv keçidlərdə və alqoritmlərdə (, və s.) istifadə olunur.

5. Alt ağaclar

Hər hansı zirvə və onun nəslindən olan bütün zirvələr alt ağac yaradır. Alt ağac özü də ağacdır.

6. Yarpaqlar

Heç bir övladı olmayan (kök verilmiş ağacda) zirvələrə yarpaq deyilir.

7. Dərinlik və Hündürlük

  • Dərinlik — kökdən həmin zirvəyə olan məsafə.

  • Hündürlük — ağacdakı maksimum dərinlik.

8. Ağacın Mərkəzi

Mərkəz — bütün digər zirvələrə qədər olan maksimal məsafəni minimallaşdıran zirvə (və ya bitişik zirvələr cütü)dir.

Ağacın Alternativ Tərifləri

Ağac üçün aşağıdakı təriflər bir-birinə ekvivalentdir və müxtəlif kontekstlərdə istifadə oluna bilər:

  • Hər hansı bir kənarın silinməsi ilə qraf əlaqəsini itirən dövrəsiz qraf.

  • zirvəsi və n - 1 kənarı olan əlaqəli qraf.

  • n - 1 kənarı olan və dəqiq bir komponentdən ibarət dövrəsiz qraf.

Ağacların Koddakı Təsviri

Məsələnin növündən və ağacın tipindən (ümumi, binar, kök verilmiş və s.) asılı olaraq müxtəlif verilən strukturlarından istifadə olunur:

1. Qonşuluq siyahısı (Adjacency Lists)

Bu yanaşma yarışma tipli məsələlərdə və istiqamətli/istiqamətsiz ağaclarla işləyərkən çox istifadə olunur.

int n;
vector<vector<int>> tree(n); // n zirvəli ağac

// u və v zirvələri arasında kənar əlavə etmək
tree[u].push_back(v);
tree[v].push_back(u); // istiqamətsiz ağac üçün

2. Valideyn massivi (Parent Array)

Çox yığcam təmsil formasıdır, xüsusilə ağac artıq qurulmuşdursa istifadə olunur.

vector<int> parent(n); // parent[i] --- i zirvəsinin valideyni
// əgər i kökdürsə, adətən parent[i] = -1 və ya 0 seçilir

3. Göstəricilər / Strukturlar (OOP üslubu)

Xüsusilə binar ağaclar, trie-lər, dekoratorlar qurarkən Python/Java/C++ dillərində obyekt-yönlü proqramlaşdırma ilə istifadə olunur.

  • Binar ağac:

struct Node 
{
  int val;
  Node* left;
  Node* right;
  Node(int v) : val(v), left(nullptr), right(nullptr) {}
};
  • Ümumi ağac:

struct Node 
{
  int val;
  vector<Node*> children;
  Node(int v) : val(v) {}
};

Nümunə

Nümunədə verilmiş ağacı nəzərdən keçirək. Hər bir zirvənin yanında, həmin zirvənin kök olduğu alt ağacın ölçüsü qeyd olunub. Zirvələr və -nın alt ağacları cüt sayda zirvəyə malikdir. Zirvə kök olduğundan və onu valideynə birləşdirən kənar olmadığından, və kənarlarını silirik.

Ağac cüt sayda zirvəsi olan əlaqəli komponentə bölünüb.

Məsələlərin siyahısı

18

Şərhlər5