2 bináris fák egyenlő-e vagy sem

szavazat
7

Lehetséges Ismétlődő:
Határozza meg, hogy a két bináris fák egyenlő

Van egy interjú tegnap, a kérdés elkapott, itt van:

Leírás

Vannak 2 binary trees, ellenőrizze, hogy azok egyenlő.

Ezek egyenlő akkor és csak akkor tree1->child == tree2->child, és egy fa balra és jobbra children can be swapped with each other.

Például:

    5     6
   / \   / \           they are equal.
   1 2   2  1

    5         6
   / \       / \           they are equal.
  1   2     2   1
 /     \   /    / 
3       4 4     3

Bármilyen ötletet értékelik.

A kérdést 12/10/2011 01:18
a forrás felhasználó
Más nyelveken...                            


6 válasz

szavazat
9

Egyenlőség operátorok tranzitív: Ha A = B, és B = C, akkor A = B = C, így A = C.

Egyenlőség szereplők reflexív: A = A, B = B, és C = C nem számít, hogy milyen értékeket vallanak.

Egyenlőség szereplők szimmetrikus. Ha A = B, akkor B = A. (Nem számít, hogy milyen sorrendben vannak.)

Most, hogy egy pillantást a meghatározás kaptál:

A fa egyenlő egy másik fát, ha a gyerekek egyenlő. Lássuk. Feltételezhetjük, hogy a csomópontok összehasonlított alján, vagy pedig a meghatározás elég használhatatlan. De nem zavarja, hogy megmondja, hogyan kell megoldani, hogy az összehasonlítás, és az egész meghatározás kaptál múlik rajta.

Röviden, ez egy gagyi kérdés.

Lássuk, mi történik, ha úgy döntünk, hogy ki szeretné próbálni, és felbomlik a kérdés, mégis.

De várjunk csak, azt is mondani, hogy a két gyermek bármilyen fa lehet cserélni. Ez növeli a kikötéssel, hogy minden fa, amely egyenlő mást (önmagát is beleértve) meg kell egyeznie a tükörképei. És minden variációját a részfák gyerekek is cserélték.

És ne feledd, hogy ez elvileg egy keresési fát. Ezért valószínűleg feltételezzük, hogy két különböző keresési fák által feldolgozott ugyanazt az algoritmust kell ugyanazt az eredményt adja, ha azok egyenlőek. Tehát, ha váltani körül az elemek egy fát, majd a keresési idő hatással lehet. Tehát, a fák, amelyek nem rendelkeznek minden csomópont helyén nem egyenlő egymással.

Üzembe, hogy együtt „cserélhető” tulajdonsága ez az egyenlőség, kiderül, hogy ez nem egy érvényes definíció az egyenlőség. (Ha megpróbáljuk alkalmazni, akkor kiderül, hogy csak a fák, amelyek az azonos csomópont minden egyes csomóponthoz egy adott szinten egyenlő, és csak magukra, ami megtöri a reflexivitás része egy operátorral.)

Válaszolt 12/10/2011 01:24
a forrás felhasználó

szavazat
3

Ha végre azok meghatározása „egyenlőség” flip-invariancia, akkor megsérti a definíció az egyenlőség. A meghatározás nem is értelme, mert ez nem így bináris keresési fák azonos (kivéve, ha minden egyes csomópont mutatót, amely a kulcsnak a „nagyobb”, és amely „kisebb”).

Két választása van az ésszerű meghatározások:

  1. topológiai (flip-agnosztikus) ekvivalencia (ebben az esetben nem lehet nevezni a „bináris keresési fa”, mert ez nem rendezve):

    tree1==tree2 eszközök set(tree1.children)==set(tree2.children)

  2. normál keresési fa (flip-gondozási) ekvivalencia:

    tree1==tree2 eszközök list(tree1.children)==list(tree2.children)

