Как найти ближайший элемент к данному значению ключа в бинарном дереве поиска?

голоса
15

Учитывая BST с целыми значениями в качестве ключей Как найти ближайший узел к этому ключу в BST? БСТ представлен с использованием объекта узлов (Java). Ближайший будет для, например, 4,5,9 и если ключ 6 он вернется 5 ..

Задан 02/06/2011 в 01:50
источник пользователем
На других языках...                            


11 ответов

голоса
-1

Самое простое решением является рекурсивным Вашим деревом, так как при

  • Вы находите элемент
  • Вы достигаете лист. Этот случай вы должны сделать пару сравнения, чтобы определить, если ближайшее значение является лист или родитель листа.

До вас реализация.

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

голоса
18

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

Так что если вы искали ключ 3в следующем дереве вы бы в конечном итоге на узле , 6не находя совпадение , но ваше записанное значение будет , 2так как это был ближайший ключ всех узлов , которые вы уже пройденных ( 2, 7, 6).

                 2
              1      7
                   6   8
Ответил 02/06/2011 в 02:03
источник пользователем

голоса
11

Траверса занимает O (N) времени. Можно ли продолжить его в верхнем дне? как этот рекурсивный код:

Tnode * closestBST(Tnode * root, int val){
    if(root->val == val)
        return root;
    if(val < root->val){
        if(!root->left)
            return root;
        Tnode * p = closestBST(root->left, val);
        return abs(p->val-val) > abs(root->val-val) ? root : p;
    }else{
        if(!root->right)
            return root;
        Tnode * p = closestBST(root->right, val);
        return abs(p->val-val) > abs(root->val-val) ? root : p;
    }   
    return null;
}
Ответил 08/06/2011 в 09:41
источник пользователем

голоса
8

Она может быть решена в O (журнал * N *) время.

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

Алгоритм может быть реализован с помощью следующего кода C ++:

BinaryTreeNode* getClosestNode(BinaryTreeNode* pRoot, int value)
{
    BinaryTreeNode* pClosest = NULL;
    int minDistance = 0x7FFFFFFF;
    BinaryTreeNode* pNode = pRoot;
    while(pNode != NULL){
        int distance = abs(pNode->m_nValue - value);
        if(distance < minDistance){
            minDistance = distance;
            pClosest = pNode;
        }

        if(distance == 0)
            break;

        if(pNode->m_nValue > value)
            pNode = pNode->m_pLeft;
        else if(pNode->m_nValue < value)
            pNode = pNode->m_pRight;
    }

    return pClosest;
}

Вы можете посетить мой блог для более подробной информации.

Ответил 14/03/2013 в 03:19
источник пользователем

голоса
0

Это может быть сделано с помощью Queue и ArrayList. Очередь будет использоваться для выполнения первого поиска ширины на дереве. ArrayList, будет использоваться для хранения элемент дерева в ширину первого порядка. Вот код для реализации того же

Queue queue = new LinkedList();
ArrayList list = new ArrayList();
int i =0;
public Node findNextRightNode(Node root,int key)
{
    System.out.print("The breadth first search on Tree : \t");      
    if(root == null)
        return null;

    queue.clear();
    queue.add(root);

    while(!queue.isEmpty() )
    {
        Node node = (Node)queue.remove();
        System.out.print(node.data + " ");
        list.add(node);
        if(node.left != null) queue.add(node.left);
        if(node.right !=null) queue.add(node.right);            
    }

    Iterator iter = list.iterator();
    while(iter.hasNext())
        {
            if(((Node)iter.next()).data == key)
            {
                return ((Node)iter.next());
            }               
        }

    return null;
}
Ответил 15/01/2014 в 14:06
источник пользователем

голоса
2

Проблема с подходом «влево правильный обход и найти ближайший» является то, что она зависит над той последовательностью, в которой были введены элементы для создания BST. Если мы ищем 11 для последовательности BST 22, 15, 16, 6,14,3,1,90, описанный выше метод будет возвращать 15 в то время как правильный ответ 14. Единственный метод следует использовать рекурсию для обхода всех узлов, возвращая ближайший как результат рекурсивной функции. Это даст нам наиболее близкое значение

Ответил 02/06/2014 в 18:02
источник пользователем

голоса
9

Вот рекурсивное решение в Python:

