Обнаружение ли 2 BST представлены массивами изоморфны или нет

голоса
0

1) Учитывая, 2 массива, содержащие элементы полного двоичного дерева (уровень по уровню), фактически реконструкции дерева (т.е. только делать свопы в массиве), как я могу найти ли эти 2 массивы изоморфны или нет?

2) лучшее решение, если одна изоморфное дерево образует Двоичное дерево.

обновление , например ,

     5 
    / \
    4  7
   /\  /\
  2  3 6 8

может быть представлена ​​в массиве, как 5 4 7 2 3 6 8

Изоморфные деревья деревья, которые могут быть преобразованы друг с другом посредством поворота вокруг узлов

     5 
    / \
    4  7
   /\  /\
  2  3 6 8



     5 
    / \
    4  7
   /\  /\
  3  2 6 8



     5 
    / \
    4  7
   /\  /\
  3  2 8 6



     5 
    / \
    7  4
   /\  /\
  8  6 3 2
Задан 07/11/2011 в 19:30
источник пользователем
На других языках...                            


4 ответов

голоса
2

Вы можете сделать заказ в дереве ходить на них обоих одновременно и проверить, являются ли элементы одинаковы.

Ответил 07/11/2011 в 20:24
источник пользователем

голоса
0

Принимая участие (2) во-первых, своп пара узлов - и их потомки - на каждом уровне, по мере необходимости, чтобы превратить каждое дерево в бинарное дерево поиска, с левыми узлами <= правые узлы. Это займет время н войти п. После того, как вы это сделали, если бы вы бинарное дерево поиска и дерево, изоморфный с двоичным деревом поиска, теперь у вас есть два бинарных дерева поиска. Как отметили yi_H, это означает, что в заказ дерево ходьба покажет одни и те же элементы в том же порядке, если оба дерева изоморфны. Но в заказ дерево ходьба, в дереве хранится в массиве, как в ваших примерах, это просто своеобразный способ посещения всех элементов массива, так что если дерева изоморфны два массива должен быть идентичен.

Самый простой способ справиться с частью (1), если вы можете найти дополнительное пространство. Для самого низкого уровня каждого дерева, построить хэш-таблицу для каждого дерева, удерживающей листья. Сравните два хэш-таблицу и выход, если они не держат тот же набор узлов. Дайте каждый лист идентификатор, который идентифицирует его, где идентификаторы одинаковы, если листы одинаковы. Для родителей этих листьев, построить другую хэш-таблицу, используя значения в каждом из родителей и идентификаторы этих детей. Опять же, убедитесь, что оба набора одинаковы и выход, если нет. Назначение каждым из родителей идентификатора, который является тем же самым, если значение в узле одинаковы и идентификаторы своих детей одинаковы. Вы можете продолжать таким образом до дерева, пока не достигнет корня. Если все множества одинаковы на всем пути вверх, у вас есть две изоморфные деревья, и идентификаторы дают вам корреспонденцию на каждом уровне. Это более сложное, чем часть (1) и занимает дополнительное пространство, но только линейное время.

Ответил 08/11/2011 в 06:26
источник пользователем

голоса
2

Для первой задачи:

Немного обозначений:

  • t0, t1 - деревья
  • значение (т) - число хранится в узле
  • слева (т) - левое поддерево
  • правый (т) - правое поддерево

t1и t2изоморфны тогда и только тогда t1и t2пустые,

или value (t1) == value (t2)

а также

либо left(t1)изоморфна left(t2)и right(t1)изоморфно right(t2),

или left(t1)изоморфно right(t2)и right(t1)изоморфнаleft(t2)

Если предположить , что деревья хранятся в массивах, таким образом, что элемент 0 является корнем , а если tэто индекс внутреннего узла 2t+1и 2t+2являются показателями его непосредственных детей, просто реализация:

#include <stdio.h>

#define N 7

int a[] = { 5, 4, 7, 2, 3, 6, 8 };
int b[] = { 5, 7, 4, 6, 8, 2, 3 };

int
is_isomorphic (int t1, int t2)
{
  if (t1 >= N && t2 >= N)
    return 1;

  if (a [t1] != b [t2])
    return 0;

  return ((is_isomorphic (2*t1 + 1, 2*t2 + 1)
           && is_isomorphic (2*t1 + 2, 2*t2 + 2))
          || (is_isomorphic (2*t1 + 1, 2*t2 + 2)
              && is_isomorphic (2*t1 + 2, 2*t2 + 1)));
}

int main ()
{
  printf ("%s\n", (is_isomorphic (0, 0) ? "yes" : "no"));
  return 0;
}

Для второй задачи, на каждый шаге мы сравниваем поддерево aс меньшим корнем поддерева bс меньшим корнем , а затем поддеревом aс большим корня поддерева bс большим корнем (меньше и больше , чем ток корни aи b).