Mert bináris fák, a fenti meghatározások fog működni-bármely nyelven, amely támogatja a listés setadattípusok (python szettek fojtó azonban a unhashable adattípusok). Mindazonáltal az alábbiakban néhány bőbeszédű és csúnya C / Java-szerű meghatározások:

  1. topológiai ekvivalencia:

    t1==t2 eszközök (t1.left==t2.left and t1.right==t2.right) or (t1.left==t2.right and t1.right==t2.left)

  2. kiválogatott fa ekvivalencia:

    t1==t2 eszközök (t1.left==t2.left and t1.right==t2.right)

A fenti definíciók rekurzívak; vagyis azt feltételezik, egyenlőség meghatározásra került a részfákat és az alap-esetben már, ami meg is történt.


oldaljegyzet:

idézet: tree1-> gyermek == tree2-> gyermek

Ez nem egy érvényes állítás, mert a fa csomópont nem rendelkezik egyetlen gyermeke.

Válaszolt 12/10/2011 02:20
a forrás felhasználó

szavazat
7

Nem hiszem, hogy ez egy ésszerűtlen kérdés. Egy egyszerű rekurzív megoldás

boolean equals(x, y)
{
  if (x == null)
  {
    return y == null;
  }
  if (y == null)
  {
    return false;
  }
  if (x.val != y.val)
  {
    return false;
  }
  if (equals(x.left, y.left) && equals(x.right, y.right))
  {
    return true;
  }
  if (equals(x.left, y.right) && equals(x.right, y.left))
  {
    return true;
  }
  return false;
}

Ez lehet nagyon drága, például abban az esetben, ha van két nagy fák hasonló alakú, ahol az összes nem-levél csomópontok ugyanolyan tartozó érték, és a levél csomópontok egy olyan permutációja szárcsomóknál másik.

Ahhoz, hogy ez a múlt tudna először változás a bal és jobb, mint szükség, hogy a bal <jobbra, néhány rekurzív definíciója <. Ez is lehet drága, de sokkal kevésbé, mint ellenőrizve minden permutáció, és azt hiszem, a választás definíciója <segítene. Ez majd lehetővé teszi, hogy ellenőrizze az egyenlőség egy közönséges meghatározás.

Ez a fogalom a http://en.wikipedia.org/wiki/Canonicalization majd rendes egyenlőség is megoldja a kérdést, hogy valóban van egy ekvivalencia reláció. Egy ekvivalencia reláció ekvivalens egy partíciót. Rendes egyenlőség nyilvánvalóan egy partíciót. Ha összehasonlítjuk az x és y összehasonlításával f (x) és f (y), majd egy ekvivalencia reláció van egy partíció x és y, és ezért ekvivalencia reláció.

Gondolkodás többet ez, azt hiszem, a módja annak, hogy akár canonicalisation vagy egyenlőséget vizsgáló ésszerűen hatékony, hogy a munka az alulról felfelé, magyarázó minden csomópont egy jelképes, amelynek értéke eredményét tükrözi összehasonlítás más csomópontokat úgy, hogy össze tudja hasonlítani a csomópontok és a részfák alattuk, csak legyen összehasonlítva zsetont.

Tehát az első lépés az egyenlőség, hogy pl egy hash tábla jegyzetekkel minden levél tokeneket, amelyek egyenlők csak az értékek levelek egyenlő. Ezt követően, a csomópontok, amelyeknek csak a gyerekek leveleit használja pl hash tábla rendelni további zsetonok, hogy a jelzőt ezek a csomópontok egyenlő csak a levelek, ha van ilyen, alatt azokat a csomópontokat mérkőzés. Akkor mehet még egy lépést, és ez alkalommal is össze zsetont a gyermek csomópontok helyett rekurzív a fát ott. Az ára hozzárendelése tokenek ilyen módon kell lineáris a méret a fák részt. A tetején össze tudja hasonlítani a fák csak összehasonlítjuk a zsetont a gyökér.

Válaszolt 12/10/2011 06:57
a forrás felhasználó

szavazat
0

Olvastam a kérdéseket: Adott két bináris fák, minden mélységet a fa, megtudja, hogy a gyermekek set borítják egymást.