def searchForClosestNodeHelper(root, val, closestNode):
    if root is None:
        return closestNode

    if root.val == val:
        return root

    if closestNode is None or abs(root.val - val) < abs(closestNode.val - val):
        closestNode = root

    if val < root.val:
        return searchForClosestNodeHelper(root.left, val, closestNode)
    else:
        return searchForClosestNodeHelper(root.right, val, closestNode)

def searchForClosestNode(root, val):
    return searchForClosestNodeHelper(root, val, None)
Ответил 21/06/2014 в 23:44
источник пользователем

голоса
0
void closestNode(Node root, int k , Node result) {
    if(root == null) 
    {
       return;      //currently result is null , so it  will be the result
    }
    if(result == null || Math.abs(root.data - k) < Math.abs(result.data - k) )
    {
      result == root;
    }
    if(k < root.data)
    {
    closestNode(root.left, k, result)
    } 
    else 
    {
        closestNode(root.right, k, result);
    }

}
Ответил 24/07/2016 в 05:45
источник пользователем

голоса
0

Ниже один работает с различными образцами, которые у меня есть.

public Node findNearest(Node root, int k) {
    if (root == null) {
        return null;
    }
    int minDiff = 0;
    Node minAt = root;
    minDiff = Math.abs(k - root.data);

    while (root != null) {
        if (k == root.data) {
            return root;
        }
        if (k < root.data) {
            minAt = updateMin(root, k, minDiff, minAt);
            root = root.left;
        } else if (k > root.data) {
            minAt = updateMin(root, k, minDiff, minAt);
            root = root.right;
        }

    }
    return minAt;
}

private Node updateMin(Node root, int k, int minDiff, Node minAt) {
    int curDif;
    curDif = Math.abs(k - root.data);
    if (curDif < minDiff) {
        minAt = root;
    }
    return minAt;
}
Ответил 04/02/2017 в 10:10
источник пользователем

голоса
0

Вот полный код Java, чтобы найти ближайший элемент в BST.

        package binarytree;

        class BSTNode {
            BSTNode left,right;
            int data;

            public BSTNode(int data) {
                this.data = data;
                this.left = this.right = null;
            }
        }

        class BST {
            BSTNode root;

            public static BST createBST() {
                BST bst = new BST();
                bst.root = new BSTNode(9);
                bst.root.left = new BSTNode(4);
                bst.root.right = new BSTNode(17);

                bst.root.left.left = new BSTNode(3);
                bst.root.left.right= new BSTNode(6);

                bst.root.left.right.left= new BSTNode(5);
                bst.root.left.right.right= new BSTNode(7);

                bst.root.right.right = new BSTNode(22);
                bst.root.right.right.left = new BSTNode(20);

                return bst;
            }
        }

        public class ClosestElementInBST {
            public static void main(String[] args) {
                BST bst = BST.createBST();
                int target = 18;
                BSTNode currentClosest = null;
                BSTNode closestNode = findClosestElement(bst.root, target, currentClosest);

                if(closestNode != null) {
                    System.out.println("Found closest node: " + closestNode.data);
                }
                else {
                    System.out.println("Couldn't find closest node.");
                }
            }

            private static BSTNode findClosestElement(BSTNode node, int target, BSTNode currentClosest) {
                if(node == null) return currentClosest;

                if(currentClosest == null || 
                        (currentClosest != null && (Math.abs(currentClosest.data - target) > Math.abs(node.data - target)))) {
                    currentClosest = node;
                }

               if(node.data == target) return node;

                else if(target < node.data) {
                    return findClosestElement(node.left, target, currentClosest);
                }

                else { //target > node.data
                    currentClosest = node;
                    return findClosestElement(node.right, target, currentClosest);
                }
            }

        }
Ответил 11/06/2018 в 20:33
источник пользователем

голоса
0

Здесь рабочий раствор в Java, которая использует характеристику BST и дополнительного целое число для хранения минимальной разницы

public class ClosestValueBinaryTree {
        static int closestValue;

        public static void closestValueBST(Node22 node, int target) {
            if (node == null) {
                return;
            }
            if (node.data - target == 0) {
                closestValue = node.data;
                return;
            }
            if (Math.abs(node.data - target) < Math.abs(closestValue - target)) {
                closestValue = node.data;
            }
            if (node.data - target < 0) {
                closestValueBST(node.right, target);
            } else {
                closestValueBST(node.left, target);
            }
        }
    }

Время работы сложность - O (LogN)

Время Пространства сложность - O (1)

Ответил 08/09/2018 в 18:23
источник пользователем

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