Реализация ES6 структуры данных двоичного дерева поиска с поддержкой TypeScript.
Ознакомьтесь с рекомендациями по участию, чтобы узнать больше о том, как перевести этот документ на другие языки.
yarn add binstree
npm install binstree
Бинарное дерево поиска — это корневая структура данных двоичного дерева, узлы которой содержат уникальный key
и связанное value
и указывают на два различающихся left
и right
поддерева. Дерево удовлетворяет свойству двоичного поиска, поэтому ключ в каждом узле больше, чем любой ключ, хранящийся в левом поддереве, и меньше, чем любой ключ, хранящийся в правом поддереве. Неизбежным результатом этого принципа являются операции с деревьями, которые получают большую выгоду, поскольку в среднем каждое сравнение ключей позволяет операциям пропустить около половины дерева, так что каждая вставка, удаление или поиск занимает время, пропорциональное логарифму числа узлов. хранится в дереве.
Binstree предоставляет цепной API, который можно использовать с помощью простого и минимального синтаксиса, что позволяет эффективно комбинировать методы.
Примеры использования также можно найти в test
каталоге.
'use strict' ;
const { Tree , Node } = require ( 'binstree' ) ;
const tree = new Tree ( ) ;
//=> Tree { root: null }
tree . insert ( 10 , 'A' ) ;
// => Tree { root: Node { left: null, right: null, key: 10, value: 'A' } }
tree . root ;
//=> Node { left: null, right: null, key: 10, value: 'A' }
const node = new Node ( 10 , 'A' ) ;
tree . root . key === node . key ;
//=> true
tree . root . value === node . value ;
//=> true
tree . insert ( 5 , 'B' ) . insert ( 15 , 'C' ) . root ;
//=> Node { left: [Node], right: [Node], key: 10, value: 'A' }
tree . root . left ;
//=> Node { left: null, right: null, key: 5, value: 'B' }
tree . root . right ;
//=> Node { left: null, right: null, key: 15, value: 'C' }
tree . insert ( 2 , 'D' ) . insert ( 7 , 'E' ) . insert ( 12 , 'F' ) . insert ( 20 , 'G' ) ;
tree . search ( 5 ) ;
//=> Node { key: 5, value: 'B',
// left: Node { left: null, right: null, key: 2, value: 'D' },
// right: Node { left: null, right: null, key: 7, value: 'E' } }
tree . search ( 15 ) ;
//=> Node { key: 15, value: 'C',
// left: Node { left: null, right: null, key: 12, value: 'F' },
// right: Node { left: null, right: null, key: 20, value: 'G' } }
tree . includes ( 12 ) ;
//=> true
tree . includes ( 100 ) ;
//=> false
tree . height ( ) ;
//=> 2
tree . isBalanced ( ) ;
//=> true
tree . remove ( 10 ) . root ;
//=> Node { key: 12, value: 'F',
// left: Node { left: [Node], right: [Node], key: 5, value: 'B' },
// right: Node { left: null, right: [Node], key: 15, value: 'C' } }
tree . isBalanced ( ) ;
//=> false
insert(key, value)
Tree
Изменяет дерево, вставляя новый узел в соответствующее место.
key
Number
Может быть любым числом, которое будет соответствовать key
создаваемого узла. Каждый узел имеет свой уникальный key
.
value
Any
Может быть любым значением, которое будет храниться в созданном узле.
const { Tree } = require ( 'binstree' ) ;
const tree = new Tree ( ) ;
tree . insert ( 10 , 'A' ) ;
// => Tree { root: Node { key: 10, value: 'A', left: null, right: null } }
root
Node | null
Возвращает корневой узел дерева. Если дерево пусто, возвращается null
.
const { Tree } = require ( 'binstree' ) ;
const tree = new Tree ( ) ;
tree . insert ( 10 , 'A' ) ;
// => Tree { root: Node { key: 10, value: 'A', left: null, right: null } }
tree . root ;
// => Node { key: 10, value: 'A', left: null, right: null }
isEmpty()
Boolean
Определяет, пусто ли дерево, возвращая true
или false
в зависимости от ситуации.
const { Tree } = require ( 'binstree' ) ;
const tree = new Tree ( ) ;
tree . insert ( 10 , 'A' ) ;
tree . isEmpty ( ) ;
// => false
remove(key)
Tree
Изменяет дерево, удаляя узел, соответствующий key
аргументу.
key
Number
Может быть любым числом, соответствующим key
существующего узла.
const { Tree } = require ( 'binstree' ) ;
const tree = new Tree ( ) ;
tree . insert ( 10 , 'A' ) ;
tree . remove ( 10 ) ;
//=> Tree { root: null }
includes(key)
Boolean
Определяет, содержит ли дерево узел с определенным key
, возвращая true
или false
в зависимости от ситуации.
key
Number
key
узла для поиска.
const { Tree } = require ( 'binstree' ) ;
const tree = new Tree ( ) ;
tree . insert ( 10 , 'A' ) . insert ( 5 , 'B' ) ;
tree . includes ( 10 ) ;
// => true
tree . includes ( 25 ) ;
// => false
tree . includes ( 5 ) ;
// => true
search(key)
Node | null
Определяет, содержит ли дерево узел с определенным key
, возвращая целевой узел или null
в зависимости от ситуации.
key
Number
key
узла для поиска.
const { Tree } = require ( 'binstree' ) ;
const tree = new Tree ( ) ;
tree . insert ( 10 , 'A' ) . insert ( 5 , 'B' ) ;
tree . search ( 10 ) ;
// => Node { key: 10, value: 'A', left: [Node], right: null }
tree . search ( 25 ) ;
// => null
tree . search ( 5 ) ;
// => Node { key: 5, value: 'B', left: null, right: null }
min()
Node | null
Возвращает самый левый узел дерева, то есть узел, соответствующий минимальному key
.
const { Tree } = require ( 'binstree' ) ;
const tree = new Tree ( ) ;
tree . insert ( 10 , 'A' ) . insert ( 5 , 'B' ) . insert ( 0 , 'C' ) ;
tree . min ( ) ;
// => Node { key: 0, value: 'C', left: null, right: null }
max()
Node | null
Возвращает самый правый узел дерева, то есть узел, соответствующий максимальному key
.
const { Tree } = require ( 'binstree' ) ;
const tree = new Tree ( ) ;
tree . insert ( 10 , 'A' ) . insert ( 15 , 'B' ) . insert ( 25 , 'C' ) ;
tree . max ( ) ;
// => Node { key: 25, value: 'C', left: null, right: null }
size()
Number
Возвращает общее количество узлов, находящихся в дереве.
const { Tree } = require ( 'binstree' ) ;
const tree = new Tree ( ) ;
tree . insert ( 10 , 'A' ) . insert ( 15 , 'B' ) . insert ( 25 , 'C' ) ;
tree . size ( ) ;
// => 3
height()
Number
Возвращает максимальное расстояние любого листового узла от корня. Если дерево пусто, возвращается -1
.
const { Tree } = require ( 'binstree' ) ;
const tree = new Tree ( ) ;
tree . insert ( 10 , 'A' ) ;
tree . height ( ) ;
// => 0
tree . insert ( 15 , 'B' ) . insert ( 25 , 'C' ) . insert ( 35 , 'D' ) ;
tree . height ( ) ;
//=> 3
inOrder(fn)
Tree
Применяет к дереву обход по порядку (обход в глубину — LNR) и выполняет предоставленную функцию fn
на каждом пройденном узле без изменения самого дерева.
fn
Function
Функция, выполняемая на каждом узле.
const { Tree } = require ( 'binstree' ) ;
const tree = new Tree ( ) ;
tree . insert ( 10 , 'A' ) . insert ( 5 , 'B' ) . insert ( 15 , 'C' ) ;
tree . inOrder ( node => console . log ( node . key ) ) ;
// => 5
// 10
// 15
preOrder(fn)
Tree
Применяет к дереву обход предварительного порядка (обход в глубину — NLR) и выполняет предоставленную функцию fn
на каждом пройденном узле без изменения самого дерева.
fn
Function
Функция, выполняемая на каждом узле.
const { Tree } = require ( 'binstree' ) ;
const tree = new Tree ( ) ;
tree . insert ( 10 , 'A' ) . insert ( 5 , 'B' ) . insert ( 15 , 'C' ) ;
tree . preOrder ( node => console . log ( node . key ) ) ;
// => 10
// 5
// 15
postOrder(fn)
Tree
Применяет обход в обратном порядке (обход в глубину — LRN) к дереву и выполняет предоставленную функцию fn
на каждом пройденном узле без изменения самого дерева.
fn
Function
Функция, выполняемая на каждом узле.
const { Tree } = require ( 'binstree' ) ;
const tree = new Tree ( ) ;
tree . insert ( 10 , 'A' ) . insert ( 5 , 'B' ) . insert ( 15 , 'C' ) ;
tree . postOrder ( node => console . log ( node . key ) ) ;
// => 5
// 15
// 10
outOrder(fn)
Tree
Применяет обход вне порядка (обход в глубину — RNL) к дереву и выполняет предоставленную функцию fn
на каждом пройденном узле без изменения самого дерева.
fn
Function
Функция, выполняемая на каждом узле.
const { Tree } = require ( 'binstree' ) ;
const tree = new Tree ( ) ;
tree . insert ( 10 , 'A' ) . insert ( 5 , 'B' ) . insert ( 15 , 'C' ) ;
tree . outOrder ( node => console . log ( node . key ) ) ;
// => 15
// 10
// 5
levelOrder(fn)
Tree
Применяет к дереву обход по уровню (обход в ширину) и выполняет предоставленную функцию fn
на каждом пройденном узле без изменения самого дерева.
fn
Function
Функция, выполняемая на каждом узле.
const { Tree } = require ( 'binstree' ) ;
const tree = new Tree ( ) ;
tree . insert ( 10 , 'A' ) . insert ( 5 , 'B' ) . insert ( 15 , 'C' ) ;
tree . levelOrder ( node => console . log ( node . key ) ) ;
// => 10
// 5
// 15
clear()
Tree
Изменяет дерево, удаляя все существующие узлы и возвращая его пустым.
const { Tree } = require ( 'binstree' ) ;
const tree = new Tree ( ) ;
tree . insert ( 10 , 'A' ) . insert ( 5 , 'B' ) . insert ( 15 , 'C' ) ;
//=> Tree { root: Node { left: [Node], right: [Node], key: 3, value: 'A' } }
tree . size ( ) ;
//=> 3
tree . clear ( ) ;
//=> Tree { root: null } }
tree . size ( ) ;
//=> 0
toArray()
Array<Node>
Применяет упорядоченный обход к дереву и сохраняет каждый пройденный узел в массиве. Массив возвращается в конце обхода.
const { Tree } = require ( 'binstree' ) ;
const tree = new Tree ( ) ;
tree . insert ( 10 , 'A' ) . insert ( 5 , 'B' ) . insert ( 15 , 'C' ) . insert ( 3 , 'D' ) . insert ( 20 , 'F' ) ;
tree . toArray ( ) ;
//=> [
// Node { left: null, right: null, key: 3, value: 'D' },
// Node { left: [Node], right: null, key: 5, value: 'B' },
// Node { left: [Node], right: [Node], key: 10, value: 'A' },
// Node { left: null, right: [Node], key: 15, value: 'C' },
// Node { left: null, right: null, key: 20, value: 'F' }
// ]
toPairs()
Array<[Number, Any]>
Применяет упорядоченный обход к дереву и для каждого пройденного узла сохраняет в n
-кортеже, где n
размер дерева, упорядоченную пару/2-кортеж, где первым элементом является number
соответствующее key
дерева. пройденный узел, а последнее — значение типа any
, соответствующее value
хранящемуся в пройденном узле. n
-кортеж возвращается в конце обхода.
const { Tree } = require ( 'binstree' ) ;
const tree = new Tree ( ) ;
tree . insert ( 10 , 'A' ) . insert ( 5 , 'B' ) . insert ( 15 , 'C' ) . insert ( 3 , 'D' ) . insert ( 20 , 'F' ) ;
tree . toPairs ( ) ;
//=> [ [3, 'D'], [5, 'B'], [10, 'A'], [15, 'C'], [20, 'F'] ]
leafNodes()
Array<Node>
Применяет упорядоченный обход к дереву и сохраняет каждый пройденный листовой узел (узел без дочерних элементов) в массиве. Массив возвращается в конце обхода.
const { Tree } = require ( 'binstree' ) ;
const tree = new Tree ( ) ;
tree . insert ( 10 , 'A' ) . insert ( 5 , 'B' ) . insert ( 15 , 'C' ) ;
tree . leafNodes ( ) ;
//=> [
// Node { left: null, right: null, key: 5, value: 'B' },
// Node { left: null, right: null, key: 15, value: 'C' }
// ]
fullNodes()
Array<Node>
Применяет упорядоченный обход к дереву и сохраняет каждый пройденный полный узел (узел с двумя ненулевыми дочерними элементами) в массиве. Массив возвращается в конце обхода.
const { Tree } = require ( 'binstree' ) ;
const tree = new Tree ( ) ;
tree . insert ( 10 , 'A' ) . insert ( 5 , 'B' ) . insert ( 15 , 'C' ) ;
tree . fullNodes ( ) ;
//=> [
// Node { left: [Node], right: [Node], key: 10, value: 'A' }
// ]
partialNodes()
Array<Node>
Применяет упорядоченный обход к дереву и сохраняет каждый частичный узел (узел с одним ненулевым дочерним элементом) в массиве. Массив возвращается в конце обхода.
const { Tree } = require ( 'binstree' ) ;
const tree = new Tree ( ) ;
tree . insert ( 10 , 'A' ) . insert ( 5 , 'B' ) . insert ( 15 , 'C' ) . insert ( 20 , 'D' ) . insert ( 3 , 'E' ) ;
tree . partialNodes ( ) ;
//=> [
// Node { left: [Node], right: null, key: 5, value: 'B' },
// Node { left: null, right: [Node], key: 15, value: 'C' }
// ]
isBalanced()
Boolean
Возвращает true
если дерево сбалансировано по высоте, что означает, что его левое поддерево сбалансировано, его правое поддерево сбалансировано и разница между высотами левого и правого поддерева не превышает 1. В в любом другом случае метод возвращает false
.
const { Tree } = require ( 'binstree' ) ;
const tree = new Tree ( ) ;
tree . insert ( 10 , 'A' ) . insert ( 5 , 'B' ) . insert ( 15 , 'C' ) ;
tree . isBalanced ( ) ;
//=> true
tree . insert ( 20 , 'D' ) . insert ( 30 , 'E' ) ;
tree . isBalanced ( ) ;
//=> false
isComplete()
Boolean
Метод возвращает true
если дерево представляет собой полное двоичное дерево поиска, что означает, что каждый уровень, за исключением, возможно, последнего, полностью заполнен, а все узлы расположены как можно дальше влево. В любом другом случае метод возвращает false.
const { Tree } = require ( 'binstree' ) ;
const tree = new Tree ( ) ;
tree . insert ( 10 , 'A' ) . insert ( 5 , 'B' ) . insert ( 15 , 'C' ) ;
tree . isComplete ( ) ;
//=> true
tree . insert ( 3 , 'D' ) ;
tree . isComplete ( ) ;
//=> true
tree . insert ( 20 , 'E' ) ;
tree . isComplete ( ) ;
//=> false
isFull()
Boolean
Метод возвращает true
если все узлы, находящиеся в дереве, являются либо листовыми, либо полными узлами. В любом другом случае (степень узла равна 1) метод возвращает false
.
const { Tree } = require ( 'binstree' ) ;
const tree = new Tree ( ) ;
tree . insert ( 10 , 'A' ) . insert ( 5 , 'B' ) . insert ( 15 , 'C' ) ;
tree . isFull ( ) ;
//=> true
tree . insert ( 8 , 'D' ) ;
tree . isFull ( ) ;
//=> false
isPerfect()
Boolean
Метод возвращает true
если все внутренние узлы, находящиеся в дереве, являются полными узлами (степень узла равна 2) и все конечные узлы находятся на одном уровне высоты. В любом другом случае (степень узла равна 1 или листовой и полный узлы находятся на одном уровне высоты) метод возвращает false
.
const { Tree } = require ( 'binstree' ) ;
const tree = new Tree ( ) ;
tree . insert ( 10 , 'A' ) . insert ( 5 , 'B' ) . insert ( 15 , 'C' ) ;
tree . isPerfect ( ) ;
//=> true
tree . insert ( 3 , 'D' ) . insert ( 7 , 'E' ) . insert ( 12 , 'F' ) . insert ( 20 , 'G' ) ;
tree . isPerfect ( ) ;
//=> true
tree . insert ( 1 , 'H' ) ;
tree . isPerfect ( ) ;
//=> false
Наряду с открытым классом Tree
также доступен класс Node
, который в основном полезен для целей тестирования, поскольку его можно использовать для сравнения узлов дерева. Класс имеет метод бинарного конструктора с key
и параметром value
, соответствующим ключу и значению, хранящимся в созданном экземпляре, соответственно.
key
Number
key
, соответствующий экземпляру узла.
const { Node } = require ( 'binstree' ) ;
const node = new Node ( 10 , 'A' ) ;
// => { key:10, value: 'A', left: null, right: null }
node . key ;
//=> 10
value
Any
Значение, которое содержит узел.
const { Node } = require ( 'binstree' ) ;
const node = new Node ( 10 , 'A' ) ;
// => { key: 10, value: 'A', left: null, right: null }
node . value ;
//=> 'A'
node . value = 'B'
// => { key: 10, value: 'B', left: null, right: null }
left
Node | null
Левое поддерево, на которое указывает узел.
const { Tree } = require ( 'binstree' ) ;
const tree = new Tree ( ) ;
tree . insert ( 10 , 'A' ) . root ;
// => { key: 10, value: 'A', left: null, right: null }
tree . root . left ;
//=> null
tree . insert ( 5 , 'B' ) . root ;
// => { key: 10, value: 'A', left: { key: 5, value: 'B', left: null, right: null } , right: null }
tree . root . left ;
//=> { key: 5, value: 'B', left: null, right: null }
right
Node | null
Правое поддерево, на которое указывает узел.
const { Tree } = require ( 'binstree' ) ;
const tree = new Tree ( ) ;
tree . insert ( 10 , 'A' ) . root ;
// => { key: 10, value: 'A', left: null, right: null }
tree . root . right ;
//=> null
tree . insert ( 15 , 'B' ) . root ;
// => { key: 10, value: 'A', left: null , right: { key: 15, value: 'B', left: null, right: null } }
tree . root . right ;
//=> { key: 15, value: 'B', left: null, right: null }
children
Array<Node>
Возвращает массив, связывающийся с дочерними элементами экземпляра, где левый дочерний элемент, если он присутствует, является первым элементом массива, а правый дочерний элемент, если он присутствует, является последним элементом массива.
const { Tree } = require ( 'binstree' ) ;
const tree = new Tree ( ) ;
tree . insert ( 10 , 'A' ) . root . children ;
//=> []
tree . insert ( 5 , 'B' ) . insert ( 15 , 'C' ) . root . children ;
// => [
// { key: 5, value: 'B', left: null , right: null },
// { key: 15, value: 'C', left: null, right: null }
// ]
degree
Number
Возвращает количество поддеревьев, на которые указывает узел.
const { Tree } = require ( 'binstree' ) ;
const tree = new Tree ( ) ;
tree . insert ( 10 , 'A' ) . root . degree ;
//=> 0
tree . insert ( 5 , 'B' ) . root . degree ;
//=> 1
tree . insert ( 15 , 'C' ) . root . degree ;
//=> 2
height()
Number
Возвращает максимальное расстояние любого листового узла от экземпляра узла.
const { Tree } = require ( 'binstree' ) ;
const tree = new Tree ( ) ;
tree . insert ( 10 , 'A' ) . insert ( 15 , 'B' ) . insert ( 25 , 'C' ) . insert ( 35 , 'D' ) ;
tree . root . height ( ) ;
//=> 3
tree . root . right . height ( ) ;
//=> 2
isFull()
Boolean
Определяет, является ли узел полным узлом (имеет двух ненулевых дочерних узлов), возвращая true
или false
в зависимости от ситуации.
const { Tree } = require ( 'binstree' ) ;
const tree = new Tree ( ) ;
tree . insert ( 10 , 'A' ) . root . isFull ( ) ;
//=> false
tree . insert ( 5 , 'B' ) . insert ( 15 , 'C' ) . root . isFull ( ) ;
//=> true
isInternal()
Boolean
Определяет, является ли узел внутренним узлом (имеет хотя бы один ненулевой дочерний узел), возвращая true
или false
в зависимости от ситуации.
const { Tree } = require ( 'binstree' ) ;
const tree = new Tree ( ) ;
tree . insert ( 10 , 'A' ) . root . isInternal ( ) ;
//=> false
tree . insert ( 5 , 'B' ) . root . isInternal ( ) ;
//=> true
isLeaf()
Boolean
Определяет, является ли узел листовым узлом (не имеет дочерних элементов), возвращая true
или false
в зависимости от ситуации.
const { Tree } = require ( 'binstree' ) ;
const tree = new Tree ( ) ;
tree . insert ( 10 , 'A' ) . root . isLeaf ( ) ;
//=> true
tree . insert ( 5 , 'B' ) . root . isLeaf ( ) ;
//=> false
isLeftPartial()
Boolean
Определяет, является ли узел левым частичным узлом (имеет только один левый ненулевой дочерний узел), возвращая true
или false
в зависимости от ситуации.
const { Tree } = require ( 'binstree' ) ;
const tree = new Tree ( ) ;
tree . insert ( 10 , 'A' ) . root . isLeftPartial ( ) ;
//=> false
tree . insert ( 5 , 'B' ) . root . isLeftPartial ( ) ;
//=> true
isPartial()
Boolean
Определяет, является ли узел частичным узлом (имеет только один ненулевой дочерний узел), возвращая true
или false
в зависимости от ситуации.
const { Tree } = require ( 'binstree' ) ;
const tree = new Tree ( ) ;
tree . insert ( 10 , 'A' ) . root . isPartial ( ) ;
//=> false
tree . insert ( 15 , 'B' ) . root . isPartial ( ) ;
//=> true
isRightPartial()
Boolean
Определяет, является ли узел правым частичным узлом (имеет только один правый ненулевой дочерний узел), возвращая true
или false
в зависимости от ситуации.
const { Tree } = require ( 'binstree' ) ;
const tree = new Tree ( ) ;
tree . insert ( 10 , 'A' ) . root . isRightPartial ( ) ;
//=> false
tree . insert ( 15 , 'B' ) . root . isRightPartial ( ) ;
//=> true
toPair()
[Number, Any]
Возвращает упорядоченную пару/2-кортеж, где первый элемент — это число, соответствующее key
узла, а последний — значение, которое может быть любого типа, соответствующего value
, хранящемуся в узле.
const { Node , Tree } = require ( 'binstree' ) ;
const tree = new Tree ( ) ;
const node = new Node ( 5 , 'B' ) ;
node . toPair ( ) ;
//=> [5, 'B']
tree . insert ( 10 , 'A' ) . root . toPair ( ) ;
//=> [10, 'A']
Для получения дополнительной информации о том, как внести свой вклад в проект, пожалуйста, прочтите правила участия.
cd binstree
npm install
или yarn install
npm test
или yarn test
Массачусетский технологический институт