Ez lehet kódolni viszonylag könnyű.

Válaszolt 12/10/2011 12:30
a forrás felhasználó

szavazat
0

Megoldás nélkül rekurzió Ruby

def same? top_t1, top_t2
  for_chek << [top_t1, top_t2]   # (1) put task for check into queue

  while t1,t2 = for_check.shift  # (2)
    return false unless t1.children.count == t2.children.count  # generally for non-binary tree, but also needed for controlling of nil children
    break if t1.children.empty?

    t1_children = t1.children.sort # this is sorted arrays
    t2_children = t2.children.sort # of childrens      
    return false unless t1_children == t2_children  # (3)

    0.upto(t1_children.count - 1) do |i|
      for_check << [t1_children[i], t2_children[i]]  # put equivalent child pairs into queue
    end
  end
  return true
end

Ruby szintaxis tipp:

  • (1) üzembe elemet tömb: arr << elem; ebben az esetben for_checka tömb tömbök
  • (2) párhuzamos hozzárendelés: t1,t2 = [item1, item2]. Ugyanaz, mint aarr = [item1, item2]; t1 = arr[0]; t2 = arr[1]
  • (3) t1_children == t2_childrenfeltételezzük, megfelelő viselkedése == az ilyen típusú objektumok. További részletes lesz t1_children.map { |el| el.val } == t2_children.map { |el| el.val }- itt maptermel tömb lok.
Válaszolt 15/10/2011 16:17
a forrás felhasználó

szavazat
1

Összehasonlítás fák segítségével szenttéavatás által javasolt megközelítés @mcdowella . A különbség az, hogy a megoldás nem igényel O(N)további memória WRT csomópontok száma a fa:

# in Python
from collections import namedtuple
from itertools import chain

# Tree is either None or a tuple of its value and left, right trees
Tree = namedtuple('Tree', 'value left right')

def canonorder(a, b):
    """Sort nodes a, b by their values.

    `None` goes to the left
    """
    if (a and b and a.value > b.value) or b is None:
        a, b = b, a # swap
    return a, b

def canonwalk(tree, canonorder=canonorder):
    """Yield all tree nodes in a canonical order.

    Bottom-up, smaller children first, None is the smallest
    """
    if tree is not None:
        children = tree[1:]
        if all(t is None for t in children): return # cut None leaves
        children = canonorder(*children)            
        for child in chain(*map(canonwalk, children)):
            yield child
    yield tree 

canonwalk()igényel O(N*M)lépések és O(log(N)*M)a memória, így minden csomópont egy fa, ahol Naz összesen csomópontok száma, Ma gyermekek száma minden egyes csomópont (ez 2 bináris fák).

canonorder()lehetne könnyen általánosítható bármilyen csomópont megjelenítés és a gyermekek száma. canonwalk()csak azt követeli meg egy fa érheti közvetlen gyermekek sorozata.

Az összehasonlító függvényt hív canonwalk():

from itertools import imap, izip_longest

unset = object() 
def cmptree(*trees):
    unequal = False # allow root nodes to be unequal
    # traverse in parallel all trees under comparison
    for nodes in izip_longest(*imap(canonwalk, trees), fillvalue=unset):
        if unequal:
            return False # children nodes are not equal
        if any(t is unset for t in nodes):
            return False # different number of nodes
        if all(t is not None for t in nodes):
            unequal = any(nodes[-1].value != t.value for t in nodes)
        else: # some are None
            unequal = any(t is not None for t in nodes)
    return True # equal

Példa

    5         6
   / \       / \           they are equal.
  1   2     2   1
 /     \   /    / 
3       4 4     3

tree1 = Tree(5, 
             Tree(1, 
                  Tree(3, None,None), None), 
             Tree(2, 
                  None, Tree(4, None, None)))
tree2 = Tree(6, 
             Tree(2, Tree(4, None, None), None),
             Tree(1, Tree(3, None, None), None))
print cmptree(tree1, tree2)

kibocsátás

True
Válaszolt 15/10/2011 21:10
a forrás felhasználó

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