Проверьте, существует ли значение в отсортированном полном двоичном дереве
Опубликовано: 12 Января, 2022
Учитывая упорядоченное по уровням полное двоичное дерево, задача состоит в том, чтобы проверить, существует ли в нем ключ или нет. Полное двоичное дерево имеет все уровни, за исключением, возможно, последнего, полностью заполненного, со всеми узлами как можно дальше слева.
Примеры:
7 / 10 15 / / 17 20 30 35 / / 40 41 50 Ввод: Узел = 3 Выход: Нет Ввод: Узел = 7 Выход: Да Ввод: Узел = 30 Выход: Да
Рекомендуется: сначала попробуйте свой подход в {IDE}, прежде чем переходить к решению.
Подход Простым решением O (n) было бы полностью пройти по дереву и проверить значение ключа. Однако мы можем использовать информацию о том, что дерево отсортировано и работать лучше с точки зрения временной сложности.
- Узнайте уровень, на котором может существовать ключ. Начните с корневого узла и продолжайте движение влево, пока не встретите значение, превышающее значение ключа. Уровень до этого будет содержать ключ, если он вообще существует в дереве. Допустим, это уровень l .
- Теперь выполните двоичный поиск в узлах l . В отличие от обычного бинарного поиска, к узлам этого уровня нельзя получить прямой доступ. Однако путь от корня к каждому узлу на этом уровне может быть закодирован с использованием двоичной логики. Например, рассмотрим 3-й уровень в дереве примеров. Он может содержать до 2 3 = 8 узлов. В эти узлы можно попасть из корневого узла, идя влево, влево, влево; или идя налево, налево, направо; и так далее. Если слева обозначено 0, а справа - 1, то возможные способы достижения узлов на этом уровне могут быть закодированы как arr = [000, 001, 010, 011, 100, 101, 110, 111].
- Однако этот массив не нужно создавать, можно применить бинарный поиск, рекурсивно выбрав средний индекс и просто сгенерировав l- битный серый код этого индекса (см. Эту статью).
- В случае неполных путей просто проверьте левую часть массива. Например, закодированный путь 011 не соответствует никакому значению в дереве выборки. Поскольку дерево завершено, оно гарантирует, что справа больше не будет элементов.
- Если ключ найден, верните true, иначе верните false.
Below is the implementation of the above approach:
C++
// C++ implementation of the approach #include<bits/stdc++.h> using namespace std; /* Class containing left and right child of current node and key value*/ class Node { public : int data; Node *left, *right; Node( int item) { data = item; left = right = NULL; } }; /* Function to locate which level to check for the existence of key. */ int findLevel(Node *root, int data) { // If the key is less than the root, // it will certainly not exist in the tree // because tree is level-order sorted if (data < root->data) return -1; // If the key is equal to the root then // simply return 0 (zero"th level) if (data == root->data) return 0; int cur_level = 0; while ( true ) { cur_level++; root = root->left; // If the key is found in any leftmost element // then simply return true // No need for any extra searching if (root->data == data) return -2; // If key lies between the root data and // the left child"s data OR if key is greater // than root data and there is no level // underneath it, return the current level if (root->data < data && (root->left == NULL || root->left->data > data)) { break ; } } return cur_level; } /* Function to traverse a binary encoded path and return the value encountered after traversal. */ int traversePath(Node *root,vector< int > path) { for ( int i = 0; i < path.size(); i++) { int direction = path[i]; // Go left if (direction == 0) { // Incomplete path if (root->left == NULL) return -1; root = root->left; } // Go right else { // Incomplete path if (root->right == NULL) return -1; root = root->right; } } // Return the data at the node return root->data; } /* Function to generate gray code of corresponding binary number of integer i */ vector< int > generateGray( int n, int x) { // Create new arraylist to store // the gray code vector< int > gray ; int i = 0; while (x > 0) { gray.push_back(x % 2); x = x / 2; i++; } // Reverse the encoding till here reverse(gray.begin(),gray.end()); // Leftmost digits are filled with 0 for ( int j = 0; j < n - i; j++) gray.insert(gray.begin(), 0); return gray; } /* Function to search the key in a particular level of the tree. */ bool binarySearch(Node *root, int start, int end, int data, int level) { if (end >= start) { // Find the middle index int mid = (start + end) / 2; // Encode path from root to this index // in the form of 0s and 1s where // 0 means LEFT and 1 means RIGHT vector< int > encoding = generateGray(level, mid); // Traverse the path in the tree // and check if the key is found int element_found = traversePath(root, encoding); // If path is incomplete if (element_found == -1) // Check the left part of the level return binarySearch(root, start, mid - 1, data, level); if (element_found == data) return true ; // Check the right part of the level if (element_found < data) return binarySearch(root, mid + 1, end, data, level); // Check the left part of the level else return binarySearch(root, start, mid - 1, data, level); } // Key not found in that level return false ; } // Function that returns true if the // key is found in the tree bool findKey(Node *root, int data) { // Find the level where the key may lie int level = findLevel(root, data); // If level is -1 then return false if (level == -1) return false ; // If level is -2 i.e. key was found in any // leftmost element then simply return true if (level == -2) return true ; // Apply binary search on the elements // of that level return binarySearch(root, 0, ( int ) pow (2, level) - 1, data, level); } // Driver code int main() { /* Consider the following level-order sorted tree 5 / 8 10 / / 13 23 25 30 / / 32 40 50 */ Node* root = new Node(5); root->left = new Node(8); root->right = new Node(10); root->left->left = new Node(13); root->left->right = new Node(23); root->right->left = new Node(25); root->right->right = new Node(30); root->left->left->left = new Node(32); root->left->left->right = new Node(40); root->left->right->left = new Node(50); // Keys to be searched int arr[] = { 5, 8, 9 }; int n = sizeof (arr)/ sizeof ( int ); for ( int i = 0; i < n; i++) { if (findKey(root, arr[i])) cout << ( "Yes" ) << endl; else cout << ( "No" ) << endl; } } // This code is contributed by Arnab Kundu |
Java
// Java implementation of the approach import java.util.*; import java.io.*; /* Class containing left and right child of current node and key value*/ class Node { int data; Node left, right; public Node( int item) { data = item; left = right = null ; } } class GFG { /* Function to locate which level to check for the existence of key. */ public static int findLevel(Node root, int data) { // If the key is less than the root, // it will certainly not exist in the tree // because tree is level-order sorted if (data < root.data) return - 1 ; // If the key is equal to the root then // simply return 0 (zero"th level) if (data == root.data) return 0 ; int cur_level = 0 ; while ( true ) { cur_level++; root = root.left; // If the key is found in any leftmost element // then simply return true // No need for any extra searching if (root.data == data) return - 2 ; // If key lies between the root data and // the left child"s data OR if key is greater // than root data and there is no level // underneath it, return the current level if (root.data < data && (root.left == null || root.left.data > data)) { break ; } } return cur_level; } /* Function to traverse a binary encoded path and return the value encountered after traversal. */ public static int traversePath(Node root, ArrayList<Integer> path) { for ( int i = 0 ; i < path.size(); i++) { int direction = path.get(i); // Go left if (direction == 0 ) { // Incomplete path if (root.left == null ) return - 1 ; root = root.left; } // Go right else { // Incomplete path if (root.right == null ) return - 1 ; root = root.right; } } // Return the data at the node return root.data; } /* Function to generate gray code of corresponding binary number of integer i */ static ArrayList<Integer> generateGray( int n, int x) { // Create new arraylist to store // the gray code ArrayList<Integer> gray = new ArrayList<Integer>(); int i = 0 ; while (x > 0 ) { gray.add(x % 2 ); x = x / 2 ; i++; } // Reverse the encoding till here Collections.reverse(gray); // Leftmost digits are filled with 0 for ( int j = 0 ; j < n - i; j++) gray.add( 0 , 0 ); return gray; } /* Function to search the key in a particular level of the tree. */ public static boolean binarySearch(Node root, int start, int end, int data, int level) { if (end >= start) { // Find the middle index int mid = (start + end) / 2 ; // Encode path from r
РЕКОМЕНДУЕМЫЕ СТАТЬИ |