Bir BST içinde takas düğümleri bulun

oy
6

Ben algılamak ve takas edilmiş BST iki düğüm yazdırabilirsiniz bir program yazmaya çalışıyorum.

Üç seviyeli ağacında, bu yaklaşımı kullanarak çözüme yakın ulaştı.

If (!AllSubTreeAreValid())
{
//Nodes swapped on same side of main root node
}
else
{
  int max = getMax(root->left);
  int min = getMin(root->right);
  if(max > root->data || min < root->data )
  {
     //Nodes swapped on different sides of main root node
     //Print max and min values

  }
else 
{
 //No node swappped
}
}

//Helper functions
int GetMaxEle(TreeNode* tree)
{
    while(tree->right!=NULL)
    {
        tree=tree->right;
    }
    return tree->info;
}

int GetMinEle(TreeNode* tree)
{
    while(tree->left!=NULL)
    {
        tree=tree->left;
    }
    return tree->info;
}

Dört seviyeli ağacıyla sınamak çalıştım ama yukarıdaki yaklaşım başarısız oldu.

             20

      15            30

   10    17       25     33

9  16  12  18  22  26  31  34

Kök düğüm 15'in sağ alt ağaç olmak, 12 hala daha büyük (ihlali) 'dir.

kök düğümü 15'in sol alt ağaç olmak, 16 yine de daha büyük (ihlali) 'dir.

Yani, 16, 12 yukarıda BST içinde takas unsurlardır. Nasıl program sayesinde bunları buluyor?

Oluştur 31/08/2011 saat 17:30
kaynak kullanıcı
Diğer dillerde...                            


3 cevaplar

oy
0

Ben senin getMin et getMax yüzden, ağaç bir BST olan hipotezler Witht işe yarıyor

T getMax(tree) {
  return tree -> right == null 
    ? tree -> value 
    : getMax(tree -> right);
}

(Bir döngü ile ya da eşdeğer kod). Eğer öyleyse, kod ağacında en fazla üç değerleri inceler. getMax ve getMin fiili maksimum / dk almak için tam ağaç geçilen bile, yine de sadece iki karşılaştırmalar üzerinde testini temel olacaktır. Eğer ağaç BST özelliğini tatmin olmadığını kontrol etmek istiyorsanız, size tüm değerleri incelemek zorunda olduğu açıktır. Onun yeterince onun ebeveyni ile her düğümü karşılaştırmak.

void CheckIsBst(Tree *tree) {
  if (tree -> left != null) {
    if (tree -> left -> value > tree -> value) {
      // print violation
    }
    CheckIsBst(tree -> left);   
  }
  // same with -> right, reversing < to > in the test
}

Düzenleme : yanlıştı, yorumu görmek. Ben bu Tamam olduğuna inanıyoruz.

void checkIsBst(Tree *Tree, Tree *lowerBound, Tree *upperBound) {
  if(lowerBound!= null && lowerBound -> value > tree -> Value) {
    //violation
  }
  // same for upper bound, check with <
  if (tree -> left != null) {
    if (tree -> left -> value > tree -> value) {
      // print violation
     }
     CheckIsBst(tree -> left, lowerBound, tree);   
  }
  // same for right, reversing comparison 
  // setting lowerBound to tree instead of upperBound
}

boş sınırları ile kökünden çağırma

Cevap 31/08/2011 saat 18:03
kaynak kullanıcı

oy
8

Bu sorun hakkında düşünmek için bir yolu ağacının bir inorder yürüyüş sıralanmış sırayla tüm öğeleri üretecek gerçeğini kullanmaktır. Bu yürüyüş sırasında sıralı düzenden sapmalar algılayabilir varsa, yanlış yerde olan iki unsurları bulmak için deneyebilirsiniz.

o sırada ağaçların üzerinde çalışmaktadır şeyler inşa etmek bizim algoritma kullanır, önce basit sıralanan dizide için bunun nasıl görelim. Biz sıralanan dizide ile başlamak ve daha sonra iki (non-eşit!) elemanları takas eğer Sezgisel, biz yersiz olmak dizideki öğelerinden bazılarını numarası ile sona erecek. Örneğin, dizi verilen

1 2 3 4 5

Biz 2 ve 4 takas, biz bu dizide ile sonuna kadar:

1 4 3 2 5

Nasıl 2 ve 4 burada takas edildiğini tespit edecek? Şekil 4, iki elemanlarının daha büyük olan ve aşağı doğru takas beri de, bunun çevresinde elemanların her ikisi de daha büyük olmalıdır. 2 kadar değiştirildiğinden Benzer bir şekilde, bunun çevresinde elemanların her ikisi de daha küçük olması gerekmektedir. Bu, biz 2 ve 4 takas edildiği sonucunu verebilir.

