Advertisement
nachtvaohal

remove-node

Feb 17th, 2024
63
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Kotlin 4.84 KB | None | 0 0
  1. import java.util.*
  2.  
  3. // <template>
  4. data class Node(var left: Node?, var right: Node?, var value: Int)
  5. // <template>
  6.  
  7.  
  8. /**
  9.  *
  10.  *
  11.  * ПРИНЦИП РАБОТЫ
  12.  *
  13.  *
  14.  * ДОКАЗАТЕЛЬСТВО КОРРЕКТНОСТИ
  15.  * На место удаляемой вершины можно поставить
  16.  * * самую правую вершину в левом поддереве (наибольшую из поддерева)
  17.  * * самую левую вершину в правом поддереве
  18.  *
  19.  * ВРЕМЕННАЯ СЛОЖНОСТЬ
  20.  *
  21.  * ПРОСТРАНСТВЕННАЯ СЛОЖНОСТЬ
  22.  *
  23.  * @param root корень дерева
  24.  * @param key значение, которое нужно удалить
  25.  *
  26.  * @return корень изменённого дерева
  27.  */
  28. fun remove(root: Node?, key: Int): Node? {
  29.     if (root == null) {
  30.         return null
  31.     }
  32.     val parents = Stack<Node>()
  33.     val toRemove = findNodeByKey(root, key, parents)
  34.     // 0. Удаляемый узел не найден
  35.     if (toRemove == null) {
  36.         return root
  37.     }
  38.     // 1. Если дерево состояло из одной вершины, то после её удаления дерева не останется
  39.     if (toRemove.value == root.value && root.isLeaf()) {
  40.         return null
  41.     }
  42.     // 2. Если мы удаляем лист, то дерево останется одним деревом и не распадётся на части
  43.     val parentOfNodeToRemove = if (parents.size == 0) null else parents.pop()
  44.     return if (parentOfNodeToRemove != null) {
  45.         val replacingNode = findReplacementNode(toRemove)
  46.         if (replacingNode == toRemove) {
  47.             if (parentOfNodeToRemove.value > replacingNode.value) {
  48.                 parentOfNodeToRemove.left = null
  49.             } else {
  50.                 parentOfNodeToRemove.right = null
  51.             }
  52.         } else {
  53.             replacingNode.right = toRemove.right
  54.             if (parentOfNodeToRemove.value > replacingNode.value) {
  55.                 parentOfNodeToRemove.left = replacingNode
  56.             } else {
  57.                 parentOfNodeToRemove.right = replacingNode
  58.             }
  59.         }
  60.         root
  61.     } else {
  62.         if (toRemove.left != null) {
  63.             val maxInLeftTree = findReplacementNode(toRemove)
  64.             maxInLeftTree.right = toRemove.right
  65.             maxInLeftTree.left = toRemove.left
  66.             maxInLeftTree
  67.         } else {
  68.             toRemove.right
  69.         }
  70.     }
  71. }
  72.  
  73. /**
  74.  * Найти узел по ключу с сохранением родителя найденной ноды в переданном стеке.
  75.  *
  76.  * @param root корень дерева
  77.  * @param key ключ, по которому осуществляется поиск
  78.  * @param parents стек, в котором сохраняется родитель найденного узла
  79.  *
  80.  * @return найденный узел
  81.  * @return null, если узел не был найден
  82.  */
  83. fun findNodeByKey(root: Node?, key: Int, parents: Stack<Node>): Node? {
  84.     if (root == null) {
  85.         parents.clear()
  86.         return null
  87.     }
  88.     if (root.value == key) {
  89.         return root
  90.     }
  91.     parents.push(root)
  92.     return if (key < root.value) {
  93.         findNodeByKey(root.left, key, parents)
  94.     } else {
  95.         findNodeByKey(root.right, key, parents)
  96.     }
  97. }
  98.  
  99. /**
  100.  * Найти наибольший элемент в левом поддереве удаляемого узла.
  101.  *
  102.  * @param toDelete удаляемый элемент
  103.  * @return наибольший (самый правый) элемент в левом поддереве удаляемого элемента [toDelete], либо сам [toDelete]
  104.  */
  105. fun findReplacementNode(toDelete: Node): Node {
  106.     if (toDelete.isLeaf()) {
  107.         return toDelete
  108.     }
  109.  
  110.     val maxRight = if (toDelete.left == null) {
  111.         extractMax(toDelete.right!!)
  112.     } else {
  113.         extractMax(toDelete.left!!)
  114.     }
  115.     if (toDelete.right == maxRight) {
  116.         toDelete.right = null
  117.     }
  118.     return maxRight
  119. }
  120.  
  121. /**
  122.  * Извлечь наибольший узел из переданного узла.
  123.  *
  124.  * @param node поддерево, в котором нужно найти наибольший узел
  125.  * @return наибольший узел или само поддерево, если оно является единственным узлом
  126.  */
  127. fun extractMax(node: Node): Node {
  128.     val max = if (node.right != null) {
  129.         extractMax(node.right!!)
  130.     } else {
  131.         node
  132.     }
  133.     // удаление наибольшего узла из его предка
  134.     if (node.right == max) {
  135.         node.right = null
  136.     }
  137.     return max
  138. }
  139.  
  140. private fun Node.isLeaf(): Boolean {
  141.     return right == null && left == null
  142. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement