2015-07-04 4 views
1

Преемник элемента в BST является преемником элемента в отсортированном порядке , определяемом обходным порядком. Поиск преемника , когда каждый узел имеет указатель на его родительский узел, представлен в учебнике алгоритмов CLRS (Введение в алгоритмы с помощью MIT ).Найти первый ключ больше, чем X в двоичном дереве поиска

Есть ли способ найти первое значение, которое больше X без parent в структуре? Как:

typedef struct tree tree; 
struct tree{ 
    int value; 
    tree *left; 
    tree *right; 
}; 

//Function: 

tree *find_first_bigger(tree *t, int x){} 

Я пытался работать:

tree *find_first_bigger(tree *t, int x){ 
    if(t == NULL) 
     return NULL; 

    if((*t)->value > x) 
     find_first_bigger((*t)->left, x); 

    else if((*t)->value < x) 
     find_first_bigger((*t)->right), x); 
    else if((*t)->value == x){ 
     if((*t)->right != NULL) 
     return tree_first_bigger((*t)->right); 
     else 
     return tree; 
    } 
} 

В этом примере (он использует букву, но там его не проблема), если я пытаюсь искать первый больше, чем N (он должен вернуться me O) но он возвращает меня N.

Search Binary Tree

+0

Я думаю, вы должны положить базовый регистр (если текущий узел равен нулю) для этой рекурсивной функции, чтобы остановить, если в дереве нет большего ключа, чем X. Также вы должны проверить, найден ли ключ и вернуть его. – Wazaaaap

+0

@PlayHardGoPro Не беспокойтесь о downvote, мое решение на 100% правильное. –

ответ

0

Вы сделали 90% от job.Allow мне сделать оставшиеся 10%.

Поскольку т является указателем на структуру, которую вы должны использовать t-> левый вместо (* т) -> левый и то же самое относится и при доступе к правой и значение, полей структуры.

Теперь Просто измените функцию:

Добавить это как первой строке функции

static tree* PTR=NULL; 

Измените второе, если условие в:

Измените второе, если условие равно:

else if(t->value == x) 
{ 
    if(t->right != NULL) 
    { 
     t=t->right; 
     while(t->left!=NULL) 
      t=t->left; 
     return t; 
    } 
    else return PTR; 
} 

Поэтому правильная функция

tree *find_first_bigger(tree *t, int x) 
{ 
    static tree* PTR=NULL; 
    if(t == NULL) 
     return NULL; 
    if(t->value > x) 
    { 
     PTR=t; 
     find_first_bigger(t->left, x); 
    } 
    else if(t->value < x) 
     find_first_bigger(t->right, x); 
    else if(t->value == x) 
    { 
     if(t->right != NULL) 
     { 
      t=t->right; 
      while(t->left!=NULL) 
       t=t->left; 
      return t; 
     } 
     else return PTR; 
    } 
} 

В основной функции, если указатель Возвращается NULL, это означает, что: сам ключ является самым большим ключом. Не стесняйтесь ответить на любые вопросы.

+0

downvoter: Пожалуйста, объясните. –

+0

Мое решение работает корректно во всех тестовых случаях, все еще снижается? Также я предоставил минимальную модификацию исходного кода. –

+0

Человек, ты мой герой! Я не мог заставить его работать omg. Глядя на ваш код, я полагаю, что трюк здесь был статическим значением, верно? Не могли бы вы просто объяснить мне, что я не видел, чтобы заставить его работать? Кстати, ваш код чист, красив и отлично работает! Большое спасибо Данте! – PlayHardGoPro

-1

Некоторые изменения, которые вы можете сделать в вашем коде:

  • Вы должны возвращать значения из рекурсивных вызовов

  • Если значение не найдено, вернуть NULL. Это означает возвращение NULL, если t->right == NULL на последних if.

  • При перемещении влево, если значение там не найдено, ответом должен быть сам узел. В случае N это последний узел, где мы поворачиваем налево: O. Если бы это было P, ответ был бы T.

После всех этих изменений, код должен выглядеть следующим образом:

tree *find_first_bigger(tree *t, int x){ 
    if(t == NULL) 
     return NULL; 

    if(t->value > x) { 
     tree *answer = find_first_bigger(t->left, x); 
     if (answer != NULL) 
      return answer; 
     return t; 
    } else if(t->value < x) { 
     return find_first_bigger(t->right, x); 
    } else if(t->value == x) { 
     if (t->right != NULL) 
      return tree_first_bigger(t->right); 
     return NULL; 
    } 
} 

Вы можете найти весь код, я использовал для тестирования in this gist.

-1

В вашем вопросе вам показалось, что вы хотите узнать InOrderSuccessor() данного значения 'x'.

Если «x» не обязательно существует в дереве, нам нужно изменить алгоритм. Учитывая приведенный вами пример и инструкцию о проблеме, вот код для поиска следующего элемента в BST.

Основные случаи:

  • Нет больше элемент существует, потому что «х» является самым большим.
  • «x» имеет ребенка в правильном направлении?
  • ДА: получите самый левый дочерний элемент справа от дерева.
  • НЕТ: возвращение родителя.

Главное замечание состоит в том, что мы не обновляем указатель родителя, всякий раз, когда мы идем прямо в дерево.

tree *ptr = root; 
    tree *prnt = NULL; 
    while (ptr != NULL) { 
     if (x == ptr->key) { 
      if (ptr->right != NULL) { 
       return GetLeftMostChild(ptr->right); 
      } else { 
       return prnt; 
      } 
     } else if (x > ptr->key) { 
      ptr = ptr->right; 
     } else { 
      prnt = ptr; 
      ptr = ptr->left; 
     } 
    } 

Вот определение для leftMostChild()

tree *GetLeftMostChild(tree *n) { 
    tree *ptr = n; 
    while (ptr->left != NULL) { 
     ptr = ptr->left; 
    } 
    return ptr; 
} 
+0

Я считаю, что вы можете просто заменить весь блок 'if (prnt! = NULL)' на 'return prnt' (** Примечание: ** OP запросил возврат указателя, а не следующего самого' int'). Проверка на 'if (prnt! = NULL)' не требуется, потому что есть либо значение указателя, либо вы будете возвращать NULL' на основе вашей инициализации 'tree * prnt = NULL;' (что и произойдет, если вы «ломаете», так как возврат функции - «return prnt;») –

+0

@ DavidC.Rankin, отредактированный код на основе вашего ввода – KalyanS

+0

Это имеет смысл. Единственным другим nit является 'return GetLeftMostChild (ptr-> right) -> key;' должен быть 'return GetLeftMostChild (ptr-> right);' для того, чтобы вернуть узел вместо значения. Причина, по которой вы не хотите возвращать значение, находится в событии 'if (x == ptr-> key)' и 'if (ptr-> right == NULL)', вы segfault, когда вы «ломаете» и пытаетесь to 'return prnt-> key;' (что является попыткой разыменовать указатель «NULL») –

Смежные вопросы