int
is_isomorphic_bst (int t1, int t2)
{
  if (t1 >= N && t2 >= N)
    return 1;

  if (a [t1] != b [t2])
    return 0;

  int t1l, t1r, t2l, t2r;
  if (a [2*t1 + 1] < a [t1] && a [t1] < a [2*t1 + 2])
    {
      t1l = 2*t1 + 1;
      t1r = 2*t1 + 2;
    }
  else if (a [2*t1 + 1] > a [t1] && a [t1] > a [2*t1 + 2])
    {
      t1l = 2*t1 + 2;
      t1r = 2*t1 + 1;
    }
  else
    return 0;

  if (b [2*t2 + 1] < b [t2] && b [t2] < b [2*t2 + 2])
    {
      t2l = 2*t2 + 1;
      t2r = 2*t2 + 2;
    }
  else if (b [2*t2 + 1] > b [t2] && b [t2] > b [2*t2 + 2])
    {
      t2l = 2*t2 + 2;
      t2r = 2*t2 + 1;
    }
  else
    return 0;

  return is_isomorphic_bst (t1l, t2l) && is_isomorphic_bst (t1r, t2r);
}
Ответил 08/11/2011 в 15:41
источник пользователем

голоса
0

Для BST:

  1. Возьмите первые элементы обоих массивов и матч. Если не равны, то BST не быть одинаковыми.
  2. Найти первые оставленные дети , которые не были отсканированы (в положениях leftPos1 и leftPos2) и матч. Если не соответствует , то BST не то же самое.
  3. Найти первые правильные дети , которые не были отсканированы (в положениях rightPos1 и rightPos2) и матч. Если не соответствует , то BST не то же самое.
  4. Если оба левых и правых детей совпадают, выполняют те же операции рекурсивно по две пары подсписков / поддеревьев (от leftPos1 и leftPos2) и (с rightPos1 и rightPos2). Родитель этого поддерева является первым элементом массива.

При поиске левых и правых детей в подсписке, может быть элементы, которые уже отсканированы. Для того, чтобы найти такие элементы, убедитесь, что элемент, который может быть чадами текущего поддерева. Если текущее поддерево на левой стороне родителя, а затем сравнить элемент с родителем, если он принадлежит к правой стороне, то игнорировать этот элемент.

#include <stdio.h>

#define BOOL int
#define TRUE 1
#define FALSE 0

BOOL isLeft(int parent, int child) {
    return child <= parent;
}

BOOL isRight(int parent, int child) {
    return child > parent;
}

BOOL isBelongToChild(int parent, int child, int value) {
    if (isLeft(parent, child) && (isLeft(parent, value))) {
        return TRUE;
    }
    if (isRight(parent, child) && (isRight(parent, value))) {
        return TRUE;
    }
    return FALSE;
}

int getLeftPosition(int * array, int size, int parent, BOOL parentExists) {
    int i;

    int first = *array;
    for (i = 1; i < size; i++) {
        int value = *(array + i);
        if (! isBelongToChild(parent, first, value)) {
            continue;
        }
        if (isLeft(first, value)) {
            return i;
        }
    }
    return -1;
}

int getRightPosition(int * array, int size, int parent, BOOL parentExists) {
    int i;

    int first = *array;
    for (i = 1; i < size; i++) {
        int value = *(array + i);
        if (! isBelongToChild(parent, first, value)) {
            continue;
        }
        if (isRight(first, value)) {
            return i;
        }
    }
    return -1;
}

BOOL areSame(int * array1, int pos1, int * array2, int pos2) {
    if (pos1 == -1 && pos2 == -1) {
        return TRUE;
    } else if (*(array1 + pos1) == *(array2 + pos2)) {
        return TRUE;
    } else {
        return FALSE;
    }
}

BOOL isSameBst(int * array1, int size1, int * array2, int size2, int parent, BOOL parentExists) {
    if (0 == size1 && 0 == size2) {
        return TRUE;
    }
    if (*array1 != *array2) {
        return FALSE;
    }

    int leftPos1 = getLeftPosition(array1, size1, parent, parentExists);
    int leftPos2 = getLeftPosition(array2, size2, parent, parentExists);
    if (! areSame(array1, leftPos1, array2, leftPos2)) {
        return FALSE;
    }
    int rightPos1 = getRightPosition(array1, size1, parent, parentExists);
    int rightPos2 = getRightPosition(array2, size2, parent, parentExists);
    if (! areSame(array1, rightPos1, array2, rightPos2)) {
        return FALSE;
    }

    if (leftPos1 > -1) {
        int result = isSameBst((array1 + leftPos1), size1 - leftPos1, (array2 + leftPos2), size2 - leftPos2, *array1, TRUE);
        if (FALSE == result) {
            return FALSE;
        }
    }
    if (rightPos1 > -1) {
        int result = isSameBst((array1 + rightPos1), size1 - rightPos1, (array2 + rightPos2), size2 - rightPos2, *array1, TRUE);
        if (FALSE == result) {
            return FALSE;
        }
    }
    return TRUE;
}

int main ()
{
    int a[] = { 5, 6, 2, 7, 4 };
    int b[] = { 5, 6, 7, 2, 4 };
    printf ("%s\n", (isSameBst(a, 5, b, 5, 0, FALSE) ? "yes" : "no"));
    return 0;
}
Ответил 16/03/2013 в 18:30
источник пользователем

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