Preorder, Postorder ve Inorder Binary Search Tree Traversal stratejileri ne zaman kullanılır?


100

Geçenlerde fark ettim ki, hayatımda BST'yi bol miktarda kullanırken, Inorder geçişinden başka bir şey kullanmayı düşünmedim bile (bir programı sipariş öncesi / sonrası geçişi kullanacak şekilde uyarlamanın ne kadar kolay olduğunun farkındayım ve biliyorum).

Bunu fark ettikten sonra, eski veri yapıları ders kitaplarından bazılarını çıkardım ve ön sipariş ve sipariş sonrası geçişlerin yararlılığının arkasındaki mantığı aradım - ama pek bir şey söylemediler.

Preorder / postorder'ın pratik olarak ne zaman kullanılacağına dair bazı örnekler nelerdir? Sıradan olmaktan ne zaman daha mantıklı geliyor?

Yanıtlar:


138

Ön Sipariş, Siparişte ve Sipariş Sonrası Geçiş Stratejisi ne zaman kullanılır?

Bir ikili ağaç için hangi koşullar altında ön sipariş, sıra ve son sipariş kullanacağınızı anlamadan önce, her geçiş stratejisinin nasıl çalıştığını tam olarak anlamanız gerekir. Aşağıdaki ağacı örnek olarak kullanın.

Ağacın kökü 7 , en soldaki düğüm 0 , en sağdaki düğüm 10'dur .

görüntü açıklamasını buraya girin

Ön sipariş geçişi :

Özet: Kökte ( 7 ) başlar, en sağdaki düğümde biter ( 10 )

Geçiş sırası: 7, 1, 0, 3, 2, 5, 4, 6, 9, 8, 10

Sıralı geçiş :

Özet: En soldaki düğümde ( 0 ) başlar, en sağdaki düğümde ( 10 ) biter

Geçiş Sırası: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10

Sipariş sonrası geçiş :

Özet: En soldaki düğüm ( 0 ) ile başlar, kök ( 7 ) ile biter

Geçiş sırası: 0, 2, 4, 6, 5, 3, 1, 8, 10, 9, 7

Ön Sipariş, Siparişte veya Sonradan Sipariş ne zaman kullanılır?

Programcının seçtiği geçiş stratejisi, tasarlanan algoritmanın özel ihtiyaçlarına bağlıdır. Hedef hızdır, bu nedenle size en hızlı şekilde ihtiyaç duyduğunuz düğümleri getiren stratejiyi seçin.

  1. Herhangi bir yaprağı incelemeden önce kökleri keşfetmeniz gerektiğini biliyorsanız, ön sipariş verirsiniz çünkü tüm yapraklardan önce tüm köklerle karşılaşacaksınız.

  2. Herhangi bir düğümden önce tüm yaprakları keşfetmeniz gerektiğini biliyorsanız, son siparişi seçersiniz çünkü yaprakları aramak için kökleri incelemekle zaman kaybetmezsiniz.

  3. Eğer ağaç düğümlerde doğal bir diziyi olduğunu biliyoruz ve bir daha özgün dizisi içine ağaç geri, düzleştirmek istiyorsanız de sipariş kastetmek kullanılmalıdır. Ağaç, yaratıldığı şekilde düzleştirilecekti. Ön sipariş veya sipariş sonrası geçiş, ağacı, onu oluşturmak için kullanılan sıraya geri döndürmeyebilir.

Ön Sipariş, Sırayla ve Sipariş Sonrası için Özyineli Algoritmalar (C ++):

struct Node{
    int data;
    Node *left, *right;
};
void preOrderPrint(Node *root)
{
  print(root->name);                                  //record root
  if (root->left != NULL) preOrderPrint(root->left);  //traverse left if exists
  if (root->right != NULL) preOrderPrint(root->right);//traverse right if exists
}

void inOrderPrint(Node *root)
{
  if (root.left != NULL) inOrderPrint(root->left);   //traverse left if exists
  print(root->name);                                 //record root
  if (root.right != NULL) inOrderPrint(root->right); //traverse right if exists
}

void postOrderPrint(Node *root)
{
  if (root->left != NULL) postOrderPrint(root->left);  //traverse left if exists
  if (root->right != NULL) postOrderPrint(root->right);//traverse right if exists
  print(root->name);                                   //record root
}

3
Yinelemeli olmayan geçişler ne olacak? Bana öyle geliyor ki, önceki düğümlere geri dönmeyi gerektirmediğinden, bir ağacı ön sırayla, sırayla / son sırayla karşılaştırıldığında, özyinelemesiz olarak geçmek çok daha kolay.
bluenote10

@ bluenote10 Ne demek istediğini açıklayabilir misin? Ön siparişte, sol çocuğunu işledikten sonra sağ çocuğunu işlemek için bir düğüme yine "dönersiniz". Elbette, "henüz ziyaret edilmemiş düğümler" kuyruğunu kullanabilirsiniz, ancak bu gerçekten sadece açık bir kuyruk için örtük (yığın) depolamayla ticaret yapmaktır. Tüm geçiş yöntemlerinde, hem sol hem de sağ çocukların işlenmesi gerekir, bu, bunlardan birini yaptıktan sonra ebeveyne "geri dönmeniz" gerektiği anlamına gelir.
Joshua Taylor