Ancak bu her zaman doğru çalışmaz. Örneğin, 1 ve 4 takas varsayalım:

4 2 3 1 5

Burada, her iki 2 ve 1 komşu elemanlar daha küçüktür, ve her ikisi de 4 ile 3 onların daha büyüktür. Bundan her nasılsa bu dört iki takas edildiğini söyleyebilir, ama biz değişimli olarak hangilerinin net değil. Biz büyük ve bu değerlerden (sırasıyla 1 ve 4,) en küçük almak Ancak, biz takas edildi çifti elde sonunda.

Daha genel olarak sırayla takas edildi unsurları bulmak için, bulmak istediğiniz

  • Dizideki en büyük lokal maksimum.
  • Dizideki en küçük yerel minimum.

Bu iki unsur yersiz ve takas edilmelidir.

Şimdi, ağaçlara bu nasıl uygulanacağı düşünelim. bozuk iki unsurları ile sıralanmış diziyi üretecek ağacın bir inorder yürüyüş yana, seçeneklerden biri daha sonra yukarıdaki algoritma kullanılarak, saptadığımız unsurların inorder dizisini kayıt ağacı yürümeye olacaktır. Örneğin, orijinal BST göz önünde bulundurun:

              20
         /         \
      15             30
     /   \         /   \ 
   10    17      25     33
  / |   /  \    /  \    |  \
9  16  12  18  22  26  31  34

Biz bir diziye bu lineerleştirmek, biz olsun

9 10 16 15 12 17 18 20 22 25 26 30 31 33 34

16 çevresindeki elemanlarının daha büyük olduğuna dikkat edin ve 12 bu onun daha azdır. Bu hemen 12 ve 16 takas edildi söyler.

Bu sorunu çözmek için basit bir algoritma, bu nedenle, bir böyle bir dizinin içine doğrusallaştırılması için ağacın bir inorder yürüyüş yapmak olacaktır vectorOr dequebüyük yerel maksimum ve en küçük yerel minimum bulmak için bu diziyi taramak için daha sonra. Bu O (n) alanı kullanarak, O (n) zamanda çalışır. Mevcut düğüm, selefi, ve ardıl - - bir seferde sadece üç düğüm takip etmek için bir yanıltıcıdır ama daha fazla yer-verimli bir algoritma olabilir O bellek kullanımını azaltır (1).

Bu yardımcı olur umarım!

Cevap 31/08/2011 saat 21:22
kaynak kullanıcı

oy
0

tarafından yapılan ağaç geçişi templatetypedef yalnızca bir takas var eminseniz çalışır. Aksi takdirde ben başlangıçtaki koduna dayalı bir çözüm önermek:

int GetMax(TreeNode* tree) {
    int max_right, max_left, ret;

    ret = tree->data;
    if (tree->left != NULL) {
        max_left = GetMax(tree->left);
        if (max_left > ret)
            ret = max_left;
    }
    if (tree->right != NULL) {
        max_right = GetMax(tree->right);
        if (max_right > ret)
            ret = max_right;
    }

    return ret;
}

int GetMin(TreeNode* tree) {
    int min_right, min_left, ret;

    ret = tree->data;
    if (tree->left != NULL) {
        min_left = GetMin(tree->left);
        if (min_left < ret)
            ret = min_left;
    }
    if (tree->right != NULL) {
        min_right = GetMin(tree->right);
        if (min_right < ret)
            ret = min_right;
    }

    return ret;
}

void print_violations(TreeNode* tree) {
    if ((tree->left != NULL) && (tree->right != NULL)) {
        int max_left = GetMax(tree->left);
        int min_right = GetMin(tree->right);
        if (max_left > tree->data && min_right < tree->data) {
            printf("Need to swap %d with %d\n", max_left, min_right);
        }
    }
    if (tree->left != NULL)
        print_violations(tree->left);
    if (tree->right != NULL)
        print_violations(tree->right);
}

Bu yavaştır, ama buna tanımlayan tüm takaslarını yazdırır. tüm ihlalleri (örn if (max_left> tree> verileri) baskı ihlali) yazdırmak için değiştirilebilir. O alt ağaç için önceden hesaplanabilir max ve min TreeNode iki alanlar ekleyebilirsiniz eğer performansını artırabilir.

Cevap 01/09/2011 saat 08:43
kaynak kullanıcı

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more