@JoshuaTaylor: Evet, hepsi aynı karmaşıklık sınıfı, ancak tipik uygulamalara bakarsanız, sipariş sonrası işlem muhtemelen biraz daha zor.
bluenote10

2
Ön sipariş geçişi, düğüm değerlerini bir ekleme sırasına göre verir. Ağacın bir kopyasını oluşturmak istiyorsanız, kaynak ağacını bu şekilde geçmeniz gerekir. Sıralı geçiş, sıralı düğüm değerlerini verir. Sonradan geçişle ilgili olarak, bu yöntemi tüm ağacı silmek için kullanabilirsiniz, çünkü ilk önce yaprak düğümlerini ziyaret eder.
albin

Bence ağaç doğru sıralanmasa bile doğru, yani sıra ilk başta sıralanmamışsa sıralı sırayı vermez.
CodeYogi

31

Ön sipariş: Bir ağacın bir kopyasını oluşturmak için kullanılır. Örneğin, bir ağacın kopyasını oluşturmak istiyorsanız, düğümleri ön sipariş geçişi olan bir diziye yerleştirin. Ardından , dizideki her değer için yeni bir ağaçta bir Ekleme işlemi gerçekleştirin . Orijinal ağacınızın bir kopyasını elde edeceksiniz.

Sıralı:: Bir BST'de düğümlerin değerlerini azalan sırayla almak için kullanılır.

Son sipariş:: Bir ağacı yapraktan köke silmek için kullanılır


2
Bu harika, kısa bir cevap ve ön sipariş ve sipariş sonrası kullanım örneklerini anlamama yardımcı oldu. Bununla birlikte, sorunun doğrudan bundan bahsettiği açık olabilir, ancak bunun ikili ARAMA ağaçları için geçerli olduğuna ve genel ikili ağaçlar için çalışmayacağına dikkat edin. örneğin, kopyalama işlemi sırasında ekleme mantığı çalışmayacağından, genel bir ikili ağacı kopyalamak için mutlaka ön sipariş geçişini kullanamazsınız.
markckim


26

Ağacın hiyerarşik biçimini doğrusal bir biçimde yazdırmak isteseydim, muhtemelen ön sipariş geçişini kullanırdım. Örneğin:

- ROOT
    - A
         - B
         - C
    - D
         - E
         - F
             - G

4
Veya TreeViewbir GUI uygulamasındaki bir bileşende.
svick

4

Ön ve son sipariş sırasıyla yukarıdan aşağıya ve aşağıdan yukarıya yinelemeli algoritmalarla ilgilidir. İkili ağaçlara yinelemeli bir şekilde belirli bir özyinelemeli algoritma yazmak istiyorsanız, esas olarak bunu yapacaksınız.

Ayrıca, ön ve son sipariş dizilerinin birlikte eldeki ağacı tamamen belirlediğini ve kompakt bir kodlama (en azından seyrek ağaçlar için) sağladığını gözlemleyin.


1
Sanırım önemli bir şey söylemeye çalışıyorsunuz, lütfen ilk yarıyı açıklar mısınız?
CodeYogi

@CodeYogi Özellikle neyin açıklanmasına ihtiyacınız var?
Raphael

1
"Ön ve son-sıra, yukarıdan aşağıya ve aşağıdan yukarıya özyinelemeli algoritmalarla ilişkilidir" Sanırım ilk durumda düğümün özyinelemeli yöntemlerden herhangi birini çağırmadan önce işlendiğini ve ikincisinde tam tersi olduğunu söylemek istersiniz. ?
CodeYogi

@CodeYogi Evet, temelde.
Raphael

2

Bu farkın gerçek bir rol oynadığını gördüğünüz tonlarca yer var.

Dikkat edeceğim harika bir şey, bir derleyici için kod üretmedir. Şu ifadeyi düşünün:

x := y + 32

Bunun için kod üretme şeklinizin yolu (doğal olarak, elbette) ilk önce y'yi bir sicile yüklemek, 32'yi bir sicile yüklemek ve ardından ikisini eklemek için bir talimat oluşturmak için kod üretmektir. Çünkü bir şeyi değiştirmeden önce bir kayıt defterinde olması gerekir (farz edelim, her zaman sabit işlenenler yapabilirsiniz ama her neyse) bunu bu şekilde yapmalısınız.

Genel olarak, bu soruya alabileceğiniz cevaplar temelde şuna indirgenir: Veri yapısının farklı parçalarının işlenmesi arasında bir miktar bağımlılık olduğunda fark gerçekten önemlidir. Öğeleri yazdırırken, kod oluştururken (dış durum fark yaratır, bunu tek taraflı olarak da görebilirsiniz) veya ilk işlenen çocuklara bağlı olarak hesaplamaları içeren yapı üzerinde diğer hesaplama türlerini yaparken bunu görürsünüz. .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.