Data structure library, phase 2 (#4062)

* Revise RedBlackTree impl docs

* Revise RedBlackTree impl docs

* Revise RedBlackTree impl docs

* Revise RedBlackTree impl docs

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise RedBlackTree impl docs

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Fix typo

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise RedBlackTree impl docs

* Revise RedBlackTree impl docs

* Revise RedBlackTree impl

* Revise RedBlackTreeImpl docs

* Revise Fw/DataStructures

Reformat code

* Revise Fw/DataStructures

Fix compile errors on Linux

* Revise Fw/DataStructures

Fix compile errors on Linux

* Revise Fw/DataStructures

Fix compile errors on Linux

* Revise Fw/DataStructures

Fix compile errors on Linux

* Fix comments

* Revise Fw/DataStructures

Fix compile errors on Linux

* Revise ArrayMap docs

* Remove helper scripts

* Revise tests for Fw/DataStructures

* Fix spelling

* Fix Markdown link

* Fix uninitialized variable in test

* Fix uninitialized variable in test

* Fix "spelling"

Why is the spelling check enforcing arbitrary rules of style?

* Fix comments

* Revise RedBlackTree impl docs

* Start adding RedBlackTree impl

* Revise tests for ArraySetOrMapImpl

* Revise RedBlackTree impl

* Revise comment

* Revise comment

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise ArraySetOrMap impl

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Add RedBlackTree impl tester

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Fix comments

* Revise RedBlackTree impl

* Fix comments

* Revise comments

* Revise comments

* Revise comments

* Revise statement order for clarity

* Revise unit tests for RedBlackTree impl

* Revise RedBlackTree impl tests

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Add build and clean scripts

Working around regressions in the F Prime build system

* Revise build

Fix warnings

* Revise RedBlackTree impl and tests

* Revise tests for RedBlackTree impl

* Revise RedBlackTree impl and tests

* Revise RedBlackTree tests

Remove debug print statements

* Revise RedBlackTree impl tester

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise build script

* Revise RedBlackTree tests

* Revise RedBlackTree tests

* Revise RedBlackTree tests

* Revise RedBlackTree tests

* Revise RedBlackTree tests

* Revise RedBlackTree impl tests

* Revise RedBlackTree impl tests

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise RedBlackTree impl tests

* Revise RedBlackTree impl tests

* Revise RedBlackTree impl tests

* Revise RedBlackTree impl tests

* Revise RedBlackTree impl tests

* Revise RedBlackTree impl tests

* Revise RedBlackTree impl test

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise comment

* Revise RedBlackTree impl and tests

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise RedBlackTree impl

* Revise RedBlackTree impl tests

* Revise RedBlackTree impl tests

* Revise RedBlackTree impl

* Revise RedBlackTree impl tests

* Revise formatting

* Format code

* Revise docs

* Revise docs for Fw/DataStructures

* Revise Array and ExternalArray

Add static assertions

* Revise FifoQueue and Stack

Add static assertions

* Revise ArraySet and ArrayMap

Add static assertions

* Revise docs for ExternalRedBlackTreeMap

* Revise docs for ExternalRedBlackTreeSet

* Revise docs for RedBlackTreeMap

* Revise docs for RedBlackTreeSet

* Revise ExternalRedBlackTreeMap tests

* Refactor ExternalStackTester

* Revise ArrayMap tests

* Add RedBlackTreeMap

* Revise RedBlackTreeMap tests

* Revise RedBlackTreeMap

* Add ExternalRedBlackTreeSet

* Add missing file

* Revise SetConstIterator

* Revise ExternalRedBlackTreeSet tests

* Revise ExternalRedBlackTreeSet tests

* Revise ExternalRedBlackTreeSet tests

* Revise ExternalRedBlackTreeSet tests

* Revise ExternalRedBlackTreeSet tests

* Revise ExternalRedBlackTree tests

* Revise ExternalArraySet tests

* Revise ExternalArraySet tests

* Add RedBlackTreeSet

* Revise RedBlackTreeSet tests

* Refactor ArraySetTest

* Revise RedBlackTreeSetOrMapImpl docs

* Revise array initialization

* Revise comments

* Revise Array initialization

* Revise Array design and implementation

* Revert changes to Fw/DataStructures

* Revise Array

* Revise Array

* Revise Array

* Fix formatting

* Add SizedContainer base class

* Revise StackBase

Make it inherit from SizedContainer
Revise stack tests

* Revise MapBase

Make it inherit from SizedContainer
Revise tests

* Revise SetBase

Make it inherit from SizedContainer
Revise tests

* Revise DataStructures design

Add SizedContainer

* Revise SDD for DataStructures

* Revise DataStructures design

* Revise DataStructures design

* Revise DataStructures design

* Revise DataStructures design

* Fix spelling

* Revise zero-arg constructor for Array

* Revise Array interface

Make it consistent with the arrays generated by FPP

* Fix to assertion

* Format code

* Fix spelling

* Fix spelling

* Add -Wno-comment to suppress warnings for now

* Revise comments

* Revise diagrams

* Fix comment warnings on gcc

* Eliminate tabs

* Remove utility scripts

* Revise placement of break statements

* Rename function

getParentDirection --> getDirectionFromParent

* Add comment

* Add svg diagram

* Add svg diagram

* Add svg files

* Revise diagram

* Replace png with svg

* Replace png with svg

* Replace png with svg

* Revise comment

* Revise SDD for red-black tree

* Revise SDD for red-black tree
This commit is contained in:
Rob Bocchino 2025-10-06 13:26:23 -07:00 committed by GitHub
parent 20477ad9c8
commit e9d7f3ab66
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
99 changed files with 11121 additions and 25 deletions

View File

@ -33,6 +33,7 @@ baremetal
batchmode
BDV
bfree
BHn
bibtex
Bies
BINDIR
@ -42,6 +43,7 @@ bitwidth
bocchino
boolt
bsd
bst
BUFFERALLOCATE
BUFFERALLOCATIONFAILED
BUFFERGETOUT
@ -237,6 +239,7 @@ fio
fle
FNDELAY
fne
fontcolor
FONTPATH
foodoodie
foodoodiehoo
@ -279,6 +282,7 @@ gpiochip
gpioevent
gpiohandle
gpioline
GPT
Graphviz
grayscales
GROUNDINTERFACERULES
@ -286,9 +290,9 @@ GSE
gtags
gtest
gtimeout
GTK
Guire
GVCID
GPT
HACKSM
Handcoded
handleflags
@ -321,12 +325,14 @@ INCLUDEDIR
ine
initstate
inkscape
inorder
installable
intlimits
inttypes
INVALIDBUFFER
INVALIDHEADER
INVALIDHEADERHASH
invis
invisi
ioc
ioctl
@ -381,6 +387,7 @@ LOCALSTATEDIR
LOGGERRULES
LOGPACKET
lseek
LTK
lvar
LVL
lxml
@ -544,6 +551,7 @@ RATELIMITERTESTER
rawtime
RAWTIMETESTER
RBF
rbt
RCHILD
rcvd
rdwr
@ -692,8 +700,8 @@ tparam
TPP
trinomials
tts
typedef'ed
typedef
typedef'ed
uart
udiv
UDPSOCKET

View File

@ -15,14 +15,21 @@ set(UT_SOURCE_FILES
"${CMAKE_CURRENT_LIST_DIR}/test/ut/ExternalArraySetTest.cpp"
"${CMAKE_CURRENT_LIST_DIR}/test/ut/ExternalArrayTest.cpp"
"${CMAKE_CURRENT_LIST_DIR}/test/ut/ExternalFifoQueueTest.cpp"
"${CMAKE_CURRENT_LIST_DIR}/test/ut/ExternalRedBlackTreeMapTest.cpp"
"${CMAKE_CURRENT_LIST_DIR}/test/ut/ExternalRedBlackTreeSetTest.cpp"
"${CMAKE_CURRENT_LIST_DIR}/test/ut/ExternalStackTest.cpp"
"${CMAKE_CURRENT_LIST_DIR}/test/ut/FifoQueueTest.cpp"
"${CMAKE_CURRENT_LIST_DIR}/test/ut/RedBlackTreeMapTest.cpp"
"${CMAKE_CURRENT_LIST_DIR}/test/ut/RedBlackTreeSetOrMapImplTest.cpp"
"${CMAKE_CURRENT_LIST_DIR}/test/ut/RedBlackTreeSetTest.cpp"
"${CMAKE_CURRENT_LIST_DIR}/test/ut/STest/ArraySetOrMapImplTestRules.cpp"
"${CMAKE_CURRENT_LIST_DIR}/test/ut/STest/ArraySetOrMapImplTestScenarios.cpp"
"${CMAKE_CURRENT_LIST_DIR}/test/ut/STest/FifoQueueTestRules.cpp"
"${CMAKE_CURRENT_LIST_DIR}/test/ut/STest/FifoQueueTestScenarios.cpp"
"${CMAKE_CURRENT_LIST_DIR}/test/ut/STest/MapTestRules.cpp"
"${CMAKE_CURRENT_LIST_DIR}/test/ut/STest/MapTestScenarios.cpp"
"${CMAKE_CURRENT_LIST_DIR}/test/ut/STest/RedBlackTreeSetOrMapImplTestRules.cpp"
"${CMAKE_CURRENT_LIST_DIR}/test/ut/STest/RedBlackTreeSetOrMapImplTestScenarios.cpp"
"${CMAKE_CURRENT_LIST_DIR}/test/ut/STest/SetTestRules.cpp"
"${CMAKE_CURRENT_LIST_DIR}/test/ut/STest/SetTestScenarios.cpp"
"${CMAKE_CURRENT_LIST_DIR}/test/ut/STest/StackTestRules.cpp"

View File

@ -0,0 +1,177 @@
// ======================================================================
// \file ExternalRedBlackTreeMap.hpp
// \author bocchino
// \brief A map based on a red-black tree with external storage
// ======================================================================
#ifndef Fw_ExternalRedBlackTreeMap_HPP
#define Fw_ExternalRedBlackTreeMap_HPP
#include "Fw/DataStructures/MapBase.hpp"
#include "Fw/DataStructures/RedBlackTreeSetOrMapImpl.hpp"
#include "Fw/Types/Assert.hpp"
namespace Fw {
template <typename K, typename V>
class ExternalRedBlackTreeMap final : public MapBase<K, V> {
// ----------------------------------------------------------------------
// Friend class for testing
// ----------------------------------------------------------------------
template <typename KK, typename VV>
friend class ExternalRedBlackTreeMapTester;
public:
// ----------------------------------------------------------------------
// Public types
// ----------------------------------------------------------------------
//! The type of a const iterator
using ConstIterator = MapConstIterator<K, V>;
//! The type of a tree node
using Node = typename RedBlackTreeSetOrMapImpl<K, V>::Node;
//! The type of a tree node index
using Index = typename RedBlackTreeSetOrMapImpl<K, V>::Index;
public:
// ----------------------------------------------------------------------
// Public constructors and destructors
// ----------------------------------------------------------------------
//! Zero-argument constructor
ExternalRedBlackTreeMap() = default;
//! Constructor providing typed backing storage.
//! nodes must point to at least capacity elements of type Node.
//! freeNodes must point to at least capacity elements of type FwSizeType.
ExternalRedBlackTreeMap(Node* nodes, //!< The nodes
Index* freeNodes, //!< The free nodes
FwSizeType capacity //!< The capacity
)
: MapBase<K, V>() {
this->setStorage(nodes, freeNodes, capacity);
}
//! Constructor providing untyped backing storage.
//! data must be aligned according to getByteArrayAlignment().
//! data must contain at least getByteArraySize(capacity) bytes.
ExternalRedBlackTreeMap(ByteArray data, //!< The data,
FwSizeType capacity //!< The capacity
)
: MapBase<K, V>() {
this->setStorage(data, capacity);
}
//! Copy constructor
ExternalRedBlackTreeMap(const ExternalRedBlackTreeMap<K, V>& map) : MapBase<K, V>() { *this = map; }
//! Destructor
~ExternalRedBlackTreeMap() override = default;
public:
// ----------------------------------------------------------------------
// Public member functions
// ----------------------------------------------------------------------
//! operator=
ExternalRedBlackTreeMap<K, V>& operator=(const ExternalRedBlackTreeMap<K, V>& map) {
if (&map != this) {
this->m_impl = map.m_impl;
}
return *this;
}
//! Get the begin iterator
//! \return The iterator
ConstIterator begin() const override { return ConstIterator(this->m_impl.begin()); }
//! Clear the map
void clear() override { this->m_impl.clear(); }
//! Get the end iterator
//! \return The iterator
ConstIterator end() const override { return ConstIterator(this->m_impl.end()); }
//! Find a value associated with a key in the map
//! \return SUCCESS if the item was found
Success find(const K& key, //!< The key
V& value //!< The value
) const override {
return this->m_impl.find(key, value);
}
//! Get the capacity of the map (max number of entries)
//! \return The capacity
FwSizeType getCapacity() const override { return this->m_impl.getCapacity(); }
//! Get the size (number of entries)
//! \return The size
FwSizeType getSize() const override { return this->m_impl.getSize(); }
//! Insert a (key, value) pair in the map
//! \return SUCCESS if there is room in the map
Success insert(const K& key, //!< The key
const V& value //!< The value
) override {
return this->m_impl.insert(key, value);
}
//! Remove a (key, value) pair from the map
//! \return SUCCESS if the key was there
Success remove(const K& key, //!< The key
V& value //!< The value
) override {
return this->m_impl.remove(key, value);
}
//! Set the backing storage (typed data)
//! nodes must point to at least capacity elements of type Node.
//! freeNodes must point to at least capacity elements of type FwSizeType.
void setStorage(Node* nodes, //!< The nodes
Index* freeNodes, //!< The free nodes
FwSizeType capacity //!< The capacity
) {
this->m_impl.setStorage(nodes, freeNodes, capacity);
}
//! Set the backing storage (untyped data)
//! data must be aligned according to getByteArrayAlignment().
//! data must contain at least getByteArraySize(capacity) bytes.
void setStorage(ByteArray data, //!< The data
FwSizeType capacity //!< The capacity
) {
this->m_impl.setStorage(data, capacity);
}
public:
// ----------------------------------------------------------------------
// Public static functions
// ----------------------------------------------------------------------
//! Get the alignment of the storage for an RedBlackTreeSetOrMapImpl
//! \return The alignment
static constexpr U8 getByteArrayAlignment() { return RedBlackTreeSetOrMapImpl<K, V>::getByteArrayAlignment(); }
//! Get the size of the storage for an ExternalArray of the specified capacity,
//! as a byte array
//! \return The byte array size
static constexpr FwSizeType getByteArraySize(FwSizeType capacity //!< The capacity
) {
return RedBlackTreeSetOrMapImpl<K, V>::getByteArraySize(capacity);
}
private:
// ----------------------------------------------------------------------
// Private member variables
// ----------------------------------------------------------------------
//! The map implementation
RedBlackTreeSetOrMapImpl<K, V> m_impl = {};
};
} // namespace Fw
#endif

View File

@ -0,0 +1,177 @@
// ======================================================================
// \file ExternalRedBlackTreeSet.hpp
// \author bocchino
// \brief An set based on a red-black tree with external storage
// ======================================================================
#ifndef Fw_ExternalRedBlackTreeSet_HPP
#define Fw_ExternalRedBlackTreeSet_HPP
#include "Fw/DataStructures/Nil.hpp"
#include "Fw/DataStructures/RedBlackTreeSetOrMapImpl.hpp"
#include "Fw/DataStructures/SetBase.hpp"
#include "Fw/Types/Assert.hpp"
namespace Fw {
template <typename T>
class ExternalRedBlackTreeSet final : public SetBase<T> {
// ----------------------------------------------------------------------
// Friend class for testing
// ----------------------------------------------------------------------
template <typename TT>
friend class ExternalRedBlackTreeSetTester;
public:
// ----------------------------------------------------------------------
// Public types
// ----------------------------------------------------------------------
//! The type of a const iterator
using ConstIterator = SetConstIterator<T>;
//! The type of a tree node
using Node = typename RedBlackTreeSetOrMapImpl<T, Nil>::Node;
//! The type of a tree node index
using Index = typename RedBlackTreeSetOrMapImpl<T, Nil>::Index;
public:
// ----------------------------------------------------------------------
// Public constructors and destructors
// ----------------------------------------------------------------------
//! Zero-argument constructor
ExternalRedBlackTreeSet() = default;
//! Constructor providing typed backing storage.
//! nodes must point to at least capacity elements of type Node.
//! freeNodes must point to at least capacity elements of type FwSizeType.
ExternalRedBlackTreeSet(Node* nodes, //!< The nodes
Index* freeNodes, //!< The free nodes
FwSizeType capacity //!< The capacity
)
: SetBase<T>() {
this->setStorage(nodes, freeNodes, capacity);
}
//! Constructor providing untyped backing storage.
//! data must be aligned according to getByteArrayAlignment().
//! data must contain at least getByteArraySize(capacity) bytes.
ExternalRedBlackTreeSet(ByteArray data, //!< The data,
FwSizeType capacity //!< The capacity
)
: SetBase<T>() {
this->setStorage(data, capacity);
}
//! Copy constructor
ExternalRedBlackTreeSet(const ExternalRedBlackTreeSet<T>& set) : SetBase<T>() { *this = set; }
//! Destructor
~ExternalRedBlackTreeSet() override = default;
public:
// ----------------------------------------------------------------------
// Public member functions
// ----------------------------------------------------------------------
//! operator=
ExternalRedBlackTreeSet<T>& operator=(const ExternalRedBlackTreeSet<T>& set) {
if (&set != this) {
this->m_impl = set.m_impl;
}
return *this;
}
//! Get the begin iterator
//! \return The iterator
ConstIterator begin() const override { return ConstIterator(this->m_impl.begin()); }
//! Clear the set
void clear() override { this->m_impl.clear(); }
//! Get the end iterator
//! \return The iterator
ConstIterator end() const override { return ConstIterator(this->m_impl.end()); }
//! Find a value associated with an element in the set
//! \return SUCCESS if the item was found
Success find(const T& element //!< The element
) const override {
Nil nil = {};
return this->m_impl.find(element, nil);
}
//! Get the capacity of the set (max number of entries)
//! \return The capacity
FwSizeType getCapacity() const override { return this->m_impl.getCapacity(); }
//! Get the size (number of entries)
//! \return The size
FwSizeType getSize() const override { return this->m_impl.getSize(); }
//! Insert an element in the set
//! \return SUCCESS if there is room in the set
Success insert(const T& element //!< The element
) override {
return this->m_impl.insert(element, Nil());
}
//! Remove an element from the set
//! \return SUCCESS if the element was there
Success remove(const T& element //!< The element
) override {
Nil nil = {};
return this->m_impl.remove(element, nil);
}
//! Set the backing storage (typed data)
//! nodes must point to at least capacity elements of type Node.
//! freeNodes must point to at least capacity elements of type FwSizeType.
void setStorage(Node* nodes, //!< The nodes
Index* freeNodes, //!< The free nodes
FwSizeType capacity //!< The capacity
) {
this->m_impl.setStorage(nodes, freeNodes, capacity);
}
//! Set the backing storage (untyped data)
//! data must be aligned according to getByteArrayAlignment().
//! data must contain at least getByteArraySize(capacity) bytes.
void setStorage(ByteArray data, //!< The data
FwSizeType capacity //!< The capacity
) {
this->m_impl.setStorage(data, capacity);
}
public:
// ----------------------------------------------------------------------
// Public static functions
// ----------------------------------------------------------------------
//! Get the alignment of the storage for an RedBlackTreeSetOrMapImpl
//! \return The alignment
static constexpr U8 getByteArrayAlignment() { return RedBlackTreeSetOrMapImpl<T, Nil>::getByteArrayAlignment(); }
//! Get the size of the storage for an ExternalArray of the specified capacity,
//! as a byte array
//! \return The byte array size
static constexpr FwSizeType getByteArraySize(FwSizeType capacity //!< The capacity
) {
return RedBlackTreeSetOrMapImpl<T, Nil>::getByteArraySize(capacity);
}
private:
// ----------------------------------------------------------------------
// Private member variables
// ----------------------------------------------------------------------
//! The set implementation
RedBlackTreeSetOrMapImpl<T, Nil> m_impl = {};
};
} // namespace Fw
#endif

View File

@ -11,6 +11,7 @@
#include "Fw/DataStructures/ArraySetOrMapImpl.hpp"
#include "Fw/DataStructures/MapEntryBase.hpp"
#include "Fw/DataStructures/RedBlackTreeSetOrMapImpl.hpp"
#include "Fw/FPrimeBasicTypes.hpp"
namespace Fw {
@ -24,7 +25,10 @@ class MapConstIterator {
//! The type of an array iterator
using ArrayIterator = typename ArraySetOrMapImpl<K, V>::ConstIterator;
//! The type of a map entry base
using EntryBase = MapEntryBase<K, V>;
//! The type of a red-black tree iterator
using RedBlackTreeIterator = typename RedBlackTreeSetOrMapImpl<K, V>::ConstIterator;
private:
// ----------------------------------------------------------------------
@ -40,9 +44,12 @@ class MapConstIterator {
Impl() {}
//! Array constructor
Impl(const ArrayIterator& it) : array(it) {}
//! Red-black tree constructor
Impl(const RedBlackTreeIterator& it) : redBlackTree(it) {}
//! An array iterator
ArrayIterator array;
// TODO: Add red-black tree implementation
//! A red-black tree iterator
RedBlackTreeIterator redBlackTree;
// ! Destructor
~Impl() {}
};
@ -55,6 +62,9 @@ class MapConstIterator {
//! Constructor providing an array implementation
MapConstIterator(const ArrayIterator& it) : m_impl(it), m_implIterator(&m_impl.array) {}
//! Constructor providing a red-black tree implementation
MapConstIterator(const RedBlackTreeIterator& it) : m_impl(it), m_implIterator(&m_impl.redBlackTree) {}
//! Copy constructor
MapConstIterator(const MapConstIterator& it) : m_impl(), m_implIterator() {
const auto implKind = it.getImplIterator().implKind();
@ -63,7 +73,7 @@ class MapConstIterator {
this->m_implIterator = new (&this->m_impl.array) ArrayIterator(it.m_impl.array);
break;
case ImplKind::RED_BLACK_TREE:
// TODO
this->m_implIterator = new (&this->m_impl.redBlackTree) RedBlackTreeIterator(it.m_impl.redBlackTree);
break;
default:
FW_ASSERT(0, static_cast<FwAssertArgType>(implKind));
@ -93,7 +103,7 @@ class MapConstIterator {
result = this->m_impl.array.compareEqual(it.m_impl.array);
break;
case ImplKind::RED_BLACK_TREE:
// TODO
result = this->m_impl.redBlackTree.compareEqual(it.m_impl.redBlackTree);
break;
default:
FW_ASSERT(0, static_cast<FwAssertArgType>(implKind1));

View File

@ -0,0 +1,136 @@
// ======================================================================
// \file RedBlackTreeMap.hpp
// \author bocchino
// \brief An map based on a red-black tree with internal storage
// ======================================================================
#ifndef Fw_RedBlackTreeMap_HPP
#define Fw_RedBlackTreeMap_HPP
#include "Fw/DataStructures/ExternalRedBlackTreeMap.hpp"
namespace Fw {
template <typename K, typename V, FwSizeType C>
class RedBlackTreeMap final : public MapBase<K, V> {
// ----------------------------------------------------------------------
// Static assertions
// ----------------------------------------------------------------------
static_assert(C > 0, "capacity must be greater than zero");
// ----------------------------------------------------------------------
// Friend class for testing
// ----------------------------------------------------------------------
template <typename KK, typename VV, FwSizeType CC>
friend class RedBlackTreeMapTester;
public:
// ----------------------------------------------------------------------
// Public types
// ----------------------------------------------------------------------
//! The type of a const iterator
using ConstIterator = MapConstIterator<K, V>;
//! The type of a tree node
using Node = typename RedBlackTreeSetOrMapImpl<K, V>::Node;
//! The type of the tree node array
using Nodes = Node[C];
//! The type of a tree node index
using Index = typename RedBlackTreeSetOrMapImpl<K, V>::Index;
//! The type of the free node array
using FreeNodes = Index[C];
public:
// ----------------------------------------------------------------------
// Public constructors and destructors
// ----------------------------------------------------------------------
//! Zero-argument constructor
RedBlackTreeMap() : MapBase<K, V>(), m_extMap(m_nodes, m_freeNodes, C) {}
//! Copy constructor
RedBlackTreeMap(const RedBlackTreeMap<K, V, C>& map) : MapBase<K, V>(), m_extMap(m_nodes, m_freeNodes, C) {
*this = map;
}
//! Destructor
~RedBlackTreeMap() override = default;
public:
// ----------------------------------------------------------------------
// Public member functions
// ----------------------------------------------------------------------
//! operator=
RedBlackTreeMap<K, V, C>& operator=(const RedBlackTreeMap<K, V, C>& map) {
this->m_extMap.copyDataFrom(map);
return *this;
}
//! Get the begin iterator
//! \return The iterator
ConstIterator begin() const override { return this->m_extMap.begin(); }
//! Clear the map
void clear() override { this->m_extMap.clear(); }
//! Get the end iterator
//! \return The iterator
ConstIterator end() const override { return this->m_extMap.end(); }
//! Find a value associated with a key in the map
//! \return SUCCESS if the item was found
Success find(const K& key, //!< The key
V& value //!< The value
) const override {
return this->m_extMap.find(key, value);
}
//! Get the capacity of the map (max number of entries)
//! \return The capacity
FwSizeType getCapacity() const override { return this->m_extMap.getCapacity(); }
//! Get the size (number of entries)
//! \return The size
FwSizeType getSize() const override { return this->m_extMap.getSize(); }
//! Insert a (key, value) pair in the map
//! \return SUCCESS if there is room in the map
Success insert(const K& key, //!< The key
const V& value //!< The value
) override {
return this->m_extMap.insert(key, value);
}
//! Remove a (key, value) pair from the map
//! \return SUCCESS if the key was there
Success remove(const K& key, //!< The key
V& value //!< The value
) override {
return this->m_extMap.remove(key, value);
}
private:
// ----------------------------------------------------------------------
// Private member variables
// ----------------------------------------------------------------------
//! The array for storing the tree nodes
Nodes m_nodes = {};
//! The array for storing the free node indices
FreeNodes m_freeNodes = {};
//! The external map implementation
ExternalRedBlackTreeMap<K, V> m_extMap = {};
};
} // namespace Fw
#endif

View File

@ -0,0 +1,131 @@
// ======================================================================
// \file RedBlackTreeSet.hpp
// \author bocchino
// \brief An array-based set with internal storage
// ======================================================================
#ifndef Fw_RedBlackTreeSet_HPP
#define Fw_RedBlackTreeSet_HPP
#include "Fw/DataStructures/ExternalRedBlackTreeSet.hpp"
namespace Fw {
template <typename T, FwSizeType C>
class RedBlackTreeSet final : public SetBase<T> {
// ----------------------------------------------------------------------
// Static assertions
// ----------------------------------------------------------------------
static_assert(C > 0, "capacity must be greater than zero");
// ----------------------------------------------------------------------
// Friend class for testing
// ----------------------------------------------------------------------
template <typename TT, FwSizeType CC>
friend class RedBlackTreeSetTester;
public:
// ----------------------------------------------------------------------
// Public types
// ----------------------------------------------------------------------
//! The type of a const iterator
using ConstIterator = SetConstIterator<T>;
//! The type of a tree node
using Node = typename RedBlackTreeSetOrMapImpl<T, Nil>::Node;
//! The type of the tree node array
using Nodes = Node[C];
//! The type of a tree node index
using Index = typename RedBlackTreeSetOrMapImpl<T, Nil>::Index;
//! The type of the free node array
using FreeNodes = Index[C];
public:
// ----------------------------------------------------------------------
// Public constructors and destructors
// ----------------------------------------------------------------------
//! Zero-argument constructor
RedBlackTreeSet() : SetBase<T>(), m_extSet(m_nodes, m_freeNodes, C) {}
//! Copy constructor
RedBlackTreeSet(const RedBlackTreeSet<T, C>& set) : SetBase<T>(), m_extSet(m_nodes, m_freeNodes, C) { *this = set; }
//! Destructor
~RedBlackTreeSet() override = default;
public:
// ----------------------------------------------------------------------
// Public member functions
// ----------------------------------------------------------------------
//! operator=
RedBlackTreeSet<T, C>& operator=(const RedBlackTreeSet<T, C>& set) {
this->m_extSet.copyDataFrom(set);
return *this;
}
//! Get the begin iterator
//! \return The iterator
ConstIterator begin() const override { return this->m_extSet.begin(); }
//! Clear the set
void clear() override { this->m_extSet.clear(); }
//! Get the end iterator
//! \return The iterator
ConstIterator end() const override { return this->m_extSet.end(); }
//! Find an element in the set
//! \return SUCCESS if the element was found
Success find(const T& element //!< The element
) const override {
return this->m_extSet.find(element);
}
//! Get the capacity of the set (max number of entries)
//! \return The capacity
FwSizeType getCapacity() const override { return this->m_extSet.getCapacity(); }
//! Get the size (number of entries)
//! \return The size
FwSizeType getSize() const override { return this->m_extSet.getSize(); }
//! Insert an element in the set
//! \return SUCCESS if there is room in the set
Success insert(const T& element //!< The element
) override {
return this->m_extSet.insert(element);
}
//! Remove an element from the set
//! \return SUCCESS if the key was there
Success remove(const T& element //!< The element
) override {
return this->m_extSet.remove(element);
}
private:
// ----------------------------------------------------------------------
// Private member variables
// ----------------------------------------------------------------------
//! The array for storing the tree nodes
Nodes m_nodes = {};
//! The array for storing the free node indices
FreeNodes m_freeNodes = {};
//! The external set implementation
ExternalRedBlackTreeSet<T> m_extSet = {};
};
} // namespace Fw
#endif

File diff suppressed because it is too large Load Diff

View File

@ -11,6 +11,7 @@
#include "Fw/DataStructures/ArraySetOrMapImpl.hpp"
#include "Fw/DataStructures/Nil.hpp"
#include "Fw/DataStructures/RedBlackTreeSetOrMapImpl.hpp"
#include "Fw/FPrimeBasicTypes.hpp"
namespace Fw {
@ -25,6 +26,9 @@ class SetConstIterator {
//! The type of an array iterator
using ArrayIterator = typename ArraySetOrMapImpl<T, Nil>::ConstIterator;
//! The type of a red-black tree iterator
using RedBlackTreeIterator = typename RedBlackTreeSetOrMapImpl<T, Nil>::ConstIterator;
private:
// ----------------------------------------------------------------------
// Private types
@ -39,9 +43,12 @@ class SetConstIterator {
Impl() {}
//! Array constructor
Impl(const ArrayIterator& it) : array(it) {}
//! Red-black tree constructor
Impl(const RedBlackTreeIterator& it) : redBlackTree(it) {}
//! An array iterator
ArrayIterator array;
// TODO: Add red-black tree implementation
//! A red-black tree iterator
RedBlackTreeIterator redBlackTree;
// ! Destructor
~Impl() {}
};
@ -54,6 +61,9 @@ class SetConstIterator {
//! Constructor providing an array implementation
SetConstIterator(const ArrayIterator& it) : m_impl(it), m_implIterator(&m_impl.array) {}
//! Constructor providing a red-black tree implementation
SetConstIterator(const RedBlackTreeIterator& it) : m_impl(it), m_implIterator(&m_impl.redBlackTree) {}
//! Copy constructor
SetConstIterator(const SetConstIterator& it) : m_impl(), m_implIterator() {
const auto implKind = it.getImplIterator().implKind();
@ -62,7 +72,7 @@ class SetConstIterator {
this->m_implIterator = new (&this->m_impl.array) ArrayIterator(it.m_impl.array);
break;
case ImplKind::RED_BLACK_TREE:
// TODO
this->m_implIterator = new (&this->m_impl.redBlackTree) RedBlackTreeIterator(it.m_impl.redBlackTree);
break;
default:
FW_ASSERT(0, static_cast<FwAssertArgType>(implKind));
@ -92,7 +102,7 @@ class SetConstIterator {
result = this->m_impl.array.compareEqual(it.m_impl.array);
break;
case ImplKind::RED_BLACK_TREE:
// TODO
result = this->m_impl.redBlackTree.compareEqual(it.m_impl.redBlackTree);
break;
default:
FW_ASSERT(0, static_cast<FwAssertArgType>(implKind1));

View File

@ -1,4 +1,430 @@
# ExternalRedBlackTreeMap
TODO
`ExternalRedBlackTreeMap` is a `final` class template
defined in [`Fw/DataStructures`](sdd.md).
It represents an map based on a red-black tree with external storage.
Internally it maintains an
[`RedBlackTreeSetOrMapImpl`](RedBlackTreeSetOrMapImpl.md)
as the map implementation.
## 1. Template Parameters
`ExternalRedBlackTreeMap` has the following template parameters.
|Kind|Name|Purpose|
|----|----|-------|
|`typename`|`K`|The type of a key in the map|
|`typename`|`V`|The type of a value in the map|
## 2. Base Class
`ExternalRedBlackTreeMap` is publicly derived from
[`MapBase<K, V>`](MapBase.md).
<a name="Public-Types"></a>
## 3. Public Types
`ExternalRedBlackTreeMap` defines the following public types:
|Name|Definition|
|----|----------|
|`ConstIterator`|Alias of [`MapConstIterator<K, V>`](MapConstIterator.md)|
|`Entry`|Alias of [`SetOrMapImplEntry<K, V>`](SetOrMapImplEntry.md)|
## 4. Private Member Variables
`ExternalRedBlackTreeMap` has the following private member variables.
|Name|Type|Purpose|Default Value|
|----|----|-------|-------------|
|`m_impl`|[`RedBlackTreeSetOrMapImpl<K, V>`](RedBlackTreeSetOrMapImpl.md)|The map implementation|C++ default initialization|
```mermaid
classDiagram
ExternalRedBlackTreeMap *-- RedBlackTreeSetOrMapImpl
```
## 5. Public Constructors and Destructors
### 5.1. Zero-Argument Constructor
```c++
ExternalRedBlackTreeMap()
```
Initialize each member variable with its default value.
_Example:_
```c++
ExternalRedBlackTreeMap<U16, U32> map;
```
### 5.2. Constructor Providing Typed Backing Storage
```c++
ExternalRedBlackTreeMap(Entry* entries, FwSizeType capacity)
```
`entries` must point to a primitive array of at least `capacity`
elements of type [`Entry`](ExternalRedBlackTreeMap.md#Public-Types).
Call `setStorage(entries, capacity)`.
_Example:_
```c++
using Map = ExternalRedBlackTreeMap<U16, U32>;
constexpr FwSizeType capacity = 10;
Map::Entry entries[capacity];
Map map(entries, capacity);
```
### 5.3. Constructor Providing Untyped Backing Storage
```c++
ExternalRedBlackTreeMap(ByteArray data, FwSizeType capacity)
```
`data` must be aligned according to
[`getByteArrayAlignment()`](#getByteArrayAlignment) and must
contain at least [`getByteArraySize(capacity)`](#getByteArraySize) bytes.
Call `setStorage(data, capacity)`.
_Example:_
```c++
using Map = ExternalRedBlackTreeMap<U16, U32>;
constexpr FwSizeType capacity = 10;
constexpr U8 alignment = Map::getByteArrayAlignment();
constexpr FwSizeType byteArraySize = Map::getByteArraySize(capacity);
alignas(alignment) U8 bytes[byteArraySize];
Map map(ByteArray(&bytes[0], sizeof bytes), capacity);
```
### 5.4. Copy Constructor
```c++
ExternalRedBlackTreeMap(const ExternalRedBlackTreeMap<K, V>& map)
```
Set `*this = map`.
_Example:_
```c++
using Map = ExternalRedBlackTreeMap<U16, U32>;
constexpr FwSizeType capacity = 3;
Map::Entry entries[capacity];
// Call the constructor providing backing storage
Map m1(entries, capacity);
// Insert an item
const U16 key = 0;
const U32 value = 42;
const auto status = m1.insert(key, value);
ASSERT_EQ(status, Success::SUCCESS);
// Call the copy constructor
Map m2(m1);
ASSERT_EQ(m2.getSize(), 1);
```
### 5.5. Destructor
```c++
~ExternalRedBlackTreeMap() override
```
Defined as `= default`.
## 6. Public Member Functions
### 6.1. operator=
```c++
ExternalRedBlackTreeMap<K, V>& operator=(const ExternalRedBlackTreeMap<K, V>& map)
```
1. If `&map != this`
1. Set `m_impl = map.m_impl`.
1. Return `*this`.
_Example:_
```c++
using Map = ExternalRedBlackTreeMap<U16, U32>;
constexpr FwSizeType capacity = 3;
Map::Entry entries[capacity];
// Call the constructor providing backing storage
Map m1(entries, capacity);
// Insert an item
U16 key = 0;
U32 value = 42;
const auto status = m1.insert(key, value);
ASSERT_EQ(status, Success::SUCCESS);
// Call the default constructor
ExternalRedBlackTreeMap m2;
ASSERT_EQ(m2.getSize(), 0);
// Call the copy assignment operator
m2 = m1;
ASSERT_EQ(m2.getSize(), 1);
value = 0;
status = m2.find(key, value);
ASSERT_EQ(status, Success::SUCCESS);
ASSERT_EQ(value, 42);
```
### 6.2. begin
```c++
ConstIterator begin() const
```
Return `m_impl.begin()`.
_Example:_
```c++
using Map = ExternalRedBlackTreeMap<U16, U32>;
constexpr FwSizeType capacity = 10;
Map::Entry entries[capacity];
// Call the constructor providing backing storage
Map map(entries, capacity);
// Insert an entry in the map
const auto status = map.insert(0, 1);
ASSERT_EQ(status, Fw::Success::SUCCESS);
// Get a map const iterator object
auto it = map.begin();
// Use the iterator to access the underlying map const entry
const auto key = it->getKey();
const auto value = it->getValue();
ASSERT_EQ(key, 0);
ASSERT_EQ(value, 1);
```
### 6.3. clear
```c++
void clear() override
```
Call `m_impl.clear()`.
_Example:_
```c++
using Map = ExternalRedBlackTreeMap<U16, U32>;
constexpr FwSizeType capacity = 10;
Map::Entry entries[capacity];
Map map(entries, capacity);
const auto status = map.insert(0, 3);
ASSERT_EQ(map.getSize(), 1);
map.clear();
ASSERT_EQ(map.getSize(), 0);
```
### 6.4. end
```c++
ConstIterator end() const
```
Return `m_impl.end()`.
_Example:_
```c++
using Map = ExternalRedBlackTreeMap<U16, U32>;
constexpr FwSizeType capacity = 10;
Map::Entry entries[capacity];
// Call the constructor providing backing storage
Map map(entries, capacity);
// Insert an entry in the map
auto status = map.insert(0, 1);
ASSERT_EQ(status, Fw::Success::SUCCESS);
// Get a map const iterator object
auto iter = map.begin();
// Check that iter is not at the end
ASSERT_NE(iter, map.end());
// Increment iter
it++;
// Check that iter is at the end
ASSERT_EQ(iter, map.end());
```
### 6.5. find
```c++
Success find(const K& key, V& value) override
```
Return `m_impl.find(key, value)`.
_Example:_
```c++
using Map = ExternalRedBlackTreeMap<U16, U32>;
constexpr FwSizeType capacity = 10;
Map::Entry entries[capacity];
Map map(entries, capacity);
U32 value = 0;
auto status = map.find(0, value);
ASSERT_EQ(status, Success::FAILURE);
status = map.insert(0, 1);
ASSERT_EQ(status, Success::SUCCESS);
status = map.find(0, value);
ASSERT_EQ(status, Success::SUCCESS);
ASSERT_EQ(value, 1);
```
### 6.6. getCapacity
```c++
FwSizeType getCapacity() const override
```
Return `m_impl.getCapacity()`.
_Example:_
```c++
using Map = ExternalRedBlackTreeMap<U16, U32>;
constexpr FwSizeType capacity = 10;
Map::Entry entries[capacity];
Map map(entries, capacity);
ASSERT_EQ(map.getCapacity(), capacity);
```
### 6.7. getSize
```c++
FwSizeType getSize() const override
```
Return `m_impl.getSize()`.
_Example:_
```c++
using Map = ExternalRedBlackTreeMap<U16, U32>;
constexpr FwSizeType capacity = 10;
Map::Entry entries[capacity];
Map map(entries, capacity);
auto size = map.getSize();
ASSERT_EQ(size, 0);
const auto status = map.insert(0, 3);
ASSERT_EQ(status, Success::SUCCESS);
size = map.getSize();
ASSERT_EQ(size, 1);
```
### 6.8. insert
```c++
Success insert(const K& key, const V& value) override
```
Return `m_impl.insert(key, value)`.
_Example:_
```c++
using Map = ExternalRedBlackTreeMap<U16, U32>;
constexpr FwSizeType capacity = 10;
Map::Entry entries[capacity];
Map map(entries, capacity);
auto size = map.getSize();
ASSERT_EQ(size, 0);
const auto status = map.insert(0, 1);
ASSERT_EQ(status, Success::SUCCESS);
size = map.getSize();
ASSERT_EQ(size, 1);
```
### 6.9. remove
```c++
Success remove(const K& key, V& value) override
```
Return `m_impl.remove(key, value)`.
_Example:_
```c++
using Map = ExternalRedBlackTreeMap<U16, U32>;
constexpr FwSizeType capacity = 10;
Map::Entry entries[capacity];
Map map(entries, capacity);
auto size = map.getSize();
ASSERT_EQ(size, 0);
auto status = map.insert(0, 1);
ASSERT_EQ(status, Success::SUCCESS);
size = map.getSize();
ASSERT_EQ(size, 1);
// Key does not exist
U32 value = 0;
status = map.remove(10, value);
ASSERT_EQ(status, Success::FAILURE);
ASSERT_EQ(size, 1);
// Key exists
status = map.remove(0, value);
ASSERT_EQ(status, Success::SUCCESS);
ASSERT_EQ(size, 0);
ASSERT_EQ(value, 1);
```
### 6.10. setStorage (Typed Data)
```c++
void setStorage(Entry* entries, FwSizeType capacity)
```
`entries` must point to a primitive array of at least `capacity`
elements of type `Entry`.
The type `Entry` is defined [in this section](ExternalRedBlackTreeMap.md#Public-Types).
Call `m_impl.setStorage(entries, capacity)`.
_Example:_
```c++
using Map = ExternalRedBlackTreeMap<U16, U32>;
constexpr FwSizeType capacity = 10;
Map map;
Map::Entry entries[capacity];
map.setStorage(entries, capacity);
```
### 6.11. setStorage (Untyped Data)
```c++
void setStorage(ByteArray data, FwSizeType capacity)
```
`data` must be aligned according to
[`getByteArrayAlignment()`](#getByteArrayAlignment) and must
contain at least [`getByteArraySize(capacity)`](#getByteArraySize) bytes.
1. Call `m_entries.setStorage(data, capacity)`.
1. Call `clear()`.
```c++
using Map = ExternalRedBlackTreeMap<U16, U32>;
constexpr FwSizeType capacity = 10;
constexpr U8 alignment = Map::getByteArrayAlignment();
constexpr FwSizeType byteArraySize = Map::getByteArraySize(capacity);
alignas(alignment) U8 bytes[byteArraySize];
Map map;
map.setStorage(ByteArray(&bytes[0], sizeof bytes), capacity);
```
## 7. Public Static Functions
<a name="getByteArrayAlignment"></a>
### 7.1. getByteArrayAlignment
```c++
static constexpr U8 getByteArrayAlignment()
```
Return `RedBlackTreeSetOrMapImpl<K, V>::getByteArrayAlignment()`.
<a name="getByteArraySize"></a>
### 7.2. getByteArraySize
```c++
static constexpr FwSizeType getByteArraySize(FwSizeType capacity)
```
Return `RedBlackTreeSetOrMapImpl<K, V>::getByteArraySize(capacity)`.

View File

@ -1,4 +1,422 @@
# RedBlackTreeSet
# ExternalRedBlackTreeSet
TODO
`ExternalRedBlackTreeSet` is a `final` class template
defined in [`Fw/DataStructures`](sdd.md).
It represents a set based on a red-black tree with external storage.
Internally it maintains an [`RedBlackTreeSetOrMapImpl`](RedBlackTreeSetOrMapImpl.md)
as the set implementation.
## 1. Template Parameters
`ExternalRedBlackTreeSet` has the following template parameters.
|Kind|Name|Purpose|
|----|----|-------|
|`typename`|`T`|The type of an element in the set|
## 2. Base Class
`ExternalRedBlackTreeSet` is publicly derived from
[`SetBase<T>`](SetBase.md).
<a name="Public-Types"></a>
## 3. Public Types
`ExternalRedBlackTreeSet` defines the following public types:
|Name|Definition|
|----|----------|
|`ConstIterator`|Alias of [`MapConstIterator<T>`](MapConstIterator.md)|
|`Entry`|Alias of [`SetOrMapImplEntry<T, Nil>`](SetOrMapImplEntry.md)|
The type `Nil` is defined [in this file](Nil.md).
## 4. Private Member Variables
`ExternalRedBlackTreeSet` has the following private member variables.
|Name|Type|Purpose|Default Value|
|----|----|-------|-------------|
|`m_impl`|[`RedBlackTreeSetOrMapImpl<T, Nil>`](RedBlackTreeSetOrMapImpl.md)|The set implementation|C++ default initialization|
The type `Nil` is defined [in this file](Nil.md).
```mermaid
classDiagram
ExternalRedBlackTreeSet *-- RedBlackTreeSetOrMapImpl
```
## 5. Public Constructors and Destructors
### 5.1. Zero-Argument Constructor
```c++
ExternalRedBlackTreeSet()
```
Initialize each member variable with its default value.
_Example:_
```c++
ExternalRedBlackTreeSet<U32> set;
```
### 5.2. Constructor Providing Typed Backing Storage
```c++
ExternalRedBlackTreeSet(Entry* entries, FwSizeType capacity)
```
`entries` must point to a primitive array of at least `capacity`
elements of type `Entry`.
The type `Entry` is defined [in this section](ExternalRedBlackTreeSet.md#Public-Types).
Call `setStorage(entries, capacity)`.
_Example:_
```c++
using Set = ExternalRedBlackTreeSet<U32>;
constexpr FwSizeType capacity = 10;
Set::Entry entries[capacity];
Set set(entries, capacity);
```
### 5.3. Constructor Providing Untyped Backing Storage
```c++
ExternalRedBlackTreeSet(ByteArray data, FwSizeType capacity)
```
`data` must be aligned according to
[`getByteArrayAlignment()`](#getByteArrayAlignment) and must
contain at least [`getByteArraySize(capacity)`](#getByteArraySize) bytes.
Call `setStorage(data, capacity)`.
_Example:_
```c++
using Set = ExternalRedBlackTreeSet<U32>;
constexpr FwSizeType capacity = 10;
constexpr U8 alignment = Set::getByteArrayAlignment();
constexpr FwSizeType byteArraySize = Set::getByteArraySize(capacity);
alignas(alignment) U8 bytes[byteArraySize];
ExternalRedBlackTreeSet<U32> set(ByteArray(&bytes[0], sizeof bytes), capacity);
```
### 5.4. Copy Constructor
```c++
ExternalRedBlackTreeSet(const ExternalRedBlackTreeSet<T>& set)
```
Set `*this = set`.
_Example:_
```c++
using Set = ExternalRedBlackTreeSet<U32>;
constexpr FwSizeType capacity = 3;
Set::Entry entries[capacity];
// Call the constructor providing backing storage
Set m1(entries, capacity);
// Insert an item
const auto status = m1.insert(42);
ASSERT_EQ(status, Success::SUCCESS);
// Call the copy constructor
Set m2(m1);
ASSERT_EQ(m2.getSize(), 1);
```
### 5.5. Destructor
```c++
~ExternalRedBlackTreeSet() override
```
Defined as `= default`.
## 6. Public Member Functions
### 6.1. operator=
```c++
ExternalRedBlackTreeSet<T>& operator=(const ExternalRedBlackTreeSet<T>& set)
```
1. If `&set != this`
1. Set `m_impl = set.m_impl`.
1. Return `*this`.
_Example:_
```c++
using Set = ExternalRedBlackTreeSet<U32>;
constexpr FwSizeType capacity = 3;
Set::Entry entries[capacity];
// Call the constructor providing backing storage
Set m1(entries, capacity);
// Insert an item
const auto status = m1.insert(42);
ASSERT_EQ(status, Success::SUCCESS);
// Call the default constructor
Set m2;
ASSERT_EQ(m2.getSize(), 0);
// Call the copy assignment operator
m2 = m1;
ASSERT_EQ(m2.getSize(), 1);
```
### 6.2. begin
```c++
ConstIterator begin() const
```
Return `m_impl.begin()`.
_Example:_
```c++
using Set = ExternalRedBlackTreeSet<U32>;
constexpr FwSizeType capacity = 10;
Set::Entry entries[capacity];
// Call the constructor providing backing storage
Set set(entries, capacity);
// Insert an entry in the set
const auto status = set.insert(42);
ASSERT_EQ(status, Fw::Success::SUCCESS);
// Get a set const iterator object
auto it = set.begin();
// Use the iterator to access the element
ASSERT_EQ(*it, 42);
```
### 6.3. clear
```c++
void clear() override
```
Call `m_impl.clear()`.
_Example:_
```c++
using Set = ExternalRedBlackTreeSet<U32>;
constexpr FwSizeType capacity = 10;
Set::Entry entries[capacity];
Set set(entries, capacity);
const auto status = set.insert(42);
ASSERT_EQ(set.getSize(), 1);
set.clear();
ASSERT_EQ(set.getSize(), 0);
```
### 6.4. end
```c++
ConstIterator end() const
```
Return `m_impl.end()`.
_Example:_
```c++
using Set = ExternalRedBlackTreeSet<U32>;
constexpr FwSizeType capacity = 10;
Set::Entry entries[capacity];
// Call the constructor providing backing storage
Set set(entries, capacity);
// Insert an entry in the set
auto status = set.insert(42);
ASSERT_EQ(status, Fw::Success::SUCCESS);
// Get a set const iterator object
auto iter = set.begin();
// Check that iter is not at the end
ASSERT_NE(iter, set.end());
// Increment iter
it++;
// Check that iter is at the end
ASSERT_EQ(iter, set.end());
```
### 6.5. find
```c++
Success find(const T& element) override
```
1. Set `Nil nil = {}`.
1. Return `m_impl.find(key, nil)`.
_Example:_
```c++
using Set = ExternalRedBlackTreeSet<U32>;
constexpr FwSizeType capacity = 10;
Set::Entry entries[capacity];
Set set(entries, capacity);
auto status = set.find(42);
ASSERT_EQ(status, Success::FAILURE);
status = set.insert(42);
ASSERT_EQ(status, Success::SUCCESS);
status = set.find(42);
ASSERT_EQ(status, Success::SUCCESS);
```
### 6.6. getCapacity
```c++
FwSizeType getCapacity() const override
```
Return `m_impl.getCapacity()`.
_Example:_
```c++
using Set = ExternalRedBlackTreeSet<U32>;
constexpr FwSizeType capacity = 10;
Set::Entry entries[capacity];
Set set(entries, capacity);
ASSERT_EQ(set.getCapacity(), capacity);
```
### 6.8. getSize
```c++
FwSizeType getSize() const override
```
Return `m_impl.getSize()`.
_Example:_
```c++
using Set = ExternalRedBlackTreeSet<U32>;
constexpr FwSizeType capacity = 10;
Set::Entry entries[capacity];
Set set(entries, capacity);
auto size = set.getSize();
ASSERT_EQ(size, 0);
const auto status = set.insert(42);
ASSERT_EQ(status, Success::SUCCESS);
size = set.getSize();
ASSERT_EQ(size, 1);
```
### 6.9. insert
```c++
Success insert(const T& element) override
```
Return `m_impl.insert(key, Nil())`.
_Example:_
```c++
using Set = ExternalRedBlackTreeSet<U32>;
constexpr FwSizeType capacity = 10;
Set::Entry entries[capacity];
Set set(entries, capacity);
auto size = set.getSize();
ASSERT_EQ(size, 0);
const auto status = set.insert(42);
ASSERT_EQ(status, Success::SUCCESS);
size = set.getSize();
ASSERT_EQ(size, 1);
```
### 6.10. remove
```c++
Success remove(const T& element) override
```
1. Set `Nil nil = {}`.
1. Return `m_impl.remove(key, nil)`.
_Example:_
```c++
using Set = ExternalRedBlackTreeSet<U32>;
constexpr FwSizeType capacity = 10;
Set::Entry entries[capacity];
Set set(entries, capacity);
auto size = set.getSize();
ASSERT_EQ(size, 0);
auto status = set.insert(42);
ASSERT_EQ(status, Success::SUCCESS);
size = set.getSize();
ASSERT_EQ(size, 1);
// Element does not exist
status = set.remove(0);
ASSERT_EQ(status, Success::FAILURE);
ASSERT_EQ(size, 1);
// Element exists
status = set.remove(42);
ASSERT_EQ(status, Success::SUCCESS);
ASSERT_EQ(size, 0);
```
### 6.11. setStorage (Typed Data)
```c++
void setStorage(Entry* entries, FwSizeType capacity)
```
`entries` must point to a primitive array of at least `capacity`
elements of type `Entry`.
The type `Entry` is defined [in this section](ExternalRedBlackTreeSet.md#Public-Types).
Call `m_impl.setStorage(entries, capacity)`.
_Example:_
```c++
using Set = ExternalRedBlackTreeSet<U32>;
constexpr FwSizeType capacity = 10;
Set set;
Set::Entry entries[capacity];
set.setStorage(entries, capacity);
```
### 6.12. setStorage (Untyped Data)
```c++
void setStorage(ByteArray data, FwSizeType capacity)
```
`data` must be aligned according to
[`getByteArrayAlignment()`](#getByteArrayAlignment) and must
contain at least [`getByteArraySize(capacity)`](#getByteArraySize) bytes.
1. Call `m_entries.setStorage(data, capacity)`.
1. Call `clear()`.
```c++
using Set = ExternalRedBlackTreeSet<U32>;
constexpr FwSizeType capacity = 10;
constexpr U8 alignment = Set::getByteArrayAlignment();
constexpr FwSizeType byteArraySize = Set::getByteArraySize(capacity);
alignas(alignment) U8 bytes[byteArraySize];
Set set;
set.setStorage(ByteArray(&bytes[0], sizeof bytes), capacity);
```
## 7. Public Static Functions
<a name="getByteArrayAlignment"></a>
### 7.1. getByteArrayAlignment
```c++
static constexpr U8 getByteArrayAlignment()
```
Return `RedBlackTreeSetOrMapImpl<Entry>::getByteArrayAlignment()`.
<a name="getByteArraySize"></a>
### 7.2. getByteArraySize
```c++
static constexpr FwSizeType getByteArraySize(FwSizeType capacity)
```
Return `RedBlackTreeSetOrMapImpl<Entry>::getByteArraySize(capacity)`.

View File

@ -1,4 +1,304 @@
# RedBlackTreeMap
TODO
`RedBlackTreeMap` is a `final` class template
defined in [`Fw/DataStructures`](sdd.md).
It represents a map based on a red-black tree with internal storage.
## 1. Template Parameters
`RedBlackTreeMap` has the following template parameters.
|Kind|Name|Purpose|
|----|----|-------|
|`typename`|`K`|The type of a key in the map|
|`typename`|`V`|The type of a value in the map|
|`FwSizeType`|`C`|The capacity, i.e., the maximum number of keys that the map can store|
`RedBlackTreeMap` statically asserts that `C > 0`.
## 2. Base Class
`RedBlackTreeMap` is publicly derived from
[`MapBase<K, V>`](MapBase.md).
<a name="Public-Types"></a>
## 3. Public Types
`RedBlackTreeMap` defines the following public types:
|Name|Definition|
|----|----------|
|`ConstIterator`|Alias of [`MapConstIterator<K, V>`](MapConstIterator.md)|
|`Node`|Alias of [`RedBlackTreeSetOrMapImpl<K, V>::Node`](SetOrMapImplEntry.md)|
|`Nodes`|Alias of [`Node[C]`|
|`Index`|Alias of [`RedBlackTreeSetOrMapImpl<K, V>::Index`](SetOrMapImplEntry.md)|
|`FreeNodes`|Alias of [`Index[C]`|
## 4. Private Member Variables
`RedBlackTreeMap` has the following private member variables.
|Name|Type|Purpose|Default Value|
|----|----|-------|-------------|
|`m_extMap`|[`ExternalRedBlackTreeMap<K, V>`](ExternalRedBlackTreeMap.md)|The external map implementation|C++ default initialization|
|`m_nodes`|`Nodes`|The array for storing the tree nodes|
|`m_freeNodes`|`FreeNodes`|The array for storing the free node indices.|
```mermaid
classDiagram
RedBlackTreeMap *-- ExternalRedBlackTreeMap
```
## 5. Public Constructors and Destructors
### 5.1. Zero-Argument Constructor
```c++
RedBlackTreeMap()
```
Initialize `m_extMap` with `ExternalRedBlackTreeMap<K, V>(m_nodes, m_freeNodes, C)`.
_Example:_
```c++
RedBlackTreeMap<U16, U32, 10> map;
```
### 5.2. Copy Constructor
```c++
RedBlackTreeMap(const RedBlackTreeMap<K, V, C>& map)
```
1. Initialize `m_extMap` with `ExternalRedBlackTreeMap<K, V>(m_nodes, m_freeNodes, C)`.
1. Set `*this = map`.
_Example:_
```c++
using Map = RedBlackTreeMap<U16, U32, 10>;
Map m1;
// Insert an item
const U16 key = 0;
const U32 value = 42;
const auto status = m1.insert(key, value);
ASSERT_EQ(status, Success::SUCCESS);
// Call the copy constructor
Map m2(m1);
ASSERT_EQ(m2.getSize(), 1);
```
### 5.3. Destructor
```c++
~RedBlackTreeMap() override
```
Defined as `= default`.
## 6. Public Member Functions
### 6.1. operator=
```c++
RedBlackTreeMap<K, V, C>& operator=(const RedBlackTreeMap<K, V, C>& map)
```
Return `m_extMap.copyDataFrom(map)`.
_Example:_
```c++
using Map = RedBlackTreeMap<U16, U32, 10>;
Map m1;
// Insert an item
U16 key = 0;
U32 value = 42;
auto status = m1.insert(key, value);
ASSERT_EQ(status, Success::SUCCESS);
// Call the default constructor
Map m2;
ASSERT_EQ(m2.getSize(), 0);
// Call the copy assignment operator
m2 = m1;
ASSERT_EQ(m2.getSize(), 1);
value = 0;
status = m2.find(key, value);
ASSERT_EQ(status, Success::SUCCESS);
ASSERT_EQ(value, 42);
```
### 6.2. begin
```c++
ConstIterator begin() const
```
Return `m_extMap.begin()`.
_Example:_
```c++
using Map = RedBlackTreeMap<U16, U32, 10>;
Map map;
// Insert an entry in the map
const auto status = map.insert(0, 1);
ASSERT_EQ(status, Fw::Success::SUCCESS);
// Get a map const iterator object
auto it = map.begin();
// Use the iterator to access the underlying map const entry
const key = it->getKey();
const value = it->getValue();
ASSERT_EQ(key, 0);
ASSERT_EQ(value, 1);
```
### 6.3. clear
```c++
void clear() override
```
Call `m_extMap.clear()`.
_Example:_
```c++
using Map = RedBlackTreeMap<U16, U32, 10>;
Map map;
const auto status = map.insert(0, 3);
ASSERT_EQ(map.getSize(), 1);
map.clear();
ASSERT_EQ(map.getSize(), 0);
```
### 6.4. end
```c++
ConstIterator end() const
```
Return `m_extMap.end()`.
_Example:_
```c++
using Map = RedBlackTreeMap<U16, U32, 10>;
// Call the constructor providing backing storage
Map map;
// Insert an entry in the map
auto status = map.insert(0, 1);
ASSERT_EQ(status, Fw::Success::SUCCESS);
// Get a map const iterator object
auto iter = map.begin();
// Check that iter is not at the end
ASSERT_NE(iter, map.end());
// Increment iter
it++;
// Check that iter is at the end
ASSERT_EQ(iter, map.end());
```
### 6.5. find
```c++
Success find(const K& key, V& value) override
```
Return `m_extMap.find(key, value)`.
_Example:_
```c++
using Map = RedBlackTreeMap<U16, U32, 10>;
Map map;
U32 value = 0;
auto status = map.find(0, value);
ASSERT_EQ(status, Success::FAILURE);
status = map.insert(0, 1);
ASSERT_EQ(status, Success::SUCCESS);
status = map.find(0, value);
ASSERT_EQ(status, Success::SUCCESS);
ASSERT_EQ(value, 1);
```
### 6.6. getCapacity
```c++
FwSizeType getCapacity() const override
```
Return `m_extMap.getCapacity()`.
_Example:_
```c++
using Map = RedBlackTreeMap<U16, U32, 10>;
Map map;
ASSERT_EQ(map.getCapacity(), 10);
```
### 6.8. getSize
```c++
FwSizeType getSize() const override
```
Return `m_extMap.getSize()`.
_Example:_
```c++
using Map = RedBlackTreeMap<U16, U32, 10>;
Map map;
auto size = map.getSize();
ASSERT_EQ(size, 0);
const auto status = map.insert(0, 3);
ASSERT_EQ(status, Success::SUCCESS);
size = map.getSize();
ASSERT_EQ(size, 1);
```
### 6.9. insert
```c++
Success insert(const K& key, const V& value) override
```
Return `m_extMap.insert(key, value)`.
_Example:_
```c++
using Map = RedBlackTreeMap<U16, U32, 10>;
Map map;
auto size = map.getSize();
ASSERT_EQ(size, 0);
const auto status = map.insert(0, 1);
ASSERT_EQ(status, Success::SUCCESS);
size = map.getSize();
ASSERT_EQ(size, 1);
```
### 6.10. remove
```c++
Success remove(const K& key, V& value) override
```
Return `m_extMap.remove(key, value)`.
_Example:_
```c++
using Map = RedBlackTreeMap<U16, U32, 10>;
Map map;
auto size = map.getSize();
ASSERT_EQ(size, 0);
auto status = map.insert(0, 1);
ASSERT_EQ(status, Success::SUCCESS);
size = map.getSize();
ASSERT_EQ(size, 1);
// Key does not exist
U32 value = 0;
status = map.remove(10, value);
ASSERT_EQ(status, Success::FAILURE);
ASSERT_EQ(size, 1);
// Key exists
status = map.remove(0, value);
ASSERT_EQ(status, Success::SUCCESS);
ASSERT_EQ(size, 0);
ASSERT_EQ(value, 1);
```

View File

@ -1,4 +1,292 @@
# ExternalRedBlackTreeSet
# RedBlackTreeSet
TODO
`RedBlackTreeSet` is a `final` class template
defined in [`Fw/DataStructures`](sdd.md).
It represents a set based on a red-black tree with internal storage.
## 1. Template Parameters
`RedBlackTreeSet` has the following template parameters.
|Kind|Name|Purpose|
|----|----|-------|
|`typename`|`T`|The type of an element in the set|
|`FwSizeType`|`C`|The capacity, i.e., the maximum number of elements that the set can store|
`RedBlackTreeSet` statically asserts that `C > 0`.
## 2. Base Class
`RedBlackTreeSet` is publicly derived from
[`SetBase<T>`](SetBase.md).
<a name="Public-Types"></a>
## 3. Public Types
`RedBlackTreeSet` defines the following public types:
|Name|Definition|
|----|----------|
|`ConstIterator`|Alias of [`SetConstIterator<T>`](SetConstIterator.md)|
|`Entry`|Alias of [`SetOrMapImplEntry<T, Nil>`](SetOrMapImplEntry.md)|
The type `Nil` is defined [in this file](Nil.md).
## 4. Private Member Variables
`RedBlackTreeSet` has the following private member variables.
|Name|Type|Purpose|Default Value|
|----|----|-------|-------------|
|`m_extSet`|[`ExternalRedBlackTreeSet<T>`](ExternalRedBlackTreeSet.md)|The external set implementation|C++ default initialization|
|`m_entries`|`Entry[C]`|The array providing the backing memory for `m_extSet`|C++ default initialization|
The type `Entry` is defined [in this section](RedBlackTreeSet.md#Public-Types).
```mermaid
classDiagram
RedBlackTreeSet *-- ExternalRedBlackTreeSet
```
## 5. Public Constructors and Destructors
### 5.1. Zero-Argument Constructor
```c++
RedBlackTreeSet()
```
Initialize `m_extSet` with `ExternalRedBlackTreeSet<T>(m_entries, C)`.
_Example:_
```c++
RedBlackTreeSet<U32, 10> set;
```
### 5.2. Copy Constructor
```c++
RedBlackTreeSet(const RedBlackTreeSet<T, C>& set)
```
1. Initialize `m_extSet` with `ExternalRedBlackTreeSet<T>(m_entries, C)`.
2. Set `*this = set`.
_Example:_
```c++
using Set = RedBlackTreeSet<U32, 10>;
Set s1;
// Insert an item
const U32 element = 42;
const auto status = s1.insert(element);
ASSERT_EQ(status, Success::SUCCESS);
// Call the copy constructor
Set s2;
ASSERT_EQ(s2.getSize(), 1);
```
### 5.3. Destructor
```c++
~RedBlackTreeSet() override
```
Defined as `= default`.
## 6. Public Member Functions
### 6.1. operator=
```c++
RedBlackTreeSet<T, C>& operator=(const RedBlackTreeSet<T, C>& set)
```
Return `m_extSet.copyDataFrom(set)`.
_Example:_
```c++
using Set = RedBlackTreeSet<U32, 10>;
Set s1;
// Insert an item
U32 element = 42;
const auto status = s1.insert(element);
ASSERT_EQ(status, Success::SUCCESS);
// Call the default constructor
Set s2;
ASSERT_EQ(s2.getSize(), 0);
// Call the copy assignment operator
s2 = s1;
ASSERT_EQ(s2.getSize(), 1);
status = s2.find(element);
ASSERT_EQ(status, Success::SUCCESS);
```
### 6.2. begin
```c++
ConstIterator begin() const
```
Return `m_extSet.begin()`.
_Example:_
```c++
using Set = RedBlackTreeSet<U32, 10>;
Set set;
// Insert an element in the set
const auto status = map.insert(42);
ASSERT_EQ(status, Fw::Success::SUCCESS);
// Get a set const iterator object
auto it = set.begin();
// Use the iterator to access the underlying map const entry
ASSERT_EQ(*it, 42);
```
### 6.3. clear
```c++
void clear() override
```
Call `m_extSet.clear()`.
_Example:_
```c++
using Set = RedBlackTreeSet<U32, 10>;
Set set;
const auto status = set.insert(42);
ASSERT_EQ(set.getSize(), 1);
set.clear();
ASSERT_EQ(set.getSize(), 0);
```
### 6.4. end
```c++
ConstIterator end() const
```
Return `m_extSet.end()`.
_Example:_
```c++
using Set = RedBlackTreeSet<U32, 10>;
// Call the constructor providing backing storage
Set set;
// Insert an element in the set
auto status = set.insert(42);
ASSERT_EQ(status, Fw::Success::SUCCESS);
// Get a set const iterator object
auto iter = set.begin();
// Check that iter is not at the end
ASSERT_NE(iter, set.end());
// Increment iter
it++;
// Check that iter is at the end
ASSERT_EQ(iter, set.end());
```
### 6.5. find
```c++
Success find(const K& element, V& value) override
```
Return `m_extSet.find(element)`.
_Example:_
```c++
using Set = RedBlackTreeSet<U32, 10>;
Set set;
auto status = set.find(42);
ASSERT_EQ(status, Success::FAILURE);
status = set.insert(42);
ASSERT_EQ(status, Success::SUCCESS);
status = set.find(42);
ASSERT_EQ(status, Success::SUCCESS);
```
### 6.6. getCapacity
```c++
FwSizeType getCapacity() const override
```
Return `m_extSet.getCapacity()`.
_Example:_
```c++
using Set = RedBlackTreeSet<U32, 10>;
Set set;
ASSERT_EQ(set.getCapacity(), 10);
```
### 6.7. getSize
```c++
FwSizeType getSize() const override
```
Return `m_extSet.getSize()`.
_Example:_
```c++
using Set = RedBlackTreeSet<U32, 10>;
Set set;
auto size = set.getSize();
ASSERT_EQ(size, 0);
const auto status = set.insert(42);
ASSERT_EQ(status, Success::SUCCESS);
size = set.getSize();
ASSERT_EQ(size, 1);
```
### 6.8. insert
```c++
Success insert(const T& element) override
```
Return `m_extSet.insert(element)`.
_Example:_
```c++
using Set = RedBlackTreeSet<U32, 10>;
Set set;
auto size = set.getSize();
ASSERT_EQ(size, 0);
const auto status = set.insert(42);
ASSERT_EQ(status, Success::SUCCESS);
size = set.getSize();
ASSERT_EQ(size, 1);
```
### 6.9. remove
```c++
Success remove(const T& element) override
```
Return `m_extSet.remove(element)`.
_Example:_
```c++
using Set = RedBlackTreeSet<U32, 10>;
Set set;
auto size = set.getSize();
ASSERT_EQ(size, 0);
auto status = set.insert(42);
ASSERT_EQ(status, Success::SUCCESS);
size = set.getSize();
ASSERT_EQ(size, 1);
// Element does not exist
status = set.remove(0);
ASSERT_EQ(status, Success::FAILURE);
ASSERT_EQ(size, 1);
// Element exists
status = set.remove(42);
ASSERT_EQ(status, Success::SUCCESS);
ASSERT_EQ(size, 0);
```

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,10 @@
digraph {
K2 -> BH2
K2 -> BH1
K2 [color="red",fontcolor="red"]
BH1 [shape="box",label="black height 1",style="dotted",fontname="Italic"]
BH2 [shape="box",label="black height 2",style="dotted",fontname="Italic"]
}

View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 12.2.1 (20241206.2353)
-->
<!-- Pages: 1 -->
<svg width="212pt" height="116pt"
viewBox="0.00 0.00 212.25 116.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 112)">
<polygon fill="white" stroke="none" points="-4,4 -4,-112 208.25,-112 208.25,4 -4,4"/>
<!-- K2 -->
<g id="node1" class="node">
<title>K2</title>
<ellipse fill="none" stroke="red" cx="101.62" cy="-90" rx="27" ry="18"/>
<text text-anchor="middle" x="101.62" y="-84.95" font-family="Times,serif" font-size="14.00" fill="red">K2</text>
</g>
<!-- BH2 -->
<g id="node2" class="node">
<title>BH2</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="93.25,-36 0,-36 0,0 93.25,0 93.25,-36"/>
<text text-anchor="middle" x="46.62" y="-11.82" font-family="Italic" font-size="14.00">black height 2</text>
</g>
<!-- K2&#45;&gt;BH2 -->
<g id="edge1" class="edge">
<title>K2&#45;&gt;BH2</title>
<path fill="none" stroke="black" d="M89.42,-73.46C82.96,-65.25 74.86,-54.93 67.44,-45.5"/>
<polygon fill="black" stroke="black" points="70.21,-43.35 61.28,-37.65 64.71,-47.68 70.21,-43.35"/>
</g>
<!-- BH1 -->
<g id="node3" class="node">
<title>BH1</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="204.25,-36 111,-36 111,0 204.25,0 204.25,-36"/>
<text text-anchor="middle" x="157.62" y="-11.82" font-family="Italic" font-size="14.00">black height 1</text>
</g>
<!-- K2&#45;&gt;BH1 -->
<g id="edge2" class="edge">
<title>K2&#45;&gt;BH1</title>
<path fill="none" stroke="black" d="M113.78,-73.81C120.5,-65.4 129.05,-54.72 136.81,-45.02"/>
<polygon fill="black" stroke="black" points="139.46,-47.3 142.98,-37.31 134,-42.93 139.46,-47.3"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,8 @@
digraph {
K4 -> K2
K4 -> K5
K2 -> K1
K2 -> K3
}

View File

@ -0,0 +1,66 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 12.2.1 (20241206.2353)
-->
<!-- Pages: 1 -->
<svg width="170pt" height="188pt"
viewBox="0.00 0.00 170.00 188.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 184)">
<polygon fill="white" stroke="none" points="-4,4 -4,-184 166,-184 166,4 -4,4"/>
<!-- K4 -->
<g id="node1" class="node">
<title>K4</title>
<ellipse fill="none" stroke="black" cx="99" cy="-162" rx="27" ry="18"/>
<text text-anchor="middle" x="99" y="-156.95" font-family="Times,serif" font-size="14.00">K4</text>
</g>
<!-- K2 -->
<g id="node2" class="node">
<title>K2</title>
<ellipse fill="none" stroke="black" cx="63" cy="-90" rx="27" ry="18"/>
<text text-anchor="middle" x="63" y="-84.95" font-family="Times,serif" font-size="14.00">K2</text>
</g>
<!-- K4&#45;&gt;K2 -->
<g id="edge1" class="edge">
<title>K4&#45;&gt;K2</title>
<path fill="none" stroke="black" d="M90.65,-144.76C86.42,-136.55 81.19,-126.37 76.42,-117.09"/>
<polygon fill="black" stroke="black" points="79.68,-115.79 72,-108.49 73.46,-118.99 79.68,-115.79"/>
</g>
<!-- K5 -->
<g id="node3" class="node">
<title>K5</title>
<ellipse fill="none" stroke="black" cx="135" cy="-90" rx="27" ry="18"/>
<text text-anchor="middle" x="135" y="-84.95" font-family="Times,serif" font-size="14.00">K5</text>
</g>
<!-- K4&#45;&gt;K5 -->
<g id="edge2" class="edge">
<title>K4&#45;&gt;K5</title>
<path fill="none" stroke="black" d="M107.35,-144.76C111.58,-136.55 116.81,-126.37 121.58,-117.09"/>
<polygon fill="black" stroke="black" points="124.54,-118.99 126,-108.49 118.32,-115.79 124.54,-118.99"/>
</g>
<!-- K1 -->
<g id="node4" class="node">
<title>K1</title>
<ellipse fill="none" stroke="black" cx="27" cy="-18" rx="27" ry="18"/>
<text text-anchor="middle" x="27" y="-12.95" font-family="Times,serif" font-size="14.00">K1</text>
</g>
<!-- K2&#45;&gt;K1 -->
<g id="edge3" class="edge">
<title>K2&#45;&gt;K1</title>
<path fill="none" stroke="black" d="M54.65,-72.76C50.42,-64.55 45.19,-54.37 40.42,-45.09"/>
<polygon fill="black" stroke="black" points="43.68,-43.79 36,-36.49 37.46,-46.99 43.68,-43.79"/>
</g>
<!-- K3 -->
<g id="node5" class="node">
<title>K3</title>
<ellipse fill="none" stroke="black" cx="99" cy="-18" rx="27" ry="18"/>
<text text-anchor="middle" x="99" y="-12.95" font-family="Times,serif" font-size="14.00">K3</text>
</g>
<!-- K2&#45;&gt;K3 -->
<g id="edge4" class="edge">
<title>K2&#45;&gt;K3</title>
<path fill="none" stroke="black" d="M71.35,-72.76C75.58,-64.55 80.81,-54.37 85.58,-45.09"/>
<polygon fill="black" stroke="black" points="88.54,-46.99 90,-36.49 82.32,-43.79 88.54,-46.99"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -0,0 +1,16 @@
digraph {
K2 -> K1
K2 -> K3 [color="invis"]
K1 -> A
K1 -> B
K2 -> C
K1
K2 [color="red",fontcolor="red"]
K3 [color="invis",fontcolor="invis"]
A [fontcolor="invis"]
B [fontcolor="invis"]
C [fontcolor="invis"]
}

View File

@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 12.2.1 (20241206.2353)
-->
<!-- Pages: 1 -->
<svg width="242pt" height="188pt"
viewBox="0.00 0.00 242.00 188.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 184)">
<polygon fill="white" stroke="none" points="-4,4 -4,-184 238,-184 238,4 -4,4"/>
<!-- K2 -->
<g id="node1" class="node">
<title>K2</title>
<ellipse fill="none" stroke="red" cx="135" cy="-162" rx="27" ry="18"/>
<text text-anchor="middle" x="135" y="-156.95" font-family="Times,serif" font-size="14.00" fill="red">K2</text>
</g>
<!-- K1 -->
<g id="node2" class="node">
<title>K1</title>
<ellipse fill="none" stroke="black" cx="63" cy="-90" rx="27" ry="18"/>
<text text-anchor="middle" x="63" y="-84.95" font-family="Times,serif" font-size="14.00">K1</text>
</g>
<!-- K2&#45;&gt;K1 -->
<g id="edge1" class="edge">
<title>K2&#45;&gt;K1</title>
<path fill="none" stroke="black" d="M120.08,-146.5C110.23,-136.92 97.14,-124.19 85.97,-113.34"/>
<polygon fill="black" stroke="black" points="88.59,-111 78.98,-106.54 83.71,-116.02 88.59,-111"/>
</g>
<!-- K3 -->
<g id="node3" class="node">
<title>K3</title>
<ellipse fill="none" stroke="none" cx="135" cy="-90" rx="27" ry="18"/>
<text text-anchor="middle" x="135" y="-84.95" font-family="Times,serif" font-size="14.00" fill="#fffffe" fill-opacity="0.000000">K3</text>
</g>
<!-- K2&#45;&gt;K3 -->
<g id="edge2" class="edge">
<title>K2&#45;&gt;K3</title>
<path fill="none" stroke="none" d="M135,-143.7C135,-136.41 135,-127.73 135,-119.54"/>
<polygon fill="none" stroke="none" points="138.5,-119.62 135,-109.62 131.5,-119.62 138.5,-119.62"/>
</g>
<!-- C -->
<g id="node6" class="node">
<title>C</title>
<ellipse fill="none" stroke="black" cx="207" cy="-90" rx="27" ry="18"/>
<text text-anchor="middle" x="207" y="-84.95" font-family="Times,serif" font-size="14.00" fill="#fffffe" fill-opacity="0.000000">C</text>
</g>
<!-- K2&#45;&gt;C -->
<g id="edge5" class="edge">
<title>K2&#45;&gt;C</title>
<path fill="none" stroke="black" d="M149.92,-146.5C159.77,-136.92 172.86,-124.19 184.03,-113.34"/>
<polygon fill="black" stroke="black" points="186.29,-116.02 191.02,-106.54 181.41,-111 186.29,-116.02"/>
</g>
<!-- A -->
<g id="node4" class="node">
<title>A</title>
<ellipse fill="none" stroke="black" cx="27" cy="-18" rx="27" ry="18"/>
<text text-anchor="middle" x="27" y="-12.95" font-family="Times,serif" font-size="14.00" fill="#fffffe" fill-opacity="0.000000">A</text>
</g>
<!-- K1&#45;&gt;A -->
<g id="edge3" class="edge">
<title>K1&#45;&gt;A</title>
<path fill="none" stroke="black" d="M54.65,-72.76C50.42,-64.55 45.19,-54.37 40.42,-45.09"/>
<polygon fill="black" stroke="black" points="43.68,-43.79 36,-36.49 37.46,-46.99 43.68,-43.79"/>
</g>
<!-- B -->
<g id="node5" class="node">
<title>B</title>
<ellipse fill="none" stroke="black" cx="99" cy="-18" rx="27" ry="18"/>
<text text-anchor="middle" x="99" y="-12.95" font-family="Times,serif" font-size="14.00" fill="#fffffe" fill-opacity="0.000000">B</text>
</g>
<!-- K1&#45;&gt;B -->
<g id="edge4" class="edge">
<title>K1&#45;&gt;B</title>
<path fill="none" stroke="black" d="M71.35,-72.76C75.58,-64.55 80.81,-54.37 85.58,-45.09"/>
<polygon fill="black" stroke="black" points="88.54,-46.99 90,-36.49 82.32,-43.79 88.54,-46.99"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

@ -0,0 +1,10 @@
digraph {
K2 -> K1
K2 -> K3 [color="invis"]
K1
K2 [color="red",fontcolor="red"]
K3 [color="invis",fontcolor="invis"]
}

View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 12.2.1 (20241206.2353)
-->
<!-- Pages: 1 -->
<svg width="134pt" height="116pt"
viewBox="0.00 0.00 134.00 116.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 112)">
<polygon fill="white" stroke="none" points="-4,4 -4,-112 130,-112 130,4 -4,4"/>
<!-- K2 -->
<g id="node1" class="node">
<title>K2</title>
<ellipse fill="none" stroke="red" cx="63" cy="-90" rx="27" ry="18"/>
<text text-anchor="middle" x="63" y="-84.95" font-family="Times,serif" font-size="14.00" fill="red">K2</text>
</g>
<!-- K1 -->
<g id="node2" class="node">
<title>K1</title>
<ellipse fill="none" stroke="black" cx="27" cy="-18" rx="27" ry="18"/>
<text text-anchor="middle" x="27" y="-12.95" font-family="Times,serif" font-size="14.00">K1</text>
</g>
<!-- K2&#45;&gt;K1 -->
<g id="edge1" class="edge">
<title>K2&#45;&gt;K1</title>
<path fill="none" stroke="black" d="M54.65,-72.76C50.42,-64.55 45.19,-54.37 40.42,-45.09"/>
<polygon fill="black" stroke="black" points="43.68,-43.79 36,-36.49 37.46,-46.99 43.68,-43.79"/>
</g>
<!-- K3 -->
<g id="node3" class="node">
<title>K3</title>
<ellipse fill="none" stroke="none" cx="99" cy="-18" rx="27" ry="18"/>
<text text-anchor="middle" x="99" y="-12.95" font-family="Times,serif" font-size="14.00" fill="#fffffe" fill-opacity="0.000000">K3</text>
</g>
<!-- K2&#45;&gt;K3 -->
<g id="edge2" class="edge">
<title>K2&#45;&gt;K3</title>
<path fill="none" stroke="none" d="M71.35,-72.76C75.58,-64.55 80.81,-54.37 85.58,-45.09"/>
<polygon fill="none" stroke="none" points="88.54,-46.99 90,-36.49 82.32,-43.79 88.54,-46.99"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1,10 @@
digraph {
1 -> 2
1 -> 3
1 [fontcolor="white"]
2 [fontcolor="white"]
3 [fontcolor="white"]
}

View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 12.2.1 (20241206.2353)
-->
<!-- Pages: 1 -->
<svg width="134pt" height="116pt"
viewBox="0.00 0.00 134.00 116.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 112)">
<polygon fill="white" stroke="none" points="-4,4 -4,-112 130,-112 130,4 -4,4"/>
<!-- 1 -->
<g id="node1" class="node">
<title>1</title>
<ellipse fill="none" stroke="black" cx="63" cy="-90" rx="27" ry="18"/>
<text text-anchor="middle" x="63" y="-84.95" font-family="Times,serif" font-size="14.00" fill="white">1</text>
</g>
<!-- 2 -->
<g id="node2" class="node">
<title>2</title>
<ellipse fill="none" stroke="black" cx="27" cy="-18" rx="27" ry="18"/>
<text text-anchor="middle" x="27" y="-12.95" font-family="Times,serif" font-size="14.00" fill="white">2</text>
</g>
<!-- 1&#45;&gt;2 -->
<g id="edge1" class="edge">
<title>1&#45;&gt;2</title>
<path fill="none" stroke="black" d="M54.65,-72.76C50.42,-64.55 45.19,-54.37 40.42,-45.09"/>
<polygon fill="black" stroke="black" points="43.68,-43.79 36,-36.49 37.46,-46.99 43.68,-43.79"/>
</g>
<!-- 3 -->
<g id="node3" class="node">
<title>3</title>
<ellipse fill="none" stroke="black" cx="99" cy="-18" rx="27" ry="18"/>
<text text-anchor="middle" x="99" y="-12.95" font-family="Times,serif" font-size="14.00" fill="white">3</text>
</g>
<!-- 1&#45;&gt;3 -->
<g id="edge2" class="edge">
<title>1&#45;&gt;3</title>
<path fill="none" stroke="black" d="M71.35,-72.76C75.58,-64.55 80.81,-54.37 85.58,-45.09"/>
<polygon fill="black" stroke="black" points="88.54,-46.99 90,-36.49 82.32,-43.79 88.54,-46.99"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1,18 @@
digraph {
K2 -> K1
K2 -> K3
K1 -> A
K1 -> B
K3 -> C
K3 -> D
K1 [color="red",fontcolor="red"]
K2
K3 [color="red",fontcolor="red"]
A [fontcolor="invis"]
B [fontcolor="invis"]
C [fontcolor="invis"]
D [fontcolor="invis"]
}

View File

@ -0,0 +1,90 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 12.2.1 (20241206.2353)
-->
<!-- Pages: 1 -->
<svg width="278pt" height="188pt"
viewBox="0.00 0.00 278.00 188.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 184)">
<polygon fill="white" stroke="none" points="-4,4 -4,-184 274,-184 274,4 -4,4"/>
<!-- K2 -->
<g id="node1" class="node">
<title>K2</title>
<ellipse fill="none" stroke="black" cx="135" cy="-162" rx="27" ry="18"/>
<text text-anchor="middle" x="135" y="-156.95" font-family="Times,serif" font-size="14.00">K2</text>
</g>
<!-- K1 -->
<g id="node2" class="node">
<title>K1</title>
<ellipse fill="none" stroke="red" cx="99" cy="-90" rx="27" ry="18"/>
<text text-anchor="middle" x="99" y="-84.95" font-family="Times,serif" font-size="14.00" fill="red">K1</text>
</g>
<!-- K2&#45;&gt;K1 -->
<g id="edge1" class="edge">
<title>K2&#45;&gt;K1</title>
<path fill="none" stroke="black" d="M126.65,-144.76C122.42,-136.55 117.19,-126.37 112.42,-117.09"/>
<polygon fill="black" stroke="black" points="115.68,-115.79 108,-108.49 109.46,-118.99 115.68,-115.79"/>
</g>
<!-- K3 -->
<g id="node3" class="node">
<title>K3</title>
<ellipse fill="none" stroke="red" cx="171" cy="-90" rx="27" ry="18"/>
<text text-anchor="middle" x="171" y="-84.95" font-family="Times,serif" font-size="14.00" fill="red">K3</text>
</g>
<!-- K2&#45;&gt;K3 -->
<g id="edge2" class="edge">
<title>K2&#45;&gt;K3</title>
<path fill="none" stroke="black" d="M143.35,-144.76C147.58,-136.55 152.81,-126.37 157.58,-117.09"/>
<polygon fill="black" stroke="black" points="160.54,-118.99 162,-108.49 154.32,-115.79 160.54,-118.99"/>
</g>
<!-- A -->
<g id="node4" class="node">
<title>A</title>
<ellipse fill="none" stroke="black" cx="27" cy="-18" rx="27" ry="18"/>
<text text-anchor="middle" x="27" y="-12.95" font-family="Times,serif" font-size="14.00" fill="#fffffe" fill-opacity="0.000000">A</text>
</g>
<!-- K1&#45;&gt;A -->
<g id="edge3" class="edge">
<title>K1&#45;&gt;A</title>
<path fill="none" stroke="black" d="M84.08,-74.5C74.23,-64.92 61.14,-52.19 49.97,-41.34"/>
<polygon fill="black" stroke="black" points="52.59,-39 42.98,-34.54 47.71,-44.02 52.59,-39"/>
</g>
<!-- B -->
<g id="node5" class="node">
<title>B</title>
<ellipse fill="none" stroke="black" cx="99" cy="-18" rx="27" ry="18"/>
<text text-anchor="middle" x="99" y="-12.95" font-family="Times,serif" font-size="14.00" fill="#fffffe" fill-opacity="0.000000">B</text>
</g>
<!-- K1&#45;&gt;B -->
<g id="edge4" class="edge">
<title>K1&#45;&gt;B</title>
<path fill="none" stroke="black" d="M99,-71.7C99,-64.41 99,-55.73 99,-47.54"/>
<polygon fill="black" stroke="black" points="102.5,-47.62 99,-37.62 95.5,-47.62 102.5,-47.62"/>
</g>
<!-- C -->
<g id="node6" class="node">
<title>C</title>
<ellipse fill="none" stroke="black" cx="171" cy="-18" rx="27" ry="18"/>
<text text-anchor="middle" x="171" y="-12.95" font-family="Times,serif" font-size="14.00" fill="#fffffe" fill-opacity="0.000000">C</text>
</g>
<!-- K3&#45;&gt;C -->
<g id="edge5" class="edge">
<title>K3&#45;&gt;C</title>
<path fill="none" stroke="black" d="M171,-71.7C171,-64.41 171,-55.73 171,-47.54"/>
<polygon fill="black" stroke="black" points="174.5,-47.62 171,-37.62 167.5,-47.62 174.5,-47.62"/>
</g>
<!-- D -->
<g id="node7" class="node">
<title>D</title>
<ellipse fill="none" stroke="black" cx="243" cy="-18" rx="27" ry="18"/>
<text text-anchor="middle" x="243" y="-12.95" font-family="Times,serif" font-size="14.00" fill="#fffffe" fill-opacity="0.000000">D</text>
</g>
<!-- K3&#45;&gt;D -->
<g id="edge6" class="edge">
<title>K3&#45;&gt;D</title>
<path fill="none" stroke="black" d="M185.92,-74.5C195.77,-64.92 208.86,-52.19 220.03,-41.34"/>
<polygon fill="black" stroke="black" points="222.29,-44.02 227.02,-34.54 217.41,-39 222.29,-44.02"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -0,0 +1,8 @@
digraph {
K2 -> BH1
K2 -> BH1
BH1 [shape="box",label="black height 1",style="dotted",fontname="Italic"]
}

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 12.2.1 (20241206.2353)
-->
<!-- Pages: 1 -->
<svg width="101pt" height="116pt"
viewBox="0.00 0.00 101.25 116.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 112)">
<polygon fill="white" stroke="none" points="-4,4 -4,-112 97.25,-112 97.25,4 -4,4"/>
<!-- K2 -->
<g id="node1" class="node">
<title>K2</title>
<ellipse fill="none" stroke="black" cx="46.62" cy="-90" rx="27" ry="18"/>
<text text-anchor="middle" x="46.62" y="-84.95" font-family="Times,serif" font-size="14.00">K2</text>
</g>
<!-- BH1 -->
<g id="node2" class="node">
<title>BH1</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="93.25,-36 0,-36 0,0 93.25,0 93.25,-36"/>
<text text-anchor="middle" x="46.62" y="-11.82" font-family="Italic" font-size="14.00">black height 1</text>
</g>
<!-- K2&#45;&gt;BH1 -->
<g id="edge1" class="edge">
<title>K2&#45;&gt;BH1</title>
<path fill="none" stroke="black" d="M40.75,-72.05C39.96,-64.68 39.71,-55.84 39.98,-47.51"/>
<polygon fill="black" stroke="black" points="43.46,-47.99 40.61,-37.79 36.47,-47.54 43.46,-47.99"/>
</g>
<!-- K2&#45;&gt;BH1 -->
<g id="edge2" class="edge">
<title>K2&#45;&gt;BH1</title>
<path fill="none" stroke="black" d="M52.5,-72.05C53.29,-64.68 53.54,-55.84 53.27,-47.51"/>
<polygon fill="black" stroke="black" points="56.78,-47.54 52.64,-37.79 49.79,-47.99 56.78,-47.54"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1,10 @@
digraph {
K2 -> K1
K2 -> K3
K1 [color="red",fontcolor="red"]
K2
K3 [color="red",fontcolor="red"]
}

View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 12.2.1 (20241206.2353)
-->
<!-- Pages: 1 -->
<svg width="134pt" height="116pt"
viewBox="0.00 0.00 134.00 116.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 112)">
<polygon fill="white" stroke="none" points="-4,4 -4,-112 130,-112 130,4 -4,4"/>
<!-- K2 -->
<g id="node1" class="node">
<title>K2</title>
<ellipse fill="none" stroke="black" cx="63" cy="-90" rx="27" ry="18"/>
<text text-anchor="middle" x="63" y="-84.95" font-family="Times,serif" font-size="14.00">K2</text>
</g>
<!-- K1 -->
<g id="node2" class="node">
<title>K1</title>
<ellipse fill="none" stroke="red" cx="27" cy="-18" rx="27" ry="18"/>
<text text-anchor="middle" x="27" y="-12.95" font-family="Times,serif" font-size="14.00" fill="red">K1</text>
</g>
<!-- K2&#45;&gt;K1 -->
<g id="edge1" class="edge">
<title>K2&#45;&gt;K1</title>
<path fill="none" stroke="black" d="M54.65,-72.76C50.42,-64.55 45.19,-54.37 40.42,-45.09"/>
<polygon fill="black" stroke="black" points="43.68,-43.79 36,-36.49 37.46,-46.99 43.68,-43.79"/>
</g>
<!-- K3 -->
<g id="node3" class="node">
<title>K3</title>
<ellipse fill="none" stroke="red" cx="99" cy="-18" rx="27" ry="18"/>
<text text-anchor="middle" x="99" y="-12.95" font-family="Times,serif" font-size="14.00" fill="red">K3</text>
</g>
<!-- K2&#45;&gt;K3 -->
<g id="edge2" class="edge">
<title>K2&#45;&gt;K3</title>
<path fill="none" stroke="black" d="M71.35,-72.76C75.58,-64.55 80.81,-54.37 85.58,-45.09"/>
<polygon fill="black" stroke="black" points="88.54,-46.99 90,-36.49 82.32,-43.79 88.54,-46.99"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1,25 @@
digraph {
K2 -> K1
K2 -> K4
K4 -> K3
K4 -> X [color="invis"]
K1 -> BHn
K1 -> BHn
K4 -> BHnPlus1
K3 -> BHnPlus1
K3 -> BHnPlus1
K1 [label="K1 (uncle)"]
K2 [label="K2 (grandparent)"]
K4 [label="K4 (parent)",color="red",fontcolor="red"]
K3 [label="K3 (node)",color="red",fontcolor="red"]
X [color="invis",fontcolor="invis"]
BHn [shape="box",label="black height n",style="dotted",fontname="Italic"]
BHnPlus1 [shape="box",label="black height n + 1",style="dotted",fontname="Italic"]
}

View File

@ -0,0 +1,108 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 12.2.1 (20241206.2353)
-->
<!-- Pages: 1 -->
<svg width="308pt" height="260pt"
viewBox="0.00 0.00 308.08 260.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 256)">
<polygon fill="white" stroke="none" points="-4,4 -4,-256 304.08,-256 304.08,4 -4,4"/>
<!-- K2 -->
<g id="node1" class="node">
<title>K2</title>
<ellipse fill="none" stroke="black" cx="111.84" cy="-234" rx="74.89" ry="18"/>
<text text-anchor="middle" x="111.84" y="-228.95" font-family="Times,serif" font-size="14.00">K2 (grandparent)</text>
</g>
<!-- K1 -->
<g id="node2" class="node">
<title>K1</title>
<ellipse fill="none" stroke="black" cx="50.84" cy="-162" rx="50.84" ry="18"/>
<text text-anchor="middle" x="50.84" y="-156.95" font-family="Times,serif" font-size="14.00">K1 (uncle)</text>
</g>
<!-- K2&#45;&gt;K1 -->
<g id="edge1" class="edge">
<title>K2&#45;&gt;K1</title>
<path fill="none" stroke="black" d="M97.07,-216.05C89.7,-207.59 80.63,-197.19 72.49,-187.84"/>
<polygon fill="black" stroke="black" points="75.25,-185.69 66.04,-180.45 69.98,-190.29 75.25,-185.69"/>
</g>
<!-- K4 -->
<g id="node3" class="node">
<title>K4</title>
<ellipse fill="none" stroke="red" cx="215.84" cy="-162" rx="53.91" ry="18"/>
<text text-anchor="middle" x="215.84" y="-156.95" font-family="Times,serif" font-size="14.00" fill="red">K4 (parent)</text>
</g>
<!-- K2&#45;&gt;K4 -->
<g id="edge2" class="edge">
<title>K2&#45;&gt;K4</title>
<path fill="none" stroke="black" d="M136.22,-216.59C150.21,-207.17 167.95,-195.23 183.14,-185.01"/>
<polygon fill="black" stroke="black" points="185.08,-187.92 191.42,-179.43 181.17,-182.11 185.08,-187.92"/>
</g>
<!-- BHn -->
<g id="node6" class="node">
<title>BHn</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="97.46,-108 4.21,-108 4.21,-72 97.46,-72 97.46,-108"/>
<text text-anchor="middle" x="50.84" y="-83.83" font-family="Italic" font-size="14.00">black height n</text>
</g>
<!-- K1&#45;&gt;BHn -->
<g id="edge5" class="edge">
<title>K1&#45;&gt;BHn</title>
<path fill="none" stroke="black" d="M44.92,-143.7C44.17,-136.41 43.93,-127.73 44.19,-119.54"/>
<polygon fill="black" stroke="black" points="47.68,-119.82 44.85,-109.61 40.7,-119.36 47.68,-119.82"/>
</g>
<!-- K1&#45;&gt;BHn -->
<g id="edge6" class="edge">
<title>K1&#45;&gt;BHn</title>
<path fill="none" stroke="black" d="M56.76,-143.7C57.51,-136.41 57.75,-127.73 57.49,-119.54"/>
<polygon fill="black" stroke="black" points="60.98,-119.36 56.83,-109.61 54,-119.82 60.98,-119.36"/>
</g>
<!-- K3 -->
<g id="node4" class="node">
<title>K3</title>
<ellipse fill="none" stroke="red" cx="163.84" cy="-90" rx="48.79" ry="18"/>
<text text-anchor="middle" x="163.84" y="-84.95" font-family="Times,serif" font-size="14.00" fill="red">K3 (node)</text>
</g>
<!-- K4&#45;&gt;K3 -->
<g id="edge3" class="edge">
<title>K4&#45;&gt;K3</title>
<path fill="none" stroke="black" d="M203.25,-144.05C197.18,-135.89 189.77,-125.91 183.02,-116.82"/>
<polygon fill="black" stroke="black" points="185.99,-114.94 177.21,-109 180.37,-119.12 185.99,-114.94"/>
</g>
<!-- X -->
<g id="node5" class="node">
<title>X</title>
<ellipse fill="none" stroke="none" cx="257.84" cy="-90" rx="27" ry="18"/>
<text text-anchor="middle" x="257.84" y="-84.95" font-family="Times,serif" font-size="14.00" fill="#fffffe" fill-opacity="0.000000">X</text>
</g>
<!-- K4&#45;&gt;X -->
<g id="edge4" class="edge">
<title>K4&#45;&gt;X</title>
<path fill="none" stroke="none" d="M226.01,-144.05C230.95,-135.82 236.99,-125.76 242.47,-116.61"/>
<polygon fill="none" stroke="none" points="245.42,-118.5 247.56,-108.13 239.42,-114.9 245.42,-118.5"/>
</g>
<!-- BHnPlus1 -->
<g id="node7" class="node">
<title>BHnPlus1</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="222.46,-36 105.21,-36 105.21,0 222.46,0 222.46,-36"/>
<text text-anchor="middle" x="163.84" y="-11.82" font-family="Italic" font-size="14.00">black height n + 1</text>
</g>
<!-- K4&#45;&gt;BHnPlus1 -->
<g id="edge7" class="edge">
<title>K4&#45;&gt;BHnPlus1</title>
<path fill="none" stroke="black" d="M249.09,-147.57C265.74,-138.94 284.34,-125.94 293.84,-108 301.33,-93.86 302.77,-85.28 293.84,-72 280.05,-51.48 256.77,-38.9 233.7,-31.19"/>
<polygon fill="black" stroke="black" points="234.82,-27.88 224.24,-28.32 232.79,-34.57 234.82,-27.88"/>
</g>
<!-- K3&#45;&gt;BHnPlus1 -->
<g id="edge8" class="edge">
<title>K3&#45;&gt;BHnPlus1</title>
<path fill="none" stroke="black" d="M157.92,-71.7C157.17,-64.41 156.93,-55.73 157.19,-47.54"/>
<polygon fill="black" stroke="black" points="160.68,-47.82 157.85,-37.61 153.7,-47.36 160.68,-47.82"/>
</g>
<!-- K3&#45;&gt;BHnPlus1 -->
<g id="edge9" class="edge">
<title>K3&#45;&gt;BHnPlus1</title>
<path fill="none" stroke="black" d="M169.76,-71.7C170.51,-64.41 170.75,-55.73 170.49,-47.54"/>
<polygon fill="black" stroke="black" points="173.98,-47.36 169.83,-37.61 167,-47.82 173.98,-47.36"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

@ -0,0 +1,25 @@
digraph {
K2 -> K1
K2 -> K3
K3 -> BHnPlus1
K3 -> X [color="invis"]
K3 -> K4
K1 -> BHn
K1 -> BHn
K4 -> BHnPlus1
K4 -> BHnPlus1
K1 [label="K1 (uncle)"]
K2 [label="K2 (grandparent)"]
K3 [label="K3 (parent)",color="red",fontcolor="red"]
K4 [color="red",fontcolor="red"]
X [color="invis",fontcolor="invis"]
BHn [shape="box",label="black height n",style="dotted",fontname="Italic"]
BHnPlus1 [shape="box",label="black height n + 1",style="dotted",fontname="Italic"]
}

View File

@ -0,0 +1,108 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 12.2.1 (20241206.2353)
-->
<!-- Pages: 1 -->
<svg width="319pt" height="260pt"
viewBox="0.00 0.00 319.46 260.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 256)">
<polygon fill="white" stroke="none" points="-4,4 -4,-256 315.46,-256 315.46,4 -4,4"/>
<!-- K2 -->
<g id="node1" class="node">
<title>K2</title>
<ellipse fill="none" stroke="black" cx="111.84" cy="-234" rx="74.89" ry="18"/>
<text text-anchor="middle" x="111.84" y="-228.95" font-family="Times,serif" font-size="14.00">K2 (grandparent)</text>
</g>
<!-- K1 -->
<g id="node2" class="node">
<title>K1</title>
<ellipse fill="none" stroke="black" cx="50.84" cy="-162" rx="50.84" ry="18"/>
<text text-anchor="middle" x="50.84" y="-156.95" font-family="Times,serif" font-size="14.00">K1 (uncle)</text>
</g>
<!-- K2&#45;&gt;K1 -->
<g id="edge1" class="edge">
<title>K2&#45;&gt;K1</title>
<path fill="none" stroke="black" d="M97.07,-216.05C89.7,-207.59 80.63,-197.19 72.49,-187.84"/>
<polygon fill="black" stroke="black" points="75.25,-185.69 66.04,-180.45 69.98,-190.29 75.25,-185.69"/>
</g>
<!-- K3 -->
<g id="node3" class="node">
<title>K3</title>
<ellipse fill="none" stroke="red" cx="176.84" cy="-162" rx="53.91" ry="18"/>
<text text-anchor="middle" x="176.84" y="-156.95" font-family="Times,serif" font-size="14.00" fill="red">K3 (parent)</text>
</g>
<!-- K2&#45;&gt;K3 -->
<g id="edge2" class="edge">
<title>K2&#45;&gt;K3</title>
<path fill="none" stroke="black" d="M127.57,-216.05C135.51,-207.5 145.29,-196.97 154.04,-187.56"/>
<polygon fill="black" stroke="black" points="156.43,-190.13 160.67,-180.42 151.3,-185.36 156.43,-190.13"/>
</g>
<!-- BHn -->
<g id="node7" class="node">
<title>BHn</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="97.46,-108 4.21,-108 4.21,-72 97.46,-72 97.46,-108"/>
<text text-anchor="middle" x="50.84" y="-83.83" font-family="Italic" font-size="14.00">black height n</text>
</g>
<!-- K1&#45;&gt;BHn -->
<g id="edge6" class="edge">
<title>K1&#45;&gt;BHn</title>
<path fill="none" stroke="black" d="M44.92,-143.7C44.17,-136.41 43.93,-127.73 44.19,-119.54"/>
<polygon fill="black" stroke="black" points="47.68,-119.82 44.85,-109.61 40.7,-119.36 47.68,-119.82"/>
</g>
<!-- K1&#45;&gt;BHn -->
<g id="edge7" class="edge">
<title>K1&#45;&gt;BHn</title>
<path fill="none" stroke="black" d="M56.76,-143.7C57.51,-136.41 57.75,-127.73 57.49,-119.54"/>
<polygon fill="black" stroke="black" points="60.98,-119.36 56.83,-109.61 54,-119.82 60.98,-119.36"/>
</g>
<!-- BHnPlus1 -->
<g id="node4" class="node">
<title>BHnPlus1</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="311.46,-36 194.21,-36 194.21,0 311.46,0 311.46,-36"/>
<text text-anchor="middle" x="252.84" y="-11.82" font-family="Italic" font-size="14.00">black height n + 1</text>
</g>
<!-- K3&#45;&gt;BHnPlus1 -->
<g id="edge3" class="edge">
<title>K3&#45;&gt;BHnPlus1</title>
<path fill="none" stroke="black" d="M162.41,-144.31C148.16,-125.69 130.42,-95.13 144.84,-72 153.95,-57.39 168.39,-46.69 183.78,-38.9"/>
<polygon fill="black" stroke="black" points="185.01,-42.19 192.62,-34.82 182.07,-35.84 185.01,-42.19"/>
</g>
<!-- X -->
<g id="node5" class="node">
<title>X</title>
<ellipse fill="none" stroke="none" cx="180.84" cy="-90" rx="27" ry="18"/>
<text text-anchor="middle" x="180.84" y="-84.95" font-family="Times,serif" font-size="14.00" fill="#fffffe" fill-opacity="0.000000">X</text>
</g>
<!-- K3&#45;&gt;X -->
<g id="edge4" class="edge">
<title>K3&#45;&gt;X</title>
<path fill="none" stroke="none" d="M177.83,-143.7C178.24,-136.41 178.74,-127.73 179.21,-119.54"/>
<polygon fill="none" stroke="none" points="182.7,-119.8 179.78,-109.62 175.71,-119.4 182.7,-119.8"/>
</g>
<!-- K4 -->
<g id="node6" class="node">
<title>K4</title>
<ellipse fill="none" stroke="red" cx="252.84" cy="-90" rx="27" ry="18"/>
<text text-anchor="middle" x="252.84" y="-84.95" font-family="Times,serif" font-size="14.00" fill="red">K4</text>
</g>
<!-- K3&#45;&gt;K4 -->
<g id="edge5" class="edge">
<title>K3&#45;&gt;K4</title>
<path fill="none" stroke="black" d="M194.47,-144.76C204.71,-135.33 217.75,-123.32 228.91,-113.04"/>
<polygon fill="black" stroke="black" points="231.27,-115.62 236.25,-106.28 226.53,-110.48 231.27,-115.62"/>
</g>
<!-- K4&#45;&gt;BHnPlus1 -->
<g id="edge8" class="edge">
<title>K4&#45;&gt;BHnPlus1</title>
<path fill="none" stroke="black" d="M246.96,-72.05C246.18,-64.68 245.92,-55.84 246.19,-47.51"/>
<polygon fill="black" stroke="black" points="249.67,-47.99 246.83,-37.79 242.68,-47.54 249.67,-47.99"/>
</g>
<!-- K4&#45;&gt;BHnPlus1 -->
<g id="edge9" class="edge">
<title>K4&#45;&gt;BHnPlus1</title>
<path fill="none" stroke="black" d="M258.72,-72.05C259.5,-64.68 259.76,-55.84 259.49,-47.51"/>
<polygon fill="black" stroke="black" points="262.99,-47.54 258.85,-37.79 256.01,-47.99 262.99,-47.54"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

@ -0,0 +1,25 @@
digraph {
K3 -> K2
K2 -> K1
K2 -> X [color="white"]
K3 -> K4
K1 -> BHn
K1 -> BHn
K2 -> BHnPlus1
K4 -> BHnPlus1
K4 -> BHnPlus1
K1 [label="K1 (uncle)"]
K2 [label="K2 (grandparent)",color="red",fontcolor="red"]
K3 [label="K3 (parent)"]
K4 [color="red",fontcolor="red"]
X [color="white",fontcolor="white"]
BHn [shape="box",label="black height n",style="dotted",fontname="Italic"]
BHnPlus1 [shape="box",label="black height n + 1",style="dotted",fontname="Italic"]
}

View File

@ -0,0 +1,108 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 12.2.1 (20241206.2353)
-->
<!-- Pages: 1 -->
<svg width="325pt" height="260pt"
viewBox="0.00 0.00 325.46 260.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 256)">
<polygon fill="white" stroke="none" points="-4,4 -4,-256 321.46,-256 321.46,4 -4,4"/>
<!-- K3 -->
<g id="node1" class="node">
<title>K3</title>
<ellipse fill="none" stroke="black" cx="198.84" cy="-234" rx="53.91" ry="18"/>
<text text-anchor="middle" x="198.84" y="-228.95" font-family="Times,serif" font-size="14.00">K3 (parent)</text>
</g>
<!-- K2 -->
<g id="node2" class="node">
<title>K2</title>
<ellipse fill="none" stroke="red" cx="138.84" cy="-162" rx="74.89" ry="18"/>
<text text-anchor="middle" x="138.84" y="-156.95" font-family="Times,serif" font-size="14.00" fill="red">K2 (grandparent)</text>
</g>
<!-- K3&#45;&gt;K2 -->
<g id="edge1" class="edge">
<title>K3&#45;&gt;K2</title>
<path fill="none" stroke="black" d="M184.62,-216.41C177.48,-208.08 168.67,-197.8 160.69,-188.49"/>
<polygon fill="black" stroke="black" points="163.52,-186.42 154.36,-181.11 158.21,-190.98 163.52,-186.42"/>
</g>
<!-- K4 -->
<g id="node5" class="node">
<title>K4</title>
<ellipse fill="none" stroke="red" cx="258.84" cy="-162" rx="27" ry="18"/>
<text text-anchor="middle" x="258.84" y="-156.95" font-family="Times,serif" font-size="14.00" fill="red">K4</text>
</g>
<!-- K3&#45;&gt;K4 -->
<g id="edge4" class="edge">
<title>K3&#45;&gt;K4</title>
<path fill="none" stroke="black" d="M213.06,-216.41C220.7,-207.5 230.25,-196.35 238.65,-186.56"/>
<polygon fill="black" stroke="black" points="241.11,-189.06 244.96,-179.19 235.8,-184.5 241.11,-189.06"/>
</g>
<!-- K1 -->
<g id="node3" class="node">
<title>K1</title>
<ellipse fill="none" stroke="black" cx="50.84" cy="-90" rx="50.84" ry="18"/>
<text text-anchor="middle" x="50.84" y="-84.95" font-family="Times,serif" font-size="14.00">K1 (uncle)</text>
</g>
<!-- K2&#45;&gt;K1 -->
<g id="edge2" class="edge">
<title>K2&#45;&gt;K1</title>
<path fill="none" stroke="black" d="M117.98,-144.41C106.53,-135.3 92.16,-123.87 79.65,-113.92"/>
<polygon fill="black" stroke="black" points="82.13,-111.42 72.12,-107.93 77.77,-116.89 82.13,-111.42"/>
</g>
<!-- X -->
<g id="node4" class="node">
<title>X</title>
<ellipse fill="none" stroke="white" cx="146.84" cy="-90" rx="27" ry="18"/>
<text text-anchor="middle" x="146.84" y="-84.95" font-family="Times,serif" font-size="14.00" fill="white">X</text>
</g>
<!-- K2&#45;&gt;X -->
<g id="edge3" class="edge">
<title>K2&#45;&gt;X</title>
<path fill="none" stroke="white" d="M140.82,-143.7C141.65,-136.41 142.64,-127.73 143.58,-119.54"/>
<polygon fill="white" stroke="white" points="147.05,-119.94 144.71,-109.61 140.1,-119.15 147.05,-119.94"/>
</g>
<!-- BHnPlus1 -->
<g id="node7" class="node">
<title>BHnPlus1</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="317.46,-108 200.21,-108 200.21,-72 317.46,-72 317.46,-108"/>
<text text-anchor="middle" x="258.84" y="-83.83" font-family="Italic" font-size="14.00">black height n + 1</text>
</g>
<!-- K2&#45;&gt;BHnPlus1 -->
<g id="edge7" class="edge">
<title>K2&#45;&gt;BHnPlus1</title>
<path fill="none" stroke="black" d="M166.37,-144.94C181.99,-135.83 201.81,-124.27 219.09,-114.19"/>
<polygon fill="black" stroke="black" points="220.73,-117.28 227.61,-109.22 217.21,-111.23 220.73,-117.28"/>
</g>
<!-- BHn -->
<g id="node6" class="node">
<title>BHn</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="97.46,-36 4.21,-36 4.21,0 97.46,0 97.46,-36"/>
<text text-anchor="middle" x="50.84" y="-11.82" font-family="Italic" font-size="14.00">black height n</text>
</g>
<!-- K1&#45;&gt;BHn -->
<g id="edge5" class="edge">
<title>K1&#45;&gt;BHn</title>
<path fill="none" stroke="black" d="M44.92,-71.7C44.17,-64.41 43.93,-55.73 44.19,-47.54"/>
<polygon fill="black" stroke="black" points="47.68,-47.82 44.85,-37.61 40.7,-47.36 47.68,-47.82"/>
</g>
<!-- K1&#45;&gt;BHn -->
<g id="edge6" class="edge">
<title>K1&#45;&gt;BHn</title>
<path fill="none" stroke="black" d="M56.76,-71.7C57.51,-64.41 57.75,-55.73 57.49,-47.54"/>
<polygon fill="black" stroke="black" points="60.98,-47.36 56.83,-37.61 54,-47.82 60.98,-47.36"/>
</g>
<!-- K4&#45;&gt;BHnPlus1 -->
<g id="edge8" class="edge">
<title>K4&#45;&gt;BHnPlus1</title>
<path fill="none" stroke="black" d="M252.96,-144.05C252.18,-136.68 251.92,-127.84 252.19,-119.51"/>
<polygon fill="black" stroke="black" points="255.67,-119.99 252.83,-109.79 248.68,-119.54 255.67,-119.99"/>
</g>
<!-- K4&#45;&gt;BHnPlus1 -->
<g id="edge9" class="edge">
<title>K4&#45;&gt;BHnPlus1</title>
<path fill="none" stroke="black" d="M264.72,-144.05C265.5,-136.68 265.76,-127.84 265.49,-119.51"/>
<polygon fill="black" stroke="black" points="268.99,-119.54 264.85,-109.79 262.01,-119.99 268.99,-119.54"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

@ -0,0 +1,28 @@
digraph {
K2 -> K1
K2 -> K3
K3 -> BHn
K3 -> X1 [color="invis"]
K3 -> K4
K1 [label="K1 (uncle)",color="red",fontcolor="red"]
K2 [label="K2 (grandparent)"]
K3 [label="K3 (parent)",color="red",fontcolor="red"]
K4 [color="red",fontcolor="red"]
X1 [color="invis",fontcolor="invis"]
X2 [color="invis",fontcolor="invis"]
BHn [shape="box",label="black height n",style="dotted",fontname="Italic"]
K1 -> X2 [color="invis"]
X2 -> BHn [color="invis"]
K1 -> BHn
K1 -> BHn
K4 -> BHn
K4 -> BHn
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 12.2.1 (20241206.2353)
-->
<!-- Pages: 1 -->
<svg width="307pt" height="260pt"
viewBox="0.00 0.00 306.84 260.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 256)">
<polygon fill="white" stroke="none" points="-4,4 -4,-256 302.84,-256 302.84,4 -4,4"/>
<!-- K2 -->
<g id="node1" class="node">
<title>K2</title>
<ellipse fill="none" stroke="black" cx="111.84" cy="-234" rx="74.89" ry="18"/>
<text text-anchor="middle" x="111.84" y="-228.95" font-family="Times,serif" font-size="14.00">K2 (grandparent)</text>
</g>
<!-- K1 -->
<g id="node2" class="node">
<title>K1</title>
<ellipse fill="none" stroke="red" cx="50.84" cy="-162" rx="50.84" ry="18"/>
<text text-anchor="middle" x="50.84" y="-156.95" font-family="Times,serif" font-size="14.00" fill="red">K1 (uncle)</text>
</g>
<!-- K2&#45;&gt;K1 -->
<g id="edge1" class="edge">
<title>K2&#45;&gt;K1</title>
<path fill="none" stroke="black" d="M97.07,-216.05C89.7,-207.59 80.63,-197.19 72.49,-187.84"/>
<polygon fill="black" stroke="black" points="75.25,-185.69 66.04,-180.45 69.98,-190.29 75.25,-185.69"/>
</g>
<!-- K3 -->
<g id="node3" class="node">
<title>K3</title>
<ellipse fill="none" stroke="red" cx="186.84" cy="-162" rx="53.91" ry="18"/>
<text text-anchor="middle" x="186.84" y="-156.95" font-family="Times,serif" font-size="14.00" fill="red">K3 (parent)</text>
</g>
<!-- K2&#45;&gt;K3 -->
<g id="edge2" class="edge">
<title>K2&#45;&gt;K3</title>
<path fill="none" stroke="black" d="M130,-216.05C139.34,-207.33 150.9,-196.54 161.15,-186.98"/>
<polygon fill="black" stroke="black" points="163.34,-189.72 168.26,-180.34 158.56,-184.6 163.34,-189.72"/>
</g>
<!-- BHn -->
<g id="node4" class="node">
<title>BHn</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="163.46,-36 70.21,-36 70.21,0 163.46,0 163.46,-36"/>
<text text-anchor="middle" x="116.84" y="-11.82" font-family="Italic" font-size="14.00">black height n</text>
</g>
<!-- K1&#45;&gt;BHn -->
<g id="edge8" class="edge">
<title>K1&#45;&gt;BHn</title>
<path fill="none" stroke="black" d="M40.89,-143.95C35.66,-125.28 33.69,-94.94 44.84,-72 50.29,-60.78 59.35,-51.05 69.28,-43.1"/>
<polygon fill="black" stroke="black" points="71.34,-45.93 77.34,-37.2 67.21,-40.28 71.34,-45.93"/>
</g>
<!-- K1&#45;&gt;BHn -->
<g id="edge9" class="edge">
<title>K1&#45;&gt;BHn</title>
<path fill="none" stroke="black" d="M54.06,-143.61C53.64,-124.91 51.75,-94.8 62.84,-72 68.24,-60.9 77.17,-51.25 86.29,-43.34"/>
<polygon fill="black" stroke="black" points="88.23,-46.27 93.8,-37.26 83.82,-40.83 88.23,-46.27"/>
</g>
<!-- X2 -->
<g id="node7" class="node">
<title>X2</title>
<ellipse fill="none" stroke="none" cx="89.84" cy="-90" rx="27" ry="18"/>
<text text-anchor="middle" x="89.84" y="-84.95" font-family="Times,serif" font-size="14.00" fill="#fffffe" fill-opacity="0.000000">X2</text>
</g>
<!-- K1&#45;&gt;X2 -->
<g id="edge6" class="edge">
<title>K1&#45;&gt;X2</title>
<path fill="none" stroke="none" d="M60.28,-144.05C64.75,-136.03 70.2,-126.26 75.19,-117.3"/>
<polygon fill="none" stroke="none" points="78.21,-119.07 80.02,-108.63 72.09,-115.66 78.21,-119.07"/>
</g>
<!-- K3&#45;&gt;BHn -->
<g id="edge3" class="edge">
<title>K3&#45;&gt;BHn</title>
<path fill="none" stroke="black" d="M178.4,-143.87C166.47,-119.67 144.55,-75.21 130.34,-46.39"/>
<polygon fill="black" stroke="black" points="133.54,-44.97 125.98,-37.55 127.26,-48.06 133.54,-44.97"/>
</g>
<!-- X1 -->
<g id="node5" class="node">
<title>X1</title>
<ellipse fill="none" stroke="none" cx="199.84" cy="-90" rx="27" ry="18"/>
<text text-anchor="middle" x="199.84" y="-84.95" font-family="Times,serif" font-size="14.00" fill="#fffffe" fill-opacity="0.000000">X1</text>
</g>
<!-- K3&#45;&gt;X1 -->
<g id="edge4" class="edge">
<title>K3&#45;&gt;X1</title>
<path fill="none" stroke="none" d="M190.05,-143.7C191.42,-136.32 193.06,-127.52 194.59,-119.25"/>
<polygon fill="none" stroke="none" points="198,-120.06 196.39,-109.59 191.12,-118.79 198,-120.06"/>
</g>
<!-- K4 -->
<g id="node6" class="node">
<title>K4</title>
<ellipse fill="none" stroke="red" cx="271.84" cy="-90" rx="27" ry="18"/>
<text text-anchor="middle" x="271.84" y="-84.95" font-family="Times,serif" font-size="14.00" fill="red">K4</text>
</g>
<!-- K3&#45;&gt;K4 -->
<g id="edge5" class="edge">
<title>K3&#45;&gt;K4</title>
<path fill="none" stroke="black" d="M206.55,-144.76C218.47,-134.95 233.78,-122.34 246.58,-111.8"/>
<polygon fill="black" stroke="black" points="248.71,-114.58 254.21,-105.52 244.26,-109.18 248.71,-114.58"/>
</g>
<!-- K4&#45;&gt;BHn -->
<g id="edge10" class="edge">
<title>K4&#45;&gt;BHn</title>
<path fill="none" stroke="black" d="M247.74,-81.48C240.82,-78.49 233.5,-75.05 226.84,-72 204.43,-61.72 179.53,-50.59 159.02,-41.19"/>
<polygon fill="black" stroke="black" points="160.65,-38.09 150.11,-37.08 157.72,-44.44 160.65,-38.09"/>
</g>
<!-- K4&#45;&gt;BHn -->
<g id="edge11" class="edge">
<title>K4&#45;&gt;BHn</title>
<path fill="none" stroke="black" d="M253.69,-76.13C250.74,-74.72 247.73,-73.33 244.84,-72 221.95,-61.5 196.45,-50.1 174.21,-40.58"/>
<polygon fill="black" stroke="black" points="175.88,-37.49 165.31,-36.8 173.14,-43.93 175.88,-37.49"/>
</g>
<!-- X2&#45;&gt;BHn -->
<g id="edge7" class="edge">
<title>X2&#45;&gt;BHn</title>
<path fill="none" stroke="none" d="M96.38,-72.05C99.28,-64.52 102.79,-55.44 106.06,-46.94"/>
<polygon fill="none" stroke="none" points="109.3,-48.28 109.63,-37.69 102.77,-45.76 109.3,-48.28"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

@ -0,0 +1,29 @@
digraph {
P -> K2 [dir="back",style="dotted"]
K2 -> K1
K2 -> K3
K3 -> BHn
K3 -> X [color="invis"]
K3 -> K4
K1 [label="K1 (uncle)"]
K2 [label="K2 (node)",color="red",fontcolor="red"]
K3 [label="K3"]
K4 [color="red",fontcolor="red"]
X [color="invis",fontcolor="invis"]
Y [color="invis",fontcolor="invis"]
P [label="parent",color="gray",fontcolor="gray"]
BHn [shape="box",label="black height n",style="dotted",fontname="Italic"]
K1 -> BHn
K1 -> Y [color="invis"]
Y -> BHn [color="invis"]
K1 -> BHn
K4 -> BHn
K4 -> BHn
}

View File

@ -0,0 +1,132 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 12.2.1 (20241206.2353)
-->
<!-- Pages: 1 -->
<svg width="294pt" height="332pt"
viewBox="0.00 0.00 293.84 332.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 328)">
<polygon fill="white" stroke="none" points="-4,4 -4,-328 289.84,-328 289.84,4 -4,4"/>
<!-- P -->
<g id="node1" class="node">
<title>P</title>
<ellipse fill="none" stroke="gray" cx="98.84" cy="-306" rx="33.95" ry="18"/>
<text text-anchor="middle" x="98.84" y="-300.95" font-family="Times,serif" font-size="14.00" fill="gray">parent</text>
</g>
<!-- K2 -->
<g id="node2" class="node">
<title>K2</title>
<ellipse fill="none" stroke="red" cx="98.84" cy="-234" rx="48.79" ry="18"/>
<text text-anchor="middle" x="98.84" y="-228.95" font-family="Times,serif" font-size="14.00" fill="red">K2 (node)</text>
</g>
<!-- P&#45;&gt;K2 -->
<g id="edge1" class="edge">
<title>P&#45;&gt;K2</title>
<path fill="none" stroke="black" stroke-dasharray="1,5" d="M98.84,-276.24C98.84,-268.04 98.84,-259.37 98.84,-252.1"/>
<polygon fill="black" stroke="black" points="95.34,-276.18 98.84,-286.18 102.34,-276.18 95.34,-276.18"/>
</g>
<!-- K1 -->
<g id="node3" class="node">
<title>K1</title>
<ellipse fill="none" stroke="black" cx="50.84" cy="-162" rx="50.84" ry="18"/>
<text text-anchor="middle" x="50.84" y="-156.95" font-family="Times,serif" font-size="14.00">K1 (uncle)</text>
</g>
<!-- K2&#45;&gt;K1 -->
<g id="edge2" class="edge">
<title>K2&#45;&gt;K1</title>
<path fill="none" stroke="black" d="M87.22,-216.05C81.68,-207.97 74.92,-198.12 68.74,-189.11"/>
<polygon fill="black" stroke="black" points="71.75,-187.31 63.21,-181.04 65.98,-191.26 71.75,-187.31"/>
</g>
<!-- K3 -->
<g id="node4" class="node">
<title>K3</title>
<ellipse fill="none" stroke="black" cx="157.84" cy="-162" rx="27" ry="18"/>
<text text-anchor="middle" x="157.84" y="-156.95" font-family="Times,serif" font-size="14.00">K3</text>
</g>
<!-- K2&#45;&gt;K3 -->
<g id="edge3" class="edge">
<title>K2&#45;&gt;K3</title>
<path fill="none" stroke="black" d="M112.82,-216.41C120.34,-207.5 129.73,-196.35 137.99,-186.56"/>
<polygon fill="black" stroke="black" points="140.42,-189.1 144.19,-179.2 135.07,-184.59 140.42,-189.1"/>
</g>
<!-- BHn -->
<g id="node5" class="node">
<title>BHn</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="150.46,-36 57.21,-36 57.21,0 150.46,0 150.46,-36"/>
<text text-anchor="middle" x="103.84" y="-11.82" font-family="Italic" font-size="14.00">black height n</text>
</g>
<!-- K1&#45;&gt;BHn -->
<g id="edge7" class="edge">
<title>K1&#45;&gt;BHn</title>
<path fill="none" stroke="black" d="M37.42,-144.41C28.39,-125.87 20.95,-95.4 31.84,-72 37.06,-60.79 45.95,-51.1 55.77,-43.19"/>
<polygon fill="black" stroke="black" points="57.77,-46.06 63.76,-37.33 53.63,-40.42 57.77,-46.06"/>
</g>
<!-- K1&#45;&gt;BHn -->
<g id="edge10" class="edge">
<title>K1&#45;&gt;BHn</title>
<path fill="none" stroke="black" d="M50.36,-143.74C46.21,-125.14 39.08,-95.12 49.84,-72 54.95,-61.02 63.58,-51.5 72.52,-43.68"/>
<polygon fill="black" stroke="black" points="74.71,-46.41 80.26,-37.39 70.29,-40.98 74.71,-46.41"/>
</g>
<!-- Y -->
<g id="node8" class="node">
<title>Y</title>
<ellipse fill="none" stroke="none" cx="76.84" cy="-90" rx="27" ry="18"/>
<text text-anchor="middle" x="76.84" y="-84.95" font-family="Times,serif" font-size="14.00" fill="#fffffe" fill-opacity="0.000000">Y</text>
</g>
<!-- K1&#45;&gt;Y -->
<g id="edge8" class="edge">
<title>K1&#45;&gt;Y</title>
<path fill="none" stroke="none" d="M57.27,-143.7C60.11,-136.04 63.52,-126.85 66.7,-118.3"/>
<polygon fill="none" stroke="none" points="69.94,-119.63 70.14,-109.04 63.38,-117.2 69.94,-119.63"/>
</g>
<!-- K3&#45;&gt;BHn -->
<g id="edge4" class="edge">
<title>K3&#45;&gt;BHn</title>
<path fill="none" stroke="black" d="M151.43,-144.15C142.31,-120.16 125.45,-75.84 114.45,-46.9"/>
<polygon fill="black" stroke="black" points="117.77,-45.79 110.94,-37.68 111.23,-48.27 117.77,-45.79"/>
</g>
<!-- X -->
<g id="node6" class="node">
<title>X</title>
<ellipse fill="none" stroke="none" cx="186.84" cy="-90" rx="27" ry="18"/>
<text text-anchor="middle" x="186.84" y="-84.95" font-family="Times,serif" font-size="14.00" fill="#fffffe" fill-opacity="0.000000">X</text>
</g>
<!-- K3&#45;&gt;X -->
<g id="edge5" class="edge">
<title>K3&#45;&gt;X</title>
<path fill="none" stroke="none" d="M164.71,-144.41C168,-136.48 172.02,-126.78 175.72,-117.84"/>
<polygon fill="none" stroke="none" points="178.84,-119.45 179.44,-108.87 172.38,-116.77 178.84,-119.45"/>
</g>
<!-- K4 -->
<g id="node7" class="node">
<title>K4</title>
<ellipse fill="none" stroke="red" cx="258.84" cy="-90" rx="27" ry="18"/>
<text text-anchor="middle" x="258.84" y="-84.95" font-family="Times,serif" font-size="14.00" fill="red">K4</text>
</g>
<!-- K3&#45;&gt;K4 -->
<g id="edge6" class="edge">
<title>K3&#45;&gt;K4</title>
<path fill="none" stroke="black" d="M175.9,-148.49C191.31,-137.8 213.72,-122.27 231.36,-110.04"/>
<polygon fill="black" stroke="black" points="233.13,-113.08 239.35,-104.5 229.14,-107.32 233.13,-113.08"/>
</g>
<!-- K4&#45;&gt;BHn -->
<g id="edge11" class="edge">
<title>K4&#45;&gt;BHn</title>
<path fill="none" stroke="black" d="M234.74,-81.48C227.82,-78.49 220.5,-75.05 213.84,-72 191.43,-61.72 166.53,-50.59 146.02,-41.19"/>
<polygon fill="black" stroke="black" points="147.65,-38.09 137.11,-37.08 144.72,-44.44 147.65,-38.09"/>
</g>
<!-- K4&#45;&gt;BHn -->
<g id="edge12" class="edge">
<title>K4&#45;&gt;BHn</title>
<path fill="none" stroke="black" d="M240.69,-76.13C237.74,-74.72 234.73,-73.33 231.84,-72 208.95,-61.5 183.45,-50.1 161.21,-40.58"/>
<polygon fill="black" stroke="black" points="162.88,-37.49 152.31,-36.8 160.14,-43.93 162.88,-37.49"/>
</g>
<!-- Y&#45;&gt;BHn -->
<g id="edge9" class="edge">
<title>Y&#45;&gt;BHn</title>
<path fill="none" stroke="none" d="M83.38,-72.05C86.28,-64.52 89.79,-55.44 93.06,-46.94"/>
<polygon fill="none" stroke="none" points="96.3,-48.28 96.63,-37.69 89.77,-45.76 96.3,-48.28"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

@ -0,0 +1,23 @@
digraph {
K6 -> K2
K6 -> BH1
K2 -> K1
K2 -> K4
K1 -> BH2
K1 -> BH2
K4 -> BH3
K4 -> BH3
K1 [label="K1 (distantNephew)"]
K2 [label="K2 (sibling)"]
K4 [label="K4 (closeNephew)"]
K6 [label="K6 (parent)"]
BH1 [shape="box",label="black height i + 1",style="dotted",fontname="Italic"]
BH2 [shape="box",label="black height i",style="dotted",fontname="Italic"]
BH3 [shape="box",label="black height i",style="dotted",fontname="Italic"]
}

View File

@ -0,0 +1,102 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 12.2.1 (20241206.2353)
-->
<!-- Pages: 1 -->
<svg width="374pt" height="260pt"
viewBox="0.00 0.00 374.28 260.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 256)">
<polygon fill="white" stroke="none" points="-4,4 -4,-256 370.28,-256 370.28,4 -4,4"/>
<!-- K6 -->
<g id="node1" class="node">
<title>K6</title>
<ellipse fill="none" stroke="black" cx="243.15" cy="-234" rx="53.91" ry="18"/>
<text text-anchor="middle" x="243.15" y="-228.95" font-family="Times,serif" font-size="14.00">K6 (parent)</text>
</g>
<!-- K2 -->
<g id="node2" class="node">
<title>K2</title>
<ellipse fill="none" stroke="black" cx="178.15" cy="-162" rx="55.96" ry="18"/>
<text text-anchor="middle" x="178.15" y="-156.95" font-family="Times,serif" font-size="14.00">K2 (sibling)</text>
</g>
<!-- K6&#45;&gt;K2 -->
<g id="edge1" class="edge">
<title>K6&#45;&gt;K2</title>
<path fill="none" stroke="black" d="M227.75,-216.41C219.82,-207.87 209.98,-197.28 201.17,-187.79"/>
<polygon fill="black" stroke="black" points="203.85,-185.53 194.48,-180.58 198.72,-190.29 203.85,-185.53"/>
</g>
<!-- BH1 -->
<g id="node3" class="node">
<title>BH1</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="366.28,-180 252.03,-180 252.03,-144 366.28,-144 366.28,-180"/>
<text text-anchor="middle" x="309.15" y="-155.82" font-family="Italic" font-size="14.00">black height i + 1</text>
</g>
<!-- K6&#45;&gt;BH1 -->
<g id="edge2" class="edge">
<title>K6&#45;&gt;BH1</title>
<path fill="none" stroke="black" d="M258.8,-216.41C266.62,-208.12 276.26,-197.89 285,-188.62"/>
<polygon fill="black" stroke="black" points="287.35,-191.22 291.67,-181.55 282.26,-186.42 287.35,-191.22"/>
</g>
<!-- K1 -->
<g id="node4" class="node">
<title>K1</title>
<ellipse fill="none" stroke="black" cx="86.15" cy="-90" rx="86.15" ry="18"/>
<text text-anchor="middle" x="86.15" y="-84.95" font-family="Times,serif" font-size="14.00">K1 (distantNephew)</text>
</g>
<!-- K2&#45;&gt;K1 -->
<g id="edge3" class="edge">
<title>K2&#45;&gt;K1</title>
<path fill="none" stroke="black" d="M157.28,-145.12C145.39,-136.07 130.27,-124.57 117.03,-114.49"/>
<polygon fill="black" stroke="black" points="119.51,-111.98 109.44,-108.71 115.27,-117.55 119.51,-111.98"/>
</g>
<!-- K4 -->
<g id="node5" class="node">
<title>K4</title>
<ellipse fill="none" stroke="black" cx="271.15" cy="-90" rx="80.52" ry="18"/>
<text text-anchor="middle" x="271.15" y="-84.95" font-family="Times,serif" font-size="14.00">K4 (closeNephew)</text>
</g>
<!-- K2&#45;&gt;K4 -->
<g id="edge4" class="edge">
<title>K2&#45;&gt;K4</title>
<path fill="none" stroke="black" d="M199.26,-145.12C211.36,-136 226.78,-124.4 240.23,-114.28"/>
<polygon fill="black" stroke="black" points="242.07,-117.27 247.96,-108.46 237.86,-111.68 242.07,-117.27"/>
</g>
<!-- BH2 -->
<g id="node6" class="node">
<title>BH2</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="131.28,-36 41.03,-36 41.03,0 131.28,0 131.28,-36"/>
<text text-anchor="middle" x="86.15" y="-11.82" font-family="Italic" font-size="14.00">black height i</text>
</g>
<!-- K1&#45;&gt;BH2 -->
<g id="edge5" class="edge">
<title>K1&#45;&gt;BH2</title>
<path fill="none" stroke="black" d="M80.24,-71.7C79.49,-64.41 79.24,-55.73 79.51,-47.54"/>
<polygon fill="black" stroke="black" points="83,-47.82 80.16,-37.61 76.01,-47.36 83,-47.82"/>
</g>
<!-- K1&#45;&gt;BH2 -->
<g id="edge6" class="edge">
<title>K1&#45;&gt;BH2</title>
<path fill="none" stroke="black" d="M92.07,-71.7C92.82,-64.41 93.07,-55.73 92.8,-47.54"/>
<polygon fill="black" stroke="black" points="96.3,-47.36 92.15,-37.61 89.31,-47.82 96.3,-47.36"/>
</g>
<!-- BH3 -->
<g id="node7" class="node">
<title>BH3</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="316.28,-36 226.03,-36 226.03,0 316.28,0 316.28,-36"/>
<text text-anchor="middle" x="271.15" y="-11.82" font-family="Italic" font-size="14.00">black height i</text>
</g>
<!-- K4&#45;&gt;BH3 -->
<g id="edge7" class="edge">
<title>K4&#45;&gt;BH3</title>
<path fill="none" stroke="black" d="M265.24,-71.7C264.49,-64.41 264.24,-55.73 264.51,-47.54"/>
<polygon fill="black" stroke="black" points="268,-47.82 265.16,-37.61 261.01,-47.36 268,-47.82"/>
</g>
<!-- K4&#45;&gt;BH3 -->
<g id="edge8" class="edge">
<title>K4&#45;&gt;BH3</title>
<path fill="none" stroke="black" d="M277.07,-71.7C277.82,-64.41 278.07,-55.73 277.8,-47.54"/>
<polygon fill="black" stroke="black" points="281.3,-47.36 277.15,-37.61 274.31,-47.82 281.3,-47.36"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@ -0,0 +1,23 @@
digraph {
K6 -> K2
K6 -> BH1
K2 -> K1
K2 -> K4
K1 -> BH2
K1 -> BH2
K4 -> BH3
K4 -> BH3
K1 [label="K1 (distantNephew)"]
K2 [label="K2 (sibling)",color="red",fontcolor="red"]
K4 [label="K4 (closeNephew)"]
K6 [label="K6 (node)"]
BH1 [shape="box",label="black height i + 1",style="dotted",fontname="Italic"]
BH2 [shape="box",label="black height i",style="dotted",fontname="Italic"]
BH3 [shape="box",label="black height i",style="dotted",fontname="Italic"]
}

View File

@ -0,0 +1,102 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 12.2.1 (20241206.2353)
-->
<!-- Pages: 1 -->
<svg width="374pt" height="260pt"
viewBox="0.00 0.00 374.28 260.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 256)">
<polygon fill="white" stroke="none" points="-4,4 -4,-256 370.28,-256 370.28,4 -4,4"/>
<!-- K6 -->
<g id="node1" class="node">
<title>K6</title>
<ellipse fill="none" stroke="black" cx="243.15" cy="-234" rx="48.79" ry="18"/>
<text text-anchor="middle" x="243.15" y="-228.95" font-family="Times,serif" font-size="14.00">K6 (node)</text>
</g>
<!-- K2 -->
<g id="node2" class="node">
<title>K2</title>
<ellipse fill="none" stroke="red" cx="178.15" cy="-162" rx="55.96" ry="18"/>
<text text-anchor="middle" x="178.15" y="-156.95" font-family="Times,serif" font-size="14.00" fill="red">K2 (sibling)</text>
</g>
<!-- K6&#45;&gt;K2 -->
<g id="edge1" class="edge">
<title>K6&#45;&gt;K2</title>
<path fill="none" stroke="black" d="M228.08,-216.76C220.15,-208.23 210.27,-197.58 201.39,-188.02"/>
<polygon fill="black" stroke="black" points="204,-185.69 194.63,-180.74 198.87,-190.45 204,-185.69"/>
</g>
<!-- BH1 -->
<g id="node3" class="node">
<title>BH1</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="366.28,-180 252.03,-180 252.03,-144 366.28,-144 366.28,-180"/>
<text text-anchor="middle" x="309.15" y="-155.82" font-family="Italic" font-size="14.00">black height i + 1</text>
</g>
<!-- K6&#45;&gt;BH1 -->
<g id="edge2" class="edge">
<title>K6&#45;&gt;BH1</title>
<path fill="none" stroke="black" d="M258.46,-216.76C266.39,-208.35 276.26,-197.89 285.17,-188.44"/>
<polygon fill="black" stroke="black" points="287.66,-190.9 291.97,-181.23 282.56,-186.1 287.66,-190.9"/>
</g>
<!-- K1 -->
<g id="node4" class="node">
<title>K1</title>
<ellipse fill="none" stroke="black" cx="86.15" cy="-90" rx="86.15" ry="18"/>
<text text-anchor="middle" x="86.15" y="-84.95" font-family="Times,serif" font-size="14.00">K1 (distantNephew)</text>
</g>
<!-- K2&#45;&gt;K1 -->
<g id="edge3" class="edge">
<title>K2&#45;&gt;K1</title>
<path fill="none" stroke="black" d="M157.28,-145.12C145.39,-136.07 130.27,-124.57 117.03,-114.49"/>
<polygon fill="black" stroke="black" points="119.51,-111.98 109.44,-108.71 115.27,-117.55 119.51,-111.98"/>
</g>
<!-- K4 -->
<g id="node5" class="node">
<title>K4</title>
<ellipse fill="none" stroke="black" cx="271.15" cy="-90" rx="80.52" ry="18"/>
<text text-anchor="middle" x="271.15" y="-84.95" font-family="Times,serif" font-size="14.00">K4 (closeNephew)</text>
</g>
<!-- K2&#45;&gt;K4 -->
<g id="edge4" class="edge">
<title>K2&#45;&gt;K4</title>
<path fill="none" stroke="black" d="M199.26,-145.12C211.36,-136 226.78,-124.4 240.23,-114.28"/>
<polygon fill="black" stroke="black" points="242.07,-117.27 247.96,-108.46 237.86,-111.68 242.07,-117.27"/>
</g>
<!-- BH2 -->
<g id="node6" class="node">
<title>BH2</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="131.28,-36 41.03,-36 41.03,0 131.28,0 131.28,-36"/>
<text text-anchor="middle" x="86.15" y="-11.82" font-family="Italic" font-size="14.00">black height i</text>
</g>
<!-- K1&#45;&gt;BH2 -->
<g id="edge5" class="edge">
<title>K1&#45;&gt;BH2</title>
<path fill="none" stroke="black" d="M80.24,-71.7C79.49,-64.41 79.24,-55.73 79.51,-47.54"/>
<polygon fill="black" stroke="black" points="83,-47.82 80.16,-37.61 76.01,-47.36 83,-47.82"/>
</g>
<!-- K1&#45;&gt;BH2 -->
<g id="edge6" class="edge">
<title>K1&#45;&gt;BH2</title>
<path fill="none" stroke="black" d="M92.07,-71.7C92.82,-64.41 93.07,-55.73 92.8,-47.54"/>
<polygon fill="black" stroke="black" points="96.3,-47.36 92.15,-37.61 89.31,-47.82 96.3,-47.36"/>
</g>
<!-- BH3 -->
<g id="node7" class="node">
<title>BH3</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="316.28,-36 226.03,-36 226.03,0 316.28,0 316.28,-36"/>
<text text-anchor="middle" x="271.15" y="-11.82" font-family="Italic" font-size="14.00">black height i</text>
</g>
<!-- K4&#45;&gt;BH3 -->
<g id="edge7" class="edge">
<title>K4&#45;&gt;BH3</title>
<path fill="none" stroke="black" d="M265.24,-71.7C264.49,-64.41 264.24,-55.73 264.51,-47.54"/>
<polygon fill="black" stroke="black" points="268,-47.82 265.16,-37.61 261.01,-47.36 268,-47.82"/>
</g>
<!-- K4&#45;&gt;BH3 -->
<g id="edge8" class="edge">
<title>K4&#45;&gt;BH3</title>
<path fill="none" stroke="black" d="M277.07,-71.7C277.82,-64.41 278.07,-55.73 277.8,-47.54"/>
<polygon fill="black" stroke="black" points="281.3,-47.36 277.15,-37.61 274.31,-47.82 281.3,-47.36"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@ -0,0 +1,28 @@
digraph {
P -> BH1
P -> K6
K6 -> K2
K6 -> BH2
K2 -> K1
K2 -> K4
K1 -> BH3
K1 -> BH3
K4 -> BH4
K4 -> BH4
P [label="parent",color="gray",fontcolor="gray"]
K1 [label="K1 (distantNephew)"]
K2 [label="K2 (sibling)",color="red",fontcolor="red"]
K4 [label="K4 (closeNephew)"]
K6 [label="K6 (node)"]
BH1 [shape="box",label="black height i + 3",style="dotted",fontname="Italic"]
BH2 [shape="box",label="black height i + 1",style="dotted",fontname="Italic"]
BH3 [shape="box",label="black height i",style="dotted",fontname="Italic"]
BH4 [shape="box",label="black height i",style="dotted",fontname="Italic"]
}

View File

@ -0,0 +1,126 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 12.2.1 (20241206.2353)
-->
<!-- Pages: 1 -->
<svg width="374pt" height="332pt"
viewBox="0.00 0.00 374.28 332.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 328)">
<polygon fill="white" stroke="none" points="-4,4 -4,-328 370.28,-328 370.28,4 -4,4"/>
<!-- P -->
<g id="node1" class="node">
<title>P</title>
<ellipse fill="none" stroke="gray" cx="182.15" cy="-306" rx="33.95" ry="18"/>
<text text-anchor="middle" x="182.15" y="-300.95" font-family="Times,serif" font-size="14.00" fill="gray">parent</text>
</g>
<!-- BH1 -->
<g id="node2" class="node">
<title>BH1</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="177.28,-252 63.03,-252 63.03,-216 177.28,-216 177.28,-252"/>
<text text-anchor="middle" x="120.15" y="-227.82" font-family="Italic" font-size="14.00">black height i + 3</text>
</g>
<!-- P&#45;&gt;BH1 -->
<g id="edge1" class="edge">
<title>P&#45;&gt;BH1</title>
<path fill="none" stroke="black" d="M168.09,-289.12C160.65,-280.72 151.33,-270.2 142.89,-260.67"/>
<polygon fill="black" stroke="black" points="145.72,-258.59 136.47,-253.43 140.48,-263.23 145.72,-258.59"/>
</g>
<!-- K6 -->
<g id="node3" class="node">
<title>K6</title>
<ellipse fill="none" stroke="black" cx="244.15" cy="-234" rx="48.79" ry="18"/>
<text text-anchor="middle" x="244.15" y="-228.95" font-family="Times,serif" font-size="14.00">K6 (node)</text>
</g>
<!-- P&#45;&gt;K6 -->
<g id="edge2" class="edge">
<title>P&#45;&gt;K6</title>
<path fill="none" stroke="black" d="M196.22,-289.12C203.88,-280.47 213.53,-269.58 222.16,-259.83"/>
<polygon fill="black" stroke="black" points="224.7,-262.25 228.71,-252.44 219.46,-257.61 224.7,-262.25"/>
</g>
<!-- K2 -->
<g id="node4" class="node">
<title>K2</title>
<ellipse fill="none" stroke="red" cx="178.15" cy="-162" rx="55.96" ry="18"/>
<text text-anchor="middle" x="178.15" y="-156.95" font-family="Times,serif" font-size="14.00" fill="red">K2 (sibling)</text>
</g>
<!-- K6&#45;&gt;K2 -->
<g id="edge3" class="edge">
<title>K6&#45;&gt;K2</title>
<path fill="none" stroke="black" d="M228.85,-216.76C220.72,-208.14 210.56,-197.36 201.47,-187.73"/>
<polygon fill="black" stroke="black" points="204.28,-185.61 194.88,-180.73 199.19,-190.41 204.28,-185.61"/>
</g>
<!-- BH2 -->
<g id="node5" class="node">
<title>BH2</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="366.28,-180 252.03,-180 252.03,-144 366.28,-144 366.28,-180"/>
<text text-anchor="middle" x="309.15" y="-155.82" font-family="Italic" font-size="14.00">black height i + 1</text>
</g>
<!-- K6&#45;&gt;BH2 -->
<g id="edge4" class="edge">
<title>K6&#45;&gt;BH2</title>
<path fill="none" stroke="black" d="M259.23,-216.76C267.04,-208.35 276.76,-197.89 285.54,-188.44"/>
<polygon fill="black" stroke="black" points="287.98,-190.94 292.22,-181.23 282.85,-186.18 287.98,-190.94"/>
</g>
<!-- K1 -->
<g id="node6" class="node">
<title>K1</title>
<ellipse fill="none" stroke="black" cx="86.15" cy="-90" rx="86.15" ry="18"/>
<text text-anchor="middle" x="86.15" y="-84.95" font-family="Times,serif" font-size="14.00">K1 (distantNephew)</text>
</g>
<!-- K2&#45;&gt;K1 -->
<g id="edge5" class="edge">
<title>K2&#45;&gt;K1</title>
<path fill="none" stroke="black" d="M157.28,-145.12C145.39,-136.07 130.27,-124.57 117.03,-114.49"/>
<polygon fill="black" stroke="black" points="119.51,-111.98 109.44,-108.71 115.27,-117.55 119.51,-111.98"/>
</g>
<!-- K4 -->
<g id="node7" class="node">
<title>K4</title>
<ellipse fill="none" stroke="black" cx="271.15" cy="-90" rx="80.52" ry="18"/>
<text text-anchor="middle" x="271.15" y="-84.95" font-family="Times,serif" font-size="14.00">K4 (closeNephew)</text>
</g>
<!-- K2&#45;&gt;K4 -->
<g id="edge6" class="edge">
<title>K2&#45;&gt;K4</title>
<path fill="none" stroke="black" d="M199.26,-145.12C211.36,-136 226.78,-124.4 240.23,-114.28"/>
<polygon fill="black" stroke="black" points="242.07,-117.27 247.96,-108.46 237.86,-111.68 242.07,-117.27"/>
</g>
<!-- BH3 -->
<g id="node8" class="node">
<title>BH3</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="131.28,-36 41.03,-36 41.03,0 131.28,0 131.28,-36"/>
<text text-anchor="middle" x="86.15" y="-11.82" font-family="Italic" font-size="14.00">black height i</text>
</g>
<!-- K1&#45;&gt;BH3 -->
<g id="edge7" class="edge">
<title>K1&#45;&gt;BH3</title>
<path fill="none" stroke="black" d="M80.24,-71.7C79.49,-64.41 79.24,-55.73 79.51,-47.54"/>
<polygon fill="black" stroke="black" points="83,-47.82 80.16,-37.61 76.01,-47.36 83,-47.82"/>
</g>
<!-- K1&#45;&gt;BH3 -->
<g id="edge8" class="edge">
<title>K1&#45;&gt;BH3</title>
<path fill="none" stroke="black" d="M92.07,-71.7C92.82,-64.41 93.07,-55.73 92.8,-47.54"/>
<polygon fill="black" stroke="black" points="96.3,-47.36 92.15,-37.61 89.31,-47.82 96.3,-47.36"/>
</g>
<!-- BH4 -->
<g id="node9" class="node">
<title>BH4</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="316.28,-36 226.03,-36 226.03,0 316.28,0 316.28,-36"/>
<text text-anchor="middle" x="271.15" y="-11.82" font-family="Italic" font-size="14.00">black height i</text>
</g>
<!-- K4&#45;&gt;BH4 -->
<g id="edge9" class="edge">
<title>K4&#45;&gt;BH4</title>
<path fill="none" stroke="black" d="M265.24,-71.7C264.49,-64.41 264.24,-55.73 264.51,-47.54"/>
<polygon fill="black" stroke="black" points="268,-47.82 265.16,-37.61 261.01,-47.36 268,-47.82"/>
</g>
<!-- K4&#45;&gt;BH4 -->
<g id="edge10" class="edge">
<title>K4&#45;&gt;BH4</title>
<path fill="none" stroke="black" d="M277.07,-71.7C277.82,-64.41 278.07,-55.73 277.8,-47.54"/>
<polygon fill="black" stroke="black" points="281.3,-47.36 277.15,-37.61 274.31,-47.82 281.3,-47.36"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.8 KiB

View File

@ -0,0 +1,14 @@
digraph {
P -> BH2
P -> N
N -> L1
N -> L2
P [label="parent",color="darkgray",fontcolor="darkgray"]
BH2 [shape="box",label="black height 2",style="dotted",fontname="Italic"]
N [label="node"]
L1 [fontcolor="invis"]
L2 [fontcolor="invis"]
}

View File

@ -0,0 +1,66 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 12.2.1 (20241206.2353)
-->
<!-- Pages: 1 -->
<svg width="211pt" height="188pt"
viewBox="0.00 0.00 210.62 188.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 184)">
<polygon fill="white" stroke="none" points="-4,4 -4,-184 206.62,-184 206.62,4 -4,4"/>
<!-- P -->
<g id="node1" class="node">
<title>P</title>
<ellipse fill="none" stroke="darkgray" cx="92.62" cy="-162" rx="33.95" ry="18"/>
<text text-anchor="middle" x="92.62" y="-156.95" font-family="Times,serif" font-size="14.00" fill="darkgray">parent</text>
</g>
<!-- BH2 -->
<g id="node2" class="node">
<title>BH2</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="93.25,-108 0,-108 0,-72 93.25,-72 93.25,-108"/>
<text text-anchor="middle" x="46.62" y="-83.83" font-family="Italic" font-size="14.00">black height 2</text>
</g>
<!-- P&#45;&gt;BH2 -->
<g id="edge1" class="edge">
<title>P&#45;&gt;BH2</title>
<path fill="none" stroke="black" d="M81.96,-144.76C76.65,-136.7 70.11,-126.74 64.1,-117.6"/>
<polygon fill="black" stroke="black" points="67.13,-115.82 58.71,-109.39 61.28,-119.67 67.13,-115.82"/>
</g>
<!-- N -->
<g id="node3" class="node">
<title>N</title>
<ellipse fill="none" stroke="black" cx="139.62" cy="-90" rx="28.83" ry="18"/>
<text text-anchor="middle" x="139.62" y="-84.95" font-family="Times,serif" font-size="14.00">node</text>
</g>
<!-- P&#45;&gt;N -->
<g id="edge2" class="edge">
<title>P&#45;&gt;N</title>
<path fill="none" stroke="black" d="M103.53,-144.76C109.16,-136.37 116.17,-125.93 122.51,-116.5"/>
<polygon fill="black" stroke="black" points="125.27,-118.66 127.94,-108.4 119.46,-114.76 125.27,-118.66"/>
</g>
<!-- L1 -->
<g id="node4" class="node">
<title>L1</title>
<ellipse fill="none" stroke="black" cx="103.62" cy="-18" rx="27" ry="18"/>
<text text-anchor="middle" x="103.62" y="-12.95" font-family="Times,serif" font-size="14.00" fill="#fffffe" fill-opacity="0.000000">L1</text>
</g>
<!-- N&#45;&gt;L1 -->
<g id="edge3" class="edge">
<title>N&#45;&gt;L1</title>
<path fill="none" stroke="black" d="M131.09,-72.41C126.97,-64.39 121.92,-54.57 117.28,-45.54"/>
<polygon fill="black" stroke="black" points="120.47,-44.11 112.79,-36.82 114.25,-47.31 120.47,-44.11"/>
</g>
<!-- L2 -->
<g id="node5" class="node">
<title>L2</title>
<ellipse fill="none" stroke="black" cx="175.62" cy="-18" rx="27" ry="18"/>
<text text-anchor="middle" x="175.62" y="-12.95" font-family="Times,serif" font-size="14.00" fill="#fffffe" fill-opacity="0.000000">L2</text>
</g>
<!-- N&#45;&gt;L2 -->
<g id="edge4" class="edge">
<title>N&#45;&gt;L2</title>
<path fill="none" stroke="black" d="M148.16,-72.41C152.28,-64.39 157.33,-54.57 161.97,-45.54"/>
<polygon fill="black" stroke="black" points="165,-47.31 166.46,-36.82 158.78,-44.11 165,-47.31"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@ -0,0 +1,10 @@
digraph {
P -> BH2
P -> L
P [label="parent",color="darkgray",fontcolor="darkgray"]
BH2 [shape="box",label="black height 2",style="dotted",fontname="Italic"]
L [fontcolor="invis"]
}

View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 12.2.1 (20241206.2353)
-->
<!-- Pages: 1 -->
<svg width="174pt" height="116pt"
viewBox="0.00 0.00 173.62 116.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 112)">
<polygon fill="white" stroke="none" points="-4,4 -4,-112 169.62,-112 169.62,4 -4,4"/>
<!-- P -->
<g id="node1" class="node">
<title>P</title>
<ellipse fill="none" stroke="darkgray" cx="92.62" cy="-90" rx="33.95" ry="18"/>
<text text-anchor="middle" x="92.62" y="-84.95" font-family="Times,serif" font-size="14.00" fill="darkgray">parent</text>
</g>
<!-- BH2 -->
<g id="node2" class="node">
<title>BH2</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="93.25,-36 0,-36 0,0 93.25,0 93.25,-36"/>
<text text-anchor="middle" x="46.62" y="-11.82" font-family="Italic" font-size="14.00">black height 2</text>
</g>
<!-- P&#45;&gt;BH2 -->
<g id="edge1" class="edge">
<title>P&#45;&gt;BH2</title>
<path fill="none" stroke="black" d="M81.96,-72.76C76.65,-64.7 70.11,-54.74 64.1,-45.6"/>
<polygon fill="black" stroke="black" points="67.13,-43.82 58.71,-37.39 61.28,-47.67 67.13,-43.82"/>
</g>
<!-- L -->
<g id="node3" class="node">
<title>L</title>
<ellipse fill="none" stroke="black" cx="138.62" cy="-18" rx="27" ry="18"/>
<text text-anchor="middle" x="138.62" y="-12.95" font-family="Times,serif" font-size="14.00" fill="#fffffe" fill-opacity="0.000000">L</text>
</g>
<!-- P&#45;&gt;L -->
<g id="edge2" class="edge">
<title>P&#45;&gt;L</title>
<path fill="none" stroke="black" d="M103.29,-72.76C108.89,-64.25 115.86,-53.64 122.14,-44.09"/>
<polygon fill="black" stroke="black" points="124.93,-46.21 127.5,-35.93 119.08,-42.37 124.93,-46.21"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,23 @@
digraph {
K6 -> K2
K6 -> BH1
K2 -> K1
K2 -> K4
K1 -> BH2
K1 -> BH2
K4 -> BH3
K4 -> BH3
K1 [label="K1 (distantNephew)",color="darkgray",fontcolor="darkgray"]
K2 [label="K2 (sibling)",color="darkgray",fontcolor="darkgray"]
K4 [label="K4 (closeNephew)",color="darkgray",fontcolor="darkgray"]
K6 [label="K6 (parent)",color="darkgray",fontcolor="darkgray"]
BH1 [shape="box",label="black height i + 1",style="dotted",fontname="Italic"]
BH2 [shape="box",label="black height i + 2 - \nnumber of black nodes\nin { K1, K2 }",style="dotted",fontname="Italic"]
BH3 [shape="box",label="black height i + 2 - \nnumber of black nodes\nin { K2, K4 }",style="dotted",fontname="Italic"]
}

View File

@ -0,0 +1,106 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 12.2.1 (20241206.2353)
-->
<!-- Pages: 1 -->
<svg width="374pt" height="275pt"
viewBox="0.00 0.00 374.28 274.75" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 270.75)">
<polygon fill="white" stroke="none" points="-4,4 -4,-270.75 370.28,-270.75 370.28,4 -4,4"/>
<!-- K6 -->
<g id="node1" class="node">
<title>K6</title>
<ellipse fill="none" stroke="darkgray" cx="243.15" cy="-248.75" rx="53.91" ry="18"/>
<text text-anchor="middle" x="243.15" y="-243.7" font-family="Times,serif" font-size="14.00" fill="darkgray">K6 (parent)</text>
</g>
<!-- K2 -->
<g id="node2" class="node">
<title>K2</title>
<ellipse fill="none" stroke="darkgray" cx="178.15" cy="-176.75" rx="55.96" ry="18"/>
<text text-anchor="middle" x="178.15" y="-171.7" font-family="Times,serif" font-size="14.00" fill="darkgray">K2 (sibling)</text>
</g>
<!-- K6&#45;&gt;K2 -->
<g id="edge1" class="edge">
<title>K6&#45;&gt;K2</title>
<path fill="none" stroke="black" d="M227.75,-231.16C219.82,-222.62 209.98,-212.03 201.17,-202.54"/>
<polygon fill="black" stroke="black" points="203.85,-200.28 194.48,-195.33 198.72,-205.04 203.85,-200.28"/>
</g>
<!-- BH1 -->
<g id="node3" class="node">
<title>BH1</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="366.28,-194.75 252.03,-194.75 252.03,-158.75 366.28,-158.75 366.28,-194.75"/>
<text text-anchor="middle" x="309.15" y="-170.57" font-family="Italic" font-size="14.00">black height i + 1</text>
</g>
<!-- K6&#45;&gt;BH1 -->
<g id="edge2" class="edge">
<title>K6&#45;&gt;BH1</title>
<path fill="none" stroke="black" d="M258.8,-231.16C266.62,-222.87 276.26,-212.64 285,-203.37"/>
<polygon fill="black" stroke="black" points="287.35,-205.97 291.67,-196.3 282.26,-201.17 287.35,-205.97"/>
</g>
<!-- K1 -->
<g id="node4" class="node">
<title>K1</title>
<ellipse fill="none" stroke="darkgray" cx="86.15" cy="-104.75" rx="86.15" ry="18"/>
<text text-anchor="middle" x="86.15" y="-99.7" font-family="Times,serif" font-size="14.00" fill="darkgray">K1 (distantNephew)</text>
</g>
<!-- K2&#45;&gt;K1 -->
<g id="edge3" class="edge">
<title>K2&#45;&gt;K1</title>
<path fill="none" stroke="black" d="M157.28,-159.87C145.39,-150.82 130.27,-139.32 117.03,-129.24"/>
<polygon fill="black" stroke="black" points="119.51,-126.73 109.44,-123.46 115.27,-132.3 119.51,-126.73"/>
</g>
<!-- K4 -->
<g id="node5" class="node">
<title>K4</title>
<ellipse fill="none" stroke="darkgray" cx="271.15" cy="-104.75" rx="80.52" ry="18"/>
<text text-anchor="middle" x="271.15" y="-99.7" font-family="Times,serif" font-size="14.00" fill="darkgray">K4 (closeNephew)</text>
</g>
<!-- K2&#45;&gt;K4 -->
<g id="edge4" class="edge">
<title>K2&#45;&gt;K4</title>
<path fill="none" stroke="black" d="M199.26,-159.87C211.36,-150.75 226.78,-139.15 240.23,-129.03"/>
<polygon fill="black" stroke="black" points="242.07,-132.02 247.96,-123.21 237.86,-126.43 242.07,-132.02"/>
</g>
<!-- BH2 -->
<g id="node6" class="node">
<title>BH2</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="156.03,-50.75 16.28,-50.75 16.28,0 156.03,0 156.03,-50.75"/>
<text text-anchor="middle" x="86.15" y="-33.45" font-family="Italic" font-size="14.00">black height i + 2 &#45; </text>
<text text-anchor="middle" x="86.15" y="-19.2" font-family="Italic" font-size="14.00">number of black nodes</text>
<text text-anchor="middle" x="86.15" y="-4.95" font-family="Italic" font-size="14.00">in { K1, K2 }</text>
</g>
<!-- K1&#45;&gt;BH2 -->
<g id="edge5" class="edge">
<title>K1&#45;&gt;BH2</title>
<path fill="none" stroke="black" d="M80.43,-86.58C79.67,-79.42 79.33,-70.81 79.42,-62.38"/>
<polygon fill="black" stroke="black" points="82.91,-62.76 79.76,-52.65 75.91,-62.52 82.91,-62.76"/>
</g>
<!-- K1&#45;&gt;BH2 -->
<g id="edge6" class="edge">
<title>K1&#45;&gt;BH2</title>
<path fill="none" stroke="black" d="M91.87,-86.58C92.64,-79.42 92.98,-70.81 92.89,-62.38"/>
<polygon fill="black" stroke="black" points="96.4,-62.52 92.55,-52.65 89.4,-62.76 96.4,-62.52"/>
</g>
<!-- BH3 -->
<g id="node7" class="node">
<title>BH3</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="341.03,-50.75 201.28,-50.75 201.28,0 341.03,0 341.03,-50.75"/>
<text text-anchor="middle" x="271.15" y="-33.45" font-family="Italic" font-size="14.00">black height i + 2 &#45; </text>
<text text-anchor="middle" x="271.15" y="-19.2" font-family="Italic" font-size="14.00">number of black nodes</text>
<text text-anchor="middle" x="271.15" y="-4.95" font-family="Italic" font-size="14.00">in { K2, K4 }</text>
</g>
<!-- K4&#45;&gt;BH3 -->
<g id="edge7" class="edge">
<title>K4&#45;&gt;BH3</title>
<path fill="none" stroke="black" d="M265.43,-86.58C264.67,-79.42 264.33,-70.81 264.42,-62.38"/>
<polygon fill="black" stroke="black" points="267.91,-62.76 264.76,-52.65 260.91,-62.52 267.91,-62.76"/>
</g>
<!-- K4&#45;&gt;BH3 -->
<g id="edge8" class="edge">
<title>K4&#45;&gt;BH3</title>
<path fill="none" stroke="black" d="M276.87,-86.58C277.64,-79.42 277.98,-70.81 277.89,-62.38"/>
<polygon fill="black" stroke="black" points="281.4,-62.52 277.55,-52.65 274.4,-62.76 281.4,-62.52"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

@ -0,0 +1,10 @@
digraph {
P -> BHnPlus2
P -> BHnPlus1
P [label="parent",color="gray",fontcolor="gray"]
BHnPlus1 [shape="box",label="black height i + 1",style="dotted",fontname="Italic"]
BHnPlus2 [shape="box",label="black height i + 2",style="dotted",fontname="Italic"]
}

View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 12.2.1 (20241206.2353)
-->
<!-- Pages: 1 -->
<svg width="254pt" height="116pt"
viewBox="0.00 0.00 254.25 116.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 112)">
<polygon fill="white" stroke="none" points="-4,4 -4,-112 250.25,-112 250.25,4 -4,4"/>
<!-- P -->
<g id="node1" class="node">
<title>P</title>
<ellipse fill="none" stroke="gray" cx="123.12" cy="-90" rx="33.95" ry="18"/>
<text text-anchor="middle" x="123.12" y="-84.95" font-family="Times,serif" font-size="14.00" fill="gray">parent</text>
</g>
<!-- BHnPlus2 -->
<g id="node2" class="node">
<title>BHnPlus2</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="114.25,-36 0,-36 0,0 114.25,0 114.25,-36"/>
<text text-anchor="middle" x="57.12" y="-11.82" font-family="Italic" font-size="14.00">black height i + 2</text>
</g>
<!-- P&#45;&gt;BHnPlus2 -->
<g id="edge1" class="edge">
<title>P&#45;&gt;BHnPlus2</title>
<path fill="none" stroke="black" d="M108.48,-73.46C100.49,-64.99 90.39,-54.29 81.27,-44.61"/>
<polygon fill="black" stroke="black" points="84.03,-42.44 74.63,-37.56 78.94,-47.24 84.03,-42.44"/>
</g>
<!-- BHnPlus1 -->
<g id="node3" class="node">
<title>BHnPlus1</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="246.25,-36 132,-36 132,0 246.25,0 246.25,-36"/>
<text text-anchor="middle" x="189.12" y="-11.82" font-family="Italic" font-size="14.00">black height i + 1</text>
</g>
<!-- P&#45;&gt;BHnPlus1 -->
<g id="edge2" class="edge">
<title>P&#45;&gt;BHnPlus1</title>
<path fill="none" stroke="black" d="M137.77,-73.46C145.76,-64.99 155.86,-54.29 164.98,-44.61"/>
<polygon fill="black" stroke="black" points="167.31,-47.24 171.62,-37.56 162.22,-42.44 167.31,-47.24"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1,19 @@
digraph {
K6 -> K2
K6 -> BH1
K2 -> BH2
K2 -> K4
K4 -> BH3
K4 -> BH3
K2 [label="K2 (sibling)"]
K4 [label="K4 (closeNephew)",color="red",fontcolor="red"]
K6 [label="K6 (parent)",color="gray",fontcolor="gray"]
BH1 [shape="box",label="black height i + 1",style="dotted",fontname="Italic"]
BH2 [shape="box",label="black height i + 1",style="dotted",fontname="Italic"]
BH3 [shape="box",label="black height i + 1",style="dotted",fontname="Italic"]
}

View File

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 12.2.1 (20241206.2353)
-->
<!-- Pages: 1 -->
<svg width="331pt" height="260pt"
viewBox="0.00 0.00 331.25 260.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 256)">
<polygon fill="white" stroke="none" points="-4,4 -4,-256 327.25,-256 327.25,4 -4,4"/>
<!-- K6 -->
<g id="node1" class="node">
<title>K6</title>
<ellipse fill="none" stroke="gray" cx="200.12" cy="-234" rx="53.91" ry="18"/>
<text text-anchor="middle" x="200.12" y="-228.95" font-family="Times,serif" font-size="14.00" fill="gray">K6 (parent)</text>
</g>
<!-- K2 -->
<g id="node2" class="node">
<title>K2</title>
<ellipse fill="none" stroke="black" cx="135.12" cy="-162" rx="55.96" ry="18"/>
<text text-anchor="middle" x="135.12" y="-156.95" font-family="Times,serif" font-size="14.00">K2 (sibling)</text>
</g>
<!-- K6&#45;&gt;K2 -->
<g id="edge1" class="edge">
<title>K6&#45;&gt;K2</title>
<path fill="none" stroke="black" d="M184.72,-216.41C176.79,-207.87 166.96,-197.28 158.14,-187.79"/>
<polygon fill="black" stroke="black" points="160.82,-185.53 151.45,-180.58 155.69,-190.29 160.82,-185.53"/>
</g>
<!-- BH1 -->
<g id="node3" class="node">
<title>BH1</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="323.25,-180 209,-180 209,-144 323.25,-144 323.25,-180"/>
<text text-anchor="middle" x="266.12" y="-155.82" font-family="Italic" font-size="14.00">black height i + 1</text>
</g>
<!-- K6&#45;&gt;BH1 -->
<g id="edge2" class="edge">
<title>K6&#45;&gt;BH1</title>
<path fill="none" stroke="black" d="M215.77,-216.41C223.59,-208.12 233.23,-197.89 241.97,-188.62"/>
<polygon fill="black" stroke="black" points="244.32,-191.22 248.64,-181.55 239.23,-186.42 244.32,-191.22"/>
</g>
<!-- BH2 -->
<g id="node4" class="node">
<title>BH2</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="114.25,-108 0,-108 0,-72 114.25,-72 114.25,-108"/>
<text text-anchor="middle" x="57.13" y="-83.83" font-family="Italic" font-size="14.00">black height i + 1</text>
</g>
<!-- K2&#45;&gt;BH2 -->
<g id="edge3" class="edge">
<title>K2&#45;&gt;BH2</title>
<path fill="none" stroke="black" d="M117.03,-144.76C107.45,-136.16 95.46,-125.41 84.74,-115.78"/>
<polygon fill="black" stroke="black" points="87.39,-113.46 77.61,-109.38 82.71,-118.67 87.39,-113.46"/>
</g>
<!-- K4 -->
<g id="node5" class="node">
<title>K4</title>
<ellipse fill="none" stroke="red" cx="213.12" cy="-90" rx="80.52" ry="18"/>
<text text-anchor="middle" x="213.12" y="-84.95" font-family="Times,serif" font-size="14.00" fill="red">K4 (closeNephew)</text>
</g>
<!-- K2&#45;&gt;K4 -->
<g id="edge4" class="edge">
<title>K2&#45;&gt;K4</title>
<path fill="none" stroke="black" d="M153.22,-144.76C162.95,-136.03 175.14,-125.09 185.98,-115.36"/>
<polygon fill="black" stroke="black" points="188.09,-118.17 193.19,-108.89 183.41,-112.96 188.09,-118.17"/>
</g>
<!-- BH3 -->
<g id="node6" class="node">
<title>BH3</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="270.25,-36 156,-36 156,0 270.25,0 270.25,-36"/>
<text text-anchor="middle" x="213.12" y="-11.82" font-family="Italic" font-size="14.00">black height i + 1</text>
</g>
<!-- K4&#45;&gt;BH3 -->
<g id="edge5" class="edge">
<title>K4&#45;&gt;BH3</title>
<path fill="none" stroke="black" d="M207.21,-71.7C206.46,-64.41 206.21,-55.73 206.48,-47.54"/>
<polygon fill="black" stroke="black" points="209.97,-47.82 207.13,-37.61 202.98,-47.36 209.97,-47.82"/>
</g>
<!-- K4&#45;&gt;BH3 -->
<g id="edge6" class="edge">
<title>K4&#45;&gt;BH3</title>
<path fill="none" stroke="black" d="M219.04,-71.7C219.79,-64.41 220.04,-55.73 219.77,-47.54"/>
<polygon fill="black" stroke="black" points="223.27,-47.36 219.12,-37.61 216.28,-47.82 223.27,-47.36"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -0,0 +1,20 @@
digraph {
K6 -> K4
K6 -> BH1
K4 -> K2
K4 -> BH2
K2 -> BH3
K2 -> BH3
K2 [label="K2 (distantNephew)",color="red",fontcolor="red"]
K4 [label="K4 (sibling)"]
K6 [label="K6 (parent)",color="gray",fontcolor="gray"]
BH1 [shape="box",label="black height i + 1",style="dotted",fontname="Italic"]
BH2 [shape="box",label="black height i + 1",style="dotted",fontname="Italic"]
BH3 [shape="box",label="black height i + 1",style="dotted",fontname="Italic"]
}

View File

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 12.2.1 (20241206.2353)
-->
<!-- Pages: 1 -->
<svg width="362pt" height="260pt"
viewBox="0.00 0.00 362.28 260.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 256)">
<polygon fill="white" stroke="none" points="-4,4 -4,-256 358.28,-256 358.28,4 -4,4"/>
<!-- K6 -->
<g id="node1" class="node">
<title>K6</title>
<ellipse fill="none" stroke="gray" cx="231.15" cy="-234" rx="53.91" ry="18"/>
<text text-anchor="middle" x="231.15" y="-228.95" font-family="Times,serif" font-size="14.00" fill="gray">K6 (parent)</text>
</g>
<!-- K4 -->
<g id="node2" class="node">
<title>K4</title>
<ellipse fill="none" stroke="black" cx="166.15" cy="-162" rx="55.96" ry="18"/>
<text text-anchor="middle" x="166.15" y="-156.95" font-family="Times,serif" font-size="14.00">K4 (sibling)</text>
</g>
<!-- K6&#45;&gt;K4 -->
<g id="edge1" class="edge">
<title>K6&#45;&gt;K4</title>
<path fill="none" stroke="black" d="M215.75,-216.41C207.82,-207.87 197.98,-197.28 189.17,-187.79"/>
<polygon fill="black" stroke="black" points="191.85,-185.53 182.48,-180.58 186.72,-190.29 191.85,-185.53"/>
</g>
<!-- BH1 -->
<g id="node3" class="node">
<title>BH1</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="354.28,-180 240.03,-180 240.03,-144 354.28,-144 354.28,-180"/>
<text text-anchor="middle" x="297.15" y="-155.82" font-family="Italic" font-size="14.00">black height i + 1</text>
</g>
<!-- K6&#45;&gt;BH1 -->
<g id="edge2" class="edge">
<title>K6&#45;&gt;BH1</title>
<path fill="none" stroke="black" d="M246.8,-216.41C254.62,-208.12 264.26,-197.89 273,-188.62"/>
<polygon fill="black" stroke="black" points="275.35,-191.22 279.67,-181.55 270.26,-186.42 275.35,-191.22"/>
</g>
<!-- K2 -->
<g id="node4" class="node">
<title>K2</title>
<ellipse fill="none" stroke="red" cx="86.15" cy="-90" rx="86.15" ry="18"/>
<text text-anchor="middle" x="86.15" y="-84.95" font-family="Times,serif" font-size="14.00" fill="red">K2 (distantNephew)</text>
</g>
<!-- K4&#45;&gt;K2 -->
<g id="edge3" class="edge">
<title>K4&#45;&gt;K2</title>
<path fill="none" stroke="black" d="M147.6,-144.76C137.62,-136.03 125.11,-125.09 113.99,-115.36"/>
<polygon fill="black" stroke="black" points="116.41,-112.83 106.58,-108.87 111.8,-118.09 116.41,-112.83"/>
</g>
<!-- BH2 -->
<g id="node5" class="node">
<title>BH2</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="304.28,-108 190.03,-108 190.03,-72 304.28,-72 304.28,-108"/>
<text text-anchor="middle" x="247.15" y="-83.83" font-family="Italic" font-size="14.00">black height i + 1</text>
</g>
<!-- K4&#45;&gt;BH2 -->
<g id="edge4" class="edge">
<title>K4&#45;&gt;BH2</title>
<path fill="none" stroke="black" d="M184.94,-144.76C194.9,-136.16 207.34,-125.41 218.48,-115.78"/>
<polygon fill="black" stroke="black" points="220.63,-118.55 225.91,-109.36 216.05,-113.25 220.63,-118.55"/>
</g>
<!-- BH3 -->
<g id="node6" class="node">
<title>BH3</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="143.28,-36 29.03,-36 29.03,0 143.28,0 143.28,-36"/>
<text text-anchor="middle" x="86.15" y="-11.82" font-family="Italic" font-size="14.00">black height i + 1</text>
</g>
<!-- K2&#45;&gt;BH3 -->
<g id="edge5" class="edge">
<title>K2&#45;&gt;BH3</title>
<path fill="none" stroke="black" d="M80.24,-71.7C79.49,-64.41 79.24,-55.73 79.51,-47.54"/>
<polygon fill="black" stroke="black" points="83,-47.82 80.16,-37.61 76.01,-47.36 83,-47.82"/>
</g>
<!-- K2&#45;&gt;BH3 -->
<g id="edge6" class="edge">
<title>K2&#45;&gt;BH3</title>
<path fill="none" stroke="black" d="M92.07,-71.7C92.82,-64.41 93.07,-55.73 92.8,-47.54"/>
<polygon fill="black" stroke="black" points="96.3,-47.36 92.15,-37.61 89.31,-47.82 96.3,-47.36"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -0,0 +1,19 @@
digraph {
K4 -> K2
K4 -> K6
K2 -> BH1
K2 -> BH1
K6 -> BH2
K6 -> BH2
K2 [label="K2 (distantNephew)"]
K4 [label="K4 (sibling)"]
K6 [label="K6 (parent)"]
BH1 [shape="box",label="black height i + 1",style="dotted",fontname="Italic"]
BH2 [shape="box",label="black height i + 1",style="dotted",fontname="Italic"]
}

View File

@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 12.2.1 (20241206.2353)
-->
<!-- Pages: 1 -->
<svg width="309pt" height="188pt"
viewBox="0.00 0.00 309.28 188.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 184)">
<polygon fill="white" stroke="none" points="-4,4 -4,-184 305.28,-184 305.28,4 -4,4"/>
<!-- K4 -->
<g id="node1" class="node">
<title>K4</title>
<ellipse fill="none" stroke="black" cx="165.15" cy="-162" rx="55.96" ry="18"/>
<text text-anchor="middle" x="165.15" y="-156.95" font-family="Times,serif" font-size="14.00">K4 (sibling)</text>
</g>
<!-- K2 -->
<g id="node2" class="node">
<title>K2</title>
<ellipse fill="none" stroke="black" cx="86.15" cy="-90" rx="86.15" ry="18"/>
<text text-anchor="middle" x="86.15" y="-84.95" font-family="Times,serif" font-size="14.00">K2 (distantNephew)</text>
</g>
<!-- K4&#45;&gt;K2 -->
<g id="edge1" class="edge">
<title>K4&#45;&gt;K2</title>
<path fill="none" stroke="black" d="M146.83,-144.76C136.98,-136.03 124.63,-125.09 113.64,-115.36"/>
<polygon fill="black" stroke="black" points="116.14,-112.89 106.34,-108.88 111.5,-118.13 116.14,-112.89"/>
</g>
<!-- K6 -->
<g id="node3" class="node">
<title>K6</title>
<ellipse fill="none" stroke="black" cx="244.15" cy="-90" rx="53.91" ry="18"/>
<text text-anchor="middle" x="244.15" y="-84.95" font-family="Times,serif" font-size="14.00">K6 (parent)</text>
</g>
<!-- K4&#45;&gt;K6 -->
<g id="edge2" class="edge">
<title>K4&#45;&gt;K6</title>
<path fill="none" stroke="black" d="M183.48,-144.76C193.48,-135.91 206.04,-124.77 217.15,-114.93"/>
<polygon fill="black" stroke="black" points="219.36,-117.65 224.52,-108.39 214.72,-112.41 219.36,-117.65"/>
</g>
<!-- BH1 -->
<g id="node4" class="node">
<title>BH1</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="143.28,-36 29.03,-36 29.03,0 143.28,0 143.28,-36"/>
<text text-anchor="middle" x="86.15" y="-11.82" font-family="Italic" font-size="14.00">black height i + 1</text>
</g>
<!-- K2&#45;&gt;BH1 -->
<g id="edge3" class="edge">
<title>K2&#45;&gt;BH1</title>
<path fill="none" stroke="black" d="M80.24,-71.7C79.49,-64.41 79.24,-55.73 79.51,-47.54"/>
<polygon fill="black" stroke="black" points="83,-47.82 80.16,-37.61 76.01,-47.36 83,-47.82"/>
</g>
<!-- K2&#45;&gt;BH1 -->
<g id="edge4" class="edge">
<title>K2&#45;&gt;BH1</title>
<path fill="none" stroke="black" d="M92.07,-71.7C92.82,-64.41 93.07,-55.73 92.8,-47.54"/>
<polygon fill="black" stroke="black" points="96.3,-47.36 92.15,-37.61 89.31,-47.82 96.3,-47.36"/>
</g>
<!-- BH2 -->
<g id="node5" class="node">
<title>BH2</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="301.28,-36 187.03,-36 187.03,0 301.28,0 301.28,-36"/>
<text text-anchor="middle" x="244.15" y="-11.82" font-family="Italic" font-size="14.00">black height i + 1</text>
</g>
<!-- K6&#45;&gt;BH2 -->
<g id="edge5" class="edge">
<title>K6&#45;&gt;BH2</title>
<path fill="none" stroke="black" d="M238.24,-71.7C237.49,-64.41 237.24,-55.73 237.51,-47.54"/>
<polygon fill="black" stroke="black" points="241,-47.82 238.16,-37.61 234.01,-47.36 241,-47.82"/>
</g>
<!-- K6&#45;&gt;BH2 -->
<g id="edge6" class="edge">
<title>K6&#45;&gt;BH2</title>
<path fill="none" stroke="black" d="M250.07,-71.7C250.82,-64.41 251.07,-55.73 250.8,-47.54"/>
<polygon fill="black" stroke="black" points="254.3,-47.36 250.15,-37.61 247.31,-47.82 254.3,-47.36"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -0,0 +1,19 @@
digraph {
K6 -> K2
K6 -> BH1
K2 -> K1
K2 -> BH3
K1 -> BH2
K1 -> BH2
K1 [label="K1 (distantNephew)",color="red",fontcolor="red"]
K2 [label="K2 (sibling)"]
K6 [label="K6 (parent)",color="gray",fontcolor="gray"]
BH1 [shape="box",label="black height i + 1",style="dotted",fontname="Italic"]
BH2 [shape="box",label="black height i + 1",style="dotted",fontname="Italic"]
BH3 [shape="box",label="black height i + 1",style="dotted",fontname="Italic"]
}

View File

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 12.2.1 (20241206.2353)
-->
<!-- Pages: 1 -->
<svg width="362pt" height="260pt"
viewBox="0.00 0.00 362.28 260.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 256)">
<polygon fill="white" stroke="none" points="-4,4 -4,-256 358.28,-256 358.28,4 -4,4"/>
<!-- K6 -->
<g id="node1" class="node">
<title>K6</title>
<ellipse fill="none" stroke="gray" cx="231.15" cy="-234" rx="53.91" ry="18"/>
<text text-anchor="middle" x="231.15" y="-228.95" font-family="Times,serif" font-size="14.00" fill="gray">K6 (parent)</text>
</g>
<!-- K2 -->
<g id="node2" class="node">
<title>K2</title>
<ellipse fill="none" stroke="black" cx="166.15" cy="-162" rx="55.96" ry="18"/>
<text text-anchor="middle" x="166.15" y="-156.95" font-family="Times,serif" font-size="14.00">K2 (sibling)</text>
</g>
<!-- K6&#45;&gt;K2 -->
<g id="edge1" class="edge">
<title>K6&#45;&gt;K2</title>
<path fill="none" stroke="black" d="M215.75,-216.41C207.82,-207.87 197.98,-197.28 189.17,-187.79"/>
<polygon fill="black" stroke="black" points="191.85,-185.53 182.48,-180.58 186.72,-190.29 191.85,-185.53"/>
</g>
<!-- BH1 -->
<g id="node3" class="node">
<title>BH1</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="354.28,-180 240.03,-180 240.03,-144 354.28,-144 354.28,-180"/>
<text text-anchor="middle" x="297.15" y="-155.82" font-family="Italic" font-size="14.00">black height i + 1</text>
</g>
<!-- K6&#45;&gt;BH1 -->
<g id="edge2" class="edge">
<title>K6&#45;&gt;BH1</title>
<path fill="none" stroke="black" d="M246.8,-216.41C254.62,-208.12 264.26,-197.89 273,-188.62"/>
<polygon fill="black" stroke="black" points="275.35,-191.22 279.67,-181.55 270.26,-186.42 275.35,-191.22"/>
</g>
<!-- K1 -->
<g id="node4" class="node">
<title>K1</title>
<ellipse fill="none" stroke="red" cx="86.15" cy="-90" rx="86.15" ry="18"/>
<text text-anchor="middle" x="86.15" y="-84.95" font-family="Times,serif" font-size="14.00" fill="red">K1 (distantNephew)</text>
</g>
<!-- K2&#45;&gt;K1 -->
<g id="edge3" class="edge">
<title>K2&#45;&gt;K1</title>
<path fill="none" stroke="black" d="M147.6,-144.76C137.62,-136.03 125.11,-125.09 113.99,-115.36"/>
<polygon fill="black" stroke="black" points="116.41,-112.83 106.58,-108.87 111.8,-118.09 116.41,-112.83"/>
</g>
<!-- BH3 -->
<g id="node5" class="node">
<title>BH3</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="304.28,-108 190.03,-108 190.03,-72 304.28,-72 304.28,-108"/>
<text text-anchor="middle" x="247.15" y="-83.83" font-family="Italic" font-size="14.00">black height i + 1</text>
</g>
<!-- K2&#45;&gt;BH3 -->
<g id="edge4" class="edge">
<title>K2&#45;&gt;BH3</title>
<path fill="none" stroke="black" d="M184.94,-144.76C194.9,-136.16 207.34,-125.41 218.48,-115.78"/>
<polygon fill="black" stroke="black" points="220.63,-118.55 225.91,-109.36 216.05,-113.25 220.63,-118.55"/>
</g>
<!-- BH2 -->
<g id="node6" class="node">
<title>BH2</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="143.28,-36 29.03,-36 29.03,0 143.28,0 143.28,-36"/>
<text text-anchor="middle" x="86.15" y="-11.82" font-family="Italic" font-size="14.00">black height i + 1</text>
</g>
<!-- K1&#45;&gt;BH2 -->
<g id="edge5" class="edge">
<title>K1&#45;&gt;BH2</title>
<path fill="none" stroke="black" d="M80.24,-71.7C79.49,-64.41 79.24,-55.73 79.51,-47.54"/>
<polygon fill="black" stroke="black" points="83,-47.82 80.16,-37.61 76.01,-47.36 83,-47.82"/>
</g>
<!-- K1&#45;&gt;BH2 -->
<g id="edge6" class="edge">
<title>K1&#45;&gt;BH2</title>
<path fill="none" stroke="black" d="M92.07,-71.7C92.82,-64.41 93.07,-55.73 92.8,-47.54"/>
<polygon fill="black" stroke="black" points="96.3,-47.36 92.15,-37.61 89.31,-47.82 96.3,-47.36"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -0,0 +1,18 @@
digraph {
K2 -> K1
K2 -> K6
K1 -> BH1
K1 -> BH1
K6 -> BH2
K6 -> BH2
K1 [label="K1 (distantNephew)"]
K2 [label="K2 (sibling)"]
K6 [label="K6 (parent)"]
BH1 [shape="box",label="black height i + 1",style="dotted",fontname="Italic"]
BH2 [shape="box",label="black height i + 1",style="dotted",fontname="Italic"]
}

View File

@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 12.2.1 (20241206.2353)
-->
<!-- Pages: 1 -->
<svg width="309pt" height="188pt"
viewBox="0.00 0.00 309.28 188.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 184)">
<polygon fill="white" stroke="none" points="-4,4 -4,-184 305.28,-184 305.28,4 -4,4"/>
<!-- K2 -->
<g id="node1" class="node">
<title>K2</title>
<ellipse fill="none" stroke="black" cx="165.15" cy="-162" rx="55.96" ry="18"/>
<text text-anchor="middle" x="165.15" y="-156.95" font-family="Times,serif" font-size="14.00">K2 (sibling)</text>
</g>
<!-- K1 -->
<g id="node2" class="node">
<title>K1</title>
<ellipse fill="none" stroke="black" cx="86.15" cy="-90" rx="86.15" ry="18"/>
<text text-anchor="middle" x="86.15" y="-84.95" font-family="Times,serif" font-size="14.00">K1 (distantNephew)</text>
</g>
<!-- K2&#45;&gt;K1 -->
<g id="edge1" class="edge">
<title>K2&#45;&gt;K1</title>
<path fill="none" stroke="black" d="M146.83,-144.76C136.98,-136.03 124.63,-125.09 113.64,-115.36"/>
<polygon fill="black" stroke="black" points="116.14,-112.89 106.34,-108.88 111.5,-118.13 116.14,-112.89"/>
</g>
<!-- K6 -->
<g id="node3" class="node">
<title>K6</title>
<ellipse fill="none" stroke="black" cx="244.15" cy="-90" rx="53.91" ry="18"/>
<text text-anchor="middle" x="244.15" y="-84.95" font-family="Times,serif" font-size="14.00">K6 (parent)</text>
</g>
<!-- K2&#45;&gt;K6 -->
<g id="edge2" class="edge">
<title>K2&#45;&gt;K6</title>
<path fill="none" stroke="black" d="M183.48,-144.76C193.48,-135.91 206.04,-124.77 217.15,-114.93"/>
<polygon fill="black" stroke="black" points="219.36,-117.65 224.52,-108.39 214.72,-112.41 219.36,-117.65"/>
</g>
<!-- BH1 -->
<g id="node4" class="node">
<title>BH1</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="143.28,-36 29.03,-36 29.03,0 143.28,0 143.28,-36"/>
<text text-anchor="middle" x="86.15" y="-11.82" font-family="Italic" font-size="14.00">black height i + 1</text>
</g>
<!-- K1&#45;&gt;BH1 -->
<g id="edge3" class="edge">
<title>K1&#45;&gt;BH1</title>
<path fill="none" stroke="black" d="M80.24,-71.7C79.49,-64.41 79.24,-55.73 79.51,-47.54"/>
<polygon fill="black" stroke="black" points="83,-47.82 80.16,-37.61 76.01,-47.36 83,-47.82"/>
</g>
<!-- K1&#45;&gt;BH1 -->
<g id="edge4" class="edge">
<title>K1&#45;&gt;BH1</title>
<path fill="none" stroke="black" d="M92.07,-71.7C92.82,-64.41 93.07,-55.73 92.8,-47.54"/>
<polygon fill="black" stroke="black" points="96.3,-47.36 92.15,-37.61 89.31,-47.82 96.3,-47.36"/>
</g>
<!-- BH2 -->
<g id="node5" class="node">
<title>BH2</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="301.28,-36 187.03,-36 187.03,0 301.28,0 301.28,-36"/>
<text text-anchor="middle" x="244.15" y="-11.82" font-family="Italic" font-size="14.00">black height i + 1</text>
</g>
<!-- K6&#45;&gt;BH2 -->
<g id="edge5" class="edge">
<title>K6&#45;&gt;BH2</title>
<path fill="none" stroke="black" d="M238.24,-71.7C237.49,-64.41 237.24,-55.73 237.51,-47.54"/>
<polygon fill="black" stroke="black" points="241,-47.82 238.16,-37.61 234.01,-47.36 241,-47.82"/>
</g>
<!-- K6&#45;&gt;BH2 -->
<g id="edge6" class="edge">
<title>K6&#45;&gt;BH2</title>
<path fill="none" stroke="black" d="M250.07,-71.7C250.82,-64.41 251.07,-55.73 250.8,-47.54"/>
<polygon fill="black" stroke="black" points="254.3,-47.36 250.15,-37.61 247.31,-47.82 254.3,-47.36"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -0,0 +1,23 @@
digraph {
K6 -> K2
K6 -> BH1
K2 -> K1
K2 -> K4
K1 -> BH2
K1 -> BH2
K4 -> BH3
K4 -> BH3
K1 [label="K1 (distantNephew)"]
K2 [label="K2 (sibling)",color="red",fontcolor="red"]
K4 [label="K4 (closeNephew)"]
K6 [label="K6 (parent)"]
BH1 [shape="box",label="black height i + 1",style="dotted",fontname="Italic"]
BH2 [shape="box",label="black height i",style="dotted",fontname="Italic"]
BH3 [shape="box",label="black height i",style="dotted",fontname="Italic"]
}

View File

@ -0,0 +1,102 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 12.2.1 (20241206.2353)
-->
<!-- Pages: 1 -->
<svg width="374pt" height="260pt"
viewBox="0.00 0.00 374.28 260.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 256)">
<polygon fill="white" stroke="none" points="-4,4 -4,-256 370.28,-256 370.28,4 -4,4"/>
<!-- K6 -->
<g id="node1" class="node">
<title>K6</title>
<ellipse fill="none" stroke="black" cx="243.15" cy="-234" rx="53.91" ry="18"/>
<text text-anchor="middle" x="243.15" y="-228.95" font-family="Times,serif" font-size="14.00">K6 (parent)</text>
</g>
<!-- K2 -->
<g id="node2" class="node">
<title>K2</title>
<ellipse fill="none" stroke="red" cx="178.15" cy="-162" rx="55.96" ry="18"/>
<text text-anchor="middle" x="178.15" y="-156.95" font-family="Times,serif" font-size="14.00" fill="red">K2 (sibling)</text>
</g>
<!-- K6&#45;&gt;K2 -->
<g id="edge1" class="edge">
<title>K6&#45;&gt;K2</title>
<path fill="none" stroke="black" d="M227.75,-216.41C219.82,-207.87 209.98,-197.28 201.17,-187.79"/>
<polygon fill="black" stroke="black" points="203.85,-185.53 194.48,-180.58 198.72,-190.29 203.85,-185.53"/>
</g>
<!-- BH1 -->
<g id="node3" class="node">
<title>BH1</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="366.28,-180 252.03,-180 252.03,-144 366.28,-144 366.28,-180"/>
<text text-anchor="middle" x="309.15" y="-155.82" font-family="Italic" font-size="14.00">black height i + 1</text>
</g>
<!-- K6&#45;&gt;BH1 -->
<g id="edge2" class="edge">
<title>K6&#45;&gt;BH1</title>
<path fill="none" stroke="black" d="M258.8,-216.41C266.62,-208.12 276.26,-197.89 285,-188.62"/>
<polygon fill="black" stroke="black" points="287.35,-191.22 291.67,-181.55 282.26,-186.42 287.35,-191.22"/>
</g>
<!-- K1 -->
<g id="node4" class="node">
<title>K1</title>
<ellipse fill="none" stroke="black" cx="86.15" cy="-90" rx="86.15" ry="18"/>
<text text-anchor="middle" x="86.15" y="-84.95" font-family="Times,serif" font-size="14.00">K1 (distantNephew)</text>
</g>
<!-- K2&#45;&gt;K1 -->
<g id="edge3" class="edge">
<title>K2&#45;&gt;K1</title>
<path fill="none" stroke="black" d="M157.28,-145.12C145.39,-136.07 130.27,-124.57 117.03,-114.49"/>
<polygon fill="black" stroke="black" points="119.51,-111.98 109.44,-108.71 115.27,-117.55 119.51,-111.98"/>
</g>
<!-- K4 -->
<g id="node5" class="node">
<title>K4</title>
<ellipse fill="none" stroke="black" cx="271.15" cy="-90" rx="80.52" ry="18"/>
<text text-anchor="middle" x="271.15" y="-84.95" font-family="Times,serif" font-size="14.00">K4 (closeNephew)</text>
</g>
<!-- K2&#45;&gt;K4 -->
<g id="edge4" class="edge">
<title>K2&#45;&gt;K4</title>
<path fill="none" stroke="black" d="M199.26,-145.12C211.36,-136 226.78,-124.4 240.23,-114.28"/>
<polygon fill="black" stroke="black" points="242.07,-117.27 247.96,-108.46 237.86,-111.68 242.07,-117.27"/>
</g>
<!-- BH2 -->
<g id="node6" class="node">
<title>BH2</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="131.28,-36 41.03,-36 41.03,0 131.28,0 131.28,-36"/>
<text text-anchor="middle" x="86.15" y="-11.82" font-family="Italic" font-size="14.00">black height i</text>
</g>
<!-- K1&#45;&gt;BH2 -->
<g id="edge5" class="edge">
<title>K1&#45;&gt;BH2</title>
<path fill="none" stroke="black" d="M80.24,-71.7C79.49,-64.41 79.24,-55.73 79.51,-47.54"/>
<polygon fill="black" stroke="black" points="83,-47.82 80.16,-37.61 76.01,-47.36 83,-47.82"/>
</g>
<!-- K1&#45;&gt;BH2 -->
<g id="edge6" class="edge">
<title>K1&#45;&gt;BH2</title>
<path fill="none" stroke="black" d="M92.07,-71.7C92.82,-64.41 93.07,-55.73 92.8,-47.54"/>
<polygon fill="black" stroke="black" points="96.3,-47.36 92.15,-37.61 89.31,-47.82 96.3,-47.36"/>
</g>
<!-- BH3 -->
<g id="node7" class="node">
<title>BH3</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="316.28,-36 226.03,-36 226.03,0 316.28,0 316.28,-36"/>
<text text-anchor="middle" x="271.15" y="-11.82" font-family="Italic" font-size="14.00">black height i</text>
</g>
<!-- K4&#45;&gt;BH3 -->
<g id="edge7" class="edge">
<title>K4&#45;&gt;BH3</title>
<path fill="none" stroke="black" d="M265.24,-71.7C264.49,-64.41 264.24,-55.73 264.51,-47.54"/>
<polygon fill="black" stroke="black" points="268,-47.82 265.16,-37.61 261.01,-47.36 268,-47.82"/>
</g>
<!-- K4&#45;&gt;BH3 -->
<g id="edge8" class="edge">
<title>K4&#45;&gt;BH3</title>
<path fill="none" stroke="black" d="M277.07,-71.7C277.82,-64.41 278.07,-55.73 277.8,-47.54"/>
<polygon fill="black" stroke="black" points="281.3,-47.36 277.15,-37.61 274.31,-47.82 281.3,-47.36"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@ -0,0 +1,23 @@
digraph {
K6 -> K2
K6 -> BH1
K2 -> K1
K2 -> K4
K1 -> BH2
K1 -> BH2
K4 -> BH3
K4 -> BH3
K1 [label="K1 (distantNephew)"]
K2 [label="K2 (sibling)",color="red",fontcolor="red"]
K4 [label="K4 (closeNephew)"]
K6 [label="K6 (parent)"]
BH1 [shape="box",label="black height i + 1",style="dotted",fontname="Italic"]
BH2 [shape="box",label="black height i + 1",style="dotted",fontname="Italic"]
BH3 [shape="box",label="black height i + 1",style="dotted",fontname="Italic"]
}

View File

@ -0,0 +1,102 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 12.2.1 (20241206.2353)
-->
<!-- Pages: 1 -->
<svg width="374pt" height="260pt"
viewBox="0.00 0.00 374.28 260.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 256)">
<polygon fill="white" stroke="none" points="-4,4 -4,-256 370.28,-256 370.28,4 -4,4"/>
<!-- K6 -->
<g id="node1" class="node">
<title>K6</title>
<ellipse fill="none" stroke="black" cx="243.15" cy="-234" rx="53.91" ry="18"/>
<text text-anchor="middle" x="243.15" y="-228.95" font-family="Times,serif" font-size="14.00">K6 (parent)</text>
</g>
<!-- K2 -->
<g id="node2" class="node">
<title>K2</title>
<ellipse fill="none" stroke="red" cx="178.15" cy="-162" rx="55.96" ry="18"/>
<text text-anchor="middle" x="178.15" y="-156.95" font-family="Times,serif" font-size="14.00" fill="red">K2 (sibling)</text>
</g>
<!-- K6&#45;&gt;K2 -->
<g id="edge1" class="edge">
<title>K6&#45;&gt;K2</title>
<path fill="none" stroke="black" d="M227.75,-216.41C219.82,-207.87 209.98,-197.28 201.17,-187.79"/>
<polygon fill="black" stroke="black" points="203.85,-185.53 194.48,-180.58 198.72,-190.29 203.85,-185.53"/>
</g>
<!-- BH1 -->
<g id="node3" class="node">
<title>BH1</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="366.28,-180 252.03,-180 252.03,-144 366.28,-144 366.28,-180"/>
<text text-anchor="middle" x="309.15" y="-155.82" font-family="Italic" font-size="14.00">black height i + 1</text>
</g>
<!-- K6&#45;&gt;BH1 -->
<g id="edge2" class="edge">
<title>K6&#45;&gt;BH1</title>
<path fill="none" stroke="black" d="M258.8,-216.41C266.62,-208.12 276.26,-197.89 285,-188.62"/>
<polygon fill="black" stroke="black" points="287.35,-191.22 291.67,-181.55 282.26,-186.42 287.35,-191.22"/>
</g>
<!-- K1 -->
<g id="node4" class="node">
<title>K1</title>
<ellipse fill="none" stroke="black" cx="86.15" cy="-90" rx="86.15" ry="18"/>
<text text-anchor="middle" x="86.15" y="-84.95" font-family="Times,serif" font-size="14.00">K1 (distantNephew)</text>
</g>
<!-- K2&#45;&gt;K1 -->
<g id="edge3" class="edge">
<title>K2&#45;&gt;K1</title>
<path fill="none" stroke="black" d="M157.28,-145.12C145.39,-136.07 130.27,-124.57 117.03,-114.49"/>
<polygon fill="black" stroke="black" points="119.51,-111.98 109.44,-108.71 115.27,-117.55 119.51,-111.98"/>
</g>
<!-- K4 -->
<g id="node5" class="node">
<title>K4</title>
<ellipse fill="none" stroke="black" cx="271.15" cy="-90" rx="80.52" ry="18"/>
<text text-anchor="middle" x="271.15" y="-84.95" font-family="Times,serif" font-size="14.00">K4 (closeNephew)</text>
</g>
<!-- K2&#45;&gt;K4 -->
<g id="edge4" class="edge">
<title>K2&#45;&gt;K4</title>
<path fill="none" stroke="black" d="M199.26,-145.12C211.36,-136 226.78,-124.4 240.23,-114.28"/>
<polygon fill="black" stroke="black" points="242.07,-117.27 247.96,-108.46 237.86,-111.68 242.07,-117.27"/>
</g>
<!-- BH2 -->
<g id="node6" class="node">
<title>BH2</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="143.28,-36 29.03,-36 29.03,0 143.28,0 143.28,-36"/>
<text text-anchor="middle" x="86.15" y="-11.82" font-family="Italic" font-size="14.00">black height i + 1</text>
</g>
<!-- K1&#45;&gt;BH2 -->
<g id="edge5" class="edge">
<title>K1&#45;&gt;BH2</title>
<path fill="none" stroke="black" d="M80.24,-71.7C79.49,-64.41 79.24,-55.73 79.51,-47.54"/>
<polygon fill="black" stroke="black" points="83,-47.82 80.16,-37.61 76.01,-47.36 83,-47.82"/>
</g>
<!-- K1&#45;&gt;BH2 -->
<g id="edge6" class="edge">
<title>K1&#45;&gt;BH2</title>
<path fill="none" stroke="black" d="M92.07,-71.7C92.82,-64.41 93.07,-55.73 92.8,-47.54"/>
<polygon fill="black" stroke="black" points="96.3,-47.36 92.15,-37.61 89.31,-47.82 96.3,-47.36"/>
</g>
<!-- BH3 -->
<g id="node7" class="node">
<title>BH3</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="328.28,-36 214.03,-36 214.03,0 328.28,0 328.28,-36"/>
<text text-anchor="middle" x="271.15" y="-11.82" font-family="Italic" font-size="14.00">black height i + 1</text>
</g>
<!-- K4&#45;&gt;BH3 -->
<g id="edge7" class="edge">
<title>K4&#45;&gt;BH3</title>
<path fill="none" stroke="black" d="M265.24,-71.7C264.49,-64.41 264.24,-55.73 264.51,-47.54"/>
<polygon fill="black" stroke="black" points="268,-47.82 265.16,-37.61 261.01,-47.36 268,-47.82"/>
</g>
<!-- K4&#45;&gt;BH3 -->
<g id="edge8" class="edge">
<title>K4&#45;&gt;BH3</title>
<path fill="none" stroke="black" d="M277.07,-71.7C277.82,-64.41 278.07,-55.73 277.8,-47.54"/>
<polygon fill="black" stroke="black" points="281.3,-47.36 277.15,-37.61 274.31,-47.82 281.3,-47.36"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@ -0,0 +1,26 @@
digraph {
K2 -> K1
K2 -> K6
K1 -> BH1
K1 -> BH1
K6 -> K4
K6 -> BH2
K4 -> BH3
K4 -> BH4
K1 [label="K1"]
K2 [label="K2"]
K4 [label="K4 (sibling)"]
K6 [label="K6 (parent)",color="red",fontcolor="red"]
BH1 [shape="box",label="black height i + 1",style="dotted",fontname="Italic"]
BH2 [shape="box",label="black height i + 1",style="dotted",fontname="Italic"]
BH3 [shape="box",label="black height i + 1\nwith root K3 (distantNephew)",style="dotted",fontname="Italic"]
BH4 [shape="box",label="black height i + 1\nwith root K5 (closeNephew)",style="dotted",fontname="Italic"]
}

View File

@ -0,0 +1,110 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 12.2.1 (20241206.2353)
-->
<!-- Pages: 1 -->
<svg width="384pt" height="261pt"
viewBox="0.00 0.00 384.25 260.50" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 256.5)">
<polygon fill="white" stroke="none" points="-4,4 -4,-256.5 380.25,-256.5 380.25,4 -4,4"/>
<!-- K2 -->
<g id="node1" class="node">
<title>K2</title>
<ellipse fill="none" stroke="black" cx="122.12" cy="-234.5" rx="27" ry="18"/>
<text text-anchor="middle" x="122.12" y="-229.45" font-family="Times,serif" font-size="14.00">K2</text>
</g>
<!-- K1 -->
<g id="node2" class="node">
<title>K1</title>
<ellipse fill="none" stroke="black" cx="57.12" cy="-162.5" rx="27" ry="18"/>
<text text-anchor="middle" x="57.13" y="-157.45" font-family="Times,serif" font-size="14.00">K1</text>
</g>
<!-- K2&#45;&gt;K1 -->
<g id="edge1" class="edge">
<title>K2&#45;&gt;K1</title>
<path fill="none" stroke="black" d="M108.34,-218.65C99.72,-209.37 88.44,-197.23 78.66,-186.69"/>
<polygon fill="black" stroke="black" points="81.29,-184.38 71.92,-179.43 76.16,-189.14 81.29,-184.38"/>
</g>
<!-- K6 -->
<g id="node3" class="node">
<title>K6</title>
<ellipse fill="none" stroke="red" cx="188.12" cy="-162.5" rx="53.91" ry="18"/>
<text text-anchor="middle" x="188.12" y="-157.45" font-family="Times,serif" font-size="14.00" fill="red">K6 (parent)</text>
</g>
<!-- K2&#45;&gt;K6 -->
<g id="edge2" class="edge">
<title>K2&#45;&gt;K6</title>
<path fill="none" stroke="black" d="M136.12,-218.65C144.52,-209.75 155.4,-198.21 165.04,-187.98"/>
<polygon fill="black" stroke="black" points="167.41,-190.57 171.73,-180.89 162.32,-185.77 167.41,-190.57"/>
</g>
<!-- BH1 -->
<g id="node4" class="node">
<title>BH1</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="114.25,-108.5 0,-108.5 0,-72.5 114.25,-72.5 114.25,-108.5"/>
<text text-anchor="middle" x="57.13" y="-84.33" font-family="Italic" font-size="14.00">black height i + 1</text>
</g>
<!-- K1&#45;&gt;BH1 -->
<g id="edge3" class="edge">
<title>K1&#45;&gt;BH1</title>
<path fill="none" stroke="black" d="M51.25,-144.55C50.46,-137.18 50.21,-128.34 50.48,-120.01"/>
<polygon fill="black" stroke="black" points="53.96,-120.49 51.11,-110.29 46.97,-120.04 53.96,-120.49"/>
</g>
<!-- K1&#45;&gt;BH1 -->
<g id="edge4" class="edge">
<title>K1&#45;&gt;BH1</title>
<path fill="none" stroke="black" d="M63,-144.55C63.79,-137.18 64.04,-128.34 63.77,-120.01"/>
<polygon fill="black" stroke="black" points="67.28,-120.04 63.14,-110.29 60.29,-120.49 67.28,-120.04"/>
</g>
<!-- K4 -->
<g id="node5" class="node">
<title>K4</title>
<ellipse fill="none" stroke="black" cx="188.12" cy="-90.5" rx="55.96" ry="18"/>
<text text-anchor="middle" x="188.12" y="-85.45" font-family="Times,serif" font-size="14.00">K4 (sibling)</text>
</g>
<!-- K6&#45;&gt;K4 -->
<g id="edge5" class="edge">
<title>K6&#45;&gt;K4</title>
<path fill="none" stroke="black" d="M188.12,-144.2C188.12,-136.91 188.12,-128.23 188.12,-120.04"/>
<polygon fill="black" stroke="black" points="191.63,-120.12 188.13,-110.12 184.63,-120.12 191.63,-120.12"/>
</g>
<!-- BH2 -->
<g id="node6" class="node">
<title>BH2</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="376.25,-108.5 262,-108.5 262,-72.5 376.25,-72.5 376.25,-108.5"/>
<text text-anchor="middle" x="319.12" y="-84.33" font-family="Italic" font-size="14.00">black height i + 1</text>
</g>
<!-- K6&#45;&gt;BH2 -->
<g id="edge6" class="edge">
<title>K6&#45;&gt;BH2</title>
<path fill="none" stroke="black" d="M215.91,-146.65C233.56,-137.22 256.76,-124.83 276.69,-114.18"/>
<polygon fill="black" stroke="black" points="278.26,-117.31 285.43,-109.51 274.96,-111.13 278.26,-117.31"/>
</g>
<!-- BH3 -->
<g id="node7" class="node">
<title>BH3</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="181.12,-36.5 3.12,-36.5 3.12,0 181.12,0 181.12,-36.5"/>
<text text-anchor="middle" x="92.12" y="-19.2" font-family="Italic" font-size="14.00">black height i + 1</text>
<text text-anchor="middle" x="92.12" y="-4.95" font-family="Italic" font-size="14.00">with root K3 (distantNephew)</text>
</g>
<!-- K4&#45;&gt;BH3 -->
<g id="edge7" class="edge">
<title>K4&#45;&gt;BH3</title>
<path fill="none" stroke="black" d="M166.34,-73.56C154.21,-64.68 138.84,-53.44 125.25,-43.49"/>
<polygon fill="black" stroke="black" points="127.54,-40.83 117.4,-37.75 123.41,-46.48 127.54,-40.83"/>
</g>
<!-- BH4 -->
<g id="node8" class="node">
<title>BH4</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="368.62,-36.5 199.62,-36.5 199.62,0 368.62,0 368.62,-36.5"/>
<text text-anchor="middle" x="284.12" y="-19.2" font-family="Italic" font-size="14.00">black height i + 1</text>
<text text-anchor="middle" x="284.12" y="-4.95" font-family="Italic" font-size="14.00">with root K5 (closeNephew)</text>
</g>
<!-- K4&#45;&gt;BH4 -->
<g id="edge8" class="edge">
<title>K4&#45;&gt;BH4</title>
<path fill="none" stroke="black" d="M209.91,-73.56C222.04,-64.68 237.41,-53.44 251,-43.49"/>
<polygon fill="black" stroke="black" points="252.84,-46.48 258.85,-37.75 248.71,-40.83 252.84,-46.48"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

@ -0,0 +1,30 @@
digraph {
K2 -> K1
K2 -> K6
K6 -> K4
K6 -> BH3
K1 -> BH1
K1 -> BH1
K4 -> K3
K3 -> BH2
K3 -> BH2
K4 -> BH4
K1 [label="K1"]
K2 [label="K2"]
K3 [label="K3 (distantNephew)",color="red",fontcolor="red"]
K4 [label="K4 (sibling)"]
K6 [label="K6 (parent)",color="red",fontcolor="red"]
BH1 [shape="box",label="black height i + 1",style="dotted",fontname="Italic"]
BH2 [shape="box",label="black height i + 1",style="dotted",fontname="Italic"]
BH3 [shape="box",label="black height i + 1",style="dotted",fontname="Italic"]
BH4 [shape="box",label="black height i + 1",style="dotted",fontname="Italic"]
}

View File

@ -0,0 +1,126 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 12.2.1 (20241206.2353)
-->
<!-- Pages: 1 -->
<svg width="384pt" height="332pt"
viewBox="0.00 0.00 384.25 332.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 328)">
<polygon fill="white" stroke="none" points="-4,4 -4,-328 380.25,-328 380.25,4 -4,4"/>
<!-- K2 -->
<g id="node1" class="node">
<title>K2</title>
<ellipse fill="none" stroke="black" cx="122.12" cy="-306" rx="27" ry="18"/>
<text text-anchor="middle" x="122.12" y="-300.95" font-family="Times,serif" font-size="14.00">K2</text>
</g>
<!-- K1 -->
<g id="node2" class="node">
<title>K1</title>
<ellipse fill="none" stroke="black" cx="57.12" cy="-234" rx="27" ry="18"/>
<text text-anchor="middle" x="57.12" y="-228.95" font-family="Times,serif" font-size="14.00">K1</text>
</g>
<!-- K2&#45;&gt;K1 -->
<g id="edge1" class="edge">
<title>K2&#45;&gt;K1</title>
<path fill="none" stroke="black" d="M108.34,-290.15C99.72,-280.87 88.44,-268.73 78.66,-258.19"/>
<polygon fill="black" stroke="black" points="81.29,-255.88 71.92,-250.93 76.16,-260.64 81.29,-255.88"/>
</g>
<!-- K6 -->
<g id="node3" class="node">
<title>K6</title>
<ellipse fill="none" stroke="red" cx="188.12" cy="-234" rx="53.91" ry="18"/>
<text text-anchor="middle" x="188.12" y="-228.95" font-family="Times,serif" font-size="14.00" fill="red">K6 (parent)</text>
</g>
<!-- K2&#45;&gt;K6 -->
<g id="edge2" class="edge">
<title>K2&#45;&gt;K6</title>
<path fill="none" stroke="black" d="M136.12,-290.15C144.52,-281.25 155.4,-269.71 165.04,-259.48"/>
<polygon fill="black" stroke="black" points="167.41,-262.07 171.73,-252.39 162.32,-257.27 167.41,-262.07"/>
</g>
<!-- BH1 -->
<g id="node6" class="node">
<title>BH1</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="114.25,-180 0,-180 0,-144 114.25,-144 114.25,-180"/>
<text text-anchor="middle" x="57.12" y="-155.82" font-family="Italic" font-size="14.00">black height i + 1</text>
</g>
<!-- K1&#45;&gt;BH1 -->
<g id="edge5" class="edge">
<title>K1&#45;&gt;BH1</title>
<path fill="none" stroke="black" d="M51.25,-216.05C50.46,-208.68 50.21,-199.84 50.48,-191.51"/>
<polygon fill="black" stroke="black" points="53.96,-191.99 51.11,-181.79 46.97,-191.54 53.96,-191.99"/>
</g>
<!-- K1&#45;&gt;BH1 -->
<g id="edge6" class="edge">
<title>K1&#45;&gt;BH1</title>
<path fill="none" stroke="black" d="M63,-216.05C63.79,-208.68 64.04,-199.84 63.77,-191.51"/>
<polygon fill="black" stroke="black" points="67.28,-191.54 63.14,-181.79 60.29,-191.99 67.28,-191.54"/>
</g>
<!-- K4 -->
<g id="node4" class="node">
<title>K4</title>
<ellipse fill="none" stroke="black" cx="188.12" cy="-162" rx="55.96" ry="18"/>
<text text-anchor="middle" x="188.12" y="-156.95" font-family="Times,serif" font-size="14.00">K4 (sibling)</text>
</g>
<!-- K6&#45;&gt;K4 -->
<g id="edge3" class="edge">
<title>K6&#45;&gt;K4</title>
<path fill="none" stroke="black" d="M188.12,-215.7C188.12,-208.41 188.12,-199.73 188.12,-191.54"/>
<polygon fill="black" stroke="black" points="191.63,-191.62 188.13,-181.62 184.63,-191.62 191.63,-191.62"/>
</g>
<!-- BH3 -->
<g id="node5" class="node">
<title>BH3</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="376.25,-180 262,-180 262,-144 376.25,-144 376.25,-180"/>
<text text-anchor="middle" x="319.12" y="-155.82" font-family="Italic" font-size="14.00">black height i + 1</text>
</g>
<!-- K6&#45;&gt;BH3 -->
<g id="edge4" class="edge">
<title>K6&#45;&gt;BH3</title>
<path fill="none" stroke="black" d="M215.91,-218.15C233.56,-208.72 256.76,-196.33 276.69,-185.68"/>
<polygon fill="black" stroke="black" points="278.26,-188.81 285.43,-181.01 274.96,-182.63 278.26,-188.81"/>
</g>
<!-- K3 -->
<g id="node7" class="node">
<title>K3</title>
<ellipse fill="none" stroke="red" cx="107.12" cy="-90" rx="86.15" ry="18"/>
<text text-anchor="middle" x="107.12" y="-84.95" font-family="Times,serif" font-size="14.00" fill="red">K3 (distantNephew)</text>
</g>
<!-- K4&#45;&gt;K3 -->
<g id="edge7" class="edge">
<title>K4&#45;&gt;K3</title>
<path fill="none" stroke="black" d="M169.34,-144.76C159.23,-136.03 146.57,-125.09 135.31,-115.36"/>
<polygon fill="black" stroke="black" points="137.66,-112.76 127.8,-108.87 133.08,-118.05 137.66,-112.76"/>
</g>
<!-- BH4 -->
<g id="node9" class="node">
<title>BH4</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="325.25,-108 211,-108 211,-72 325.25,-72 325.25,-108"/>
<text text-anchor="middle" x="268.12" y="-83.83" font-family="Italic" font-size="14.00">black height i + 1</text>
</g>
<!-- K4&#45;&gt;BH4 -->
<g id="edge10" class="edge">
<title>K4&#45;&gt;BH4</title>
<path fill="none" stroke="black" d="M206.68,-144.76C216.51,-136.16 228.8,-125.41 239.8,-115.78"/>
<polygon fill="black" stroke="black" points="241.91,-118.59 247.13,-109.37 237.3,-113.32 241.91,-118.59"/>
</g>
<!-- BH2 -->
<g id="node8" class="node">
<title>BH2</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="164.25,-36 50,-36 50,0 164.25,0 164.25,-36"/>
<text text-anchor="middle" x="107.12" y="-11.82" font-family="Italic" font-size="14.00">black height i + 1</text>
</g>
<!-- K3&#45;&gt;BH2 -->
<g id="edge8" class="edge">
<title>K3&#45;&gt;BH2</title>
<path fill="none" stroke="black" d="M101.21,-71.7C100.46,-64.41 100.21,-55.73 100.48,-47.54"/>
<polygon fill="black" stroke="black" points="103.97,-47.82 101.13,-37.61 96.98,-47.36 103.97,-47.82"/>
</g>
<!-- K3&#45;&gt;BH2 -->
<g id="edge9" class="edge">
<title>K3&#45;&gt;BH2</title>
<path fill="none" stroke="black" d="M113.04,-71.7C113.79,-64.41 114.04,-55.73 113.77,-47.54"/>
<polygon fill="black" stroke="black" points="117.27,-47.36 113.12,-37.61 110.28,-47.82 117.27,-47.36"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.8 KiB

View File

@ -0,0 +1,27 @@
digraph {
K2 -> K1
K2 -> K4
K1 -> BH1
K1 -> BH1
K4 -> K3
K4 -> K6
K3 -> BH2
K3 -> BH2
K6 -> BH3
K6 -> BH3
K1 [label="K1"]
K2 [label="K2"]
K3 [label="K3 (distantNephew)"]
K4 [label="K4 (sibling)",color="red",fontcolor="red"]
K6 [label="K6 (parent)"]
BH1 [shape="box",label="black height i + 1",style="dotted",fontname="Italic"]
BH2 [shape="box",label="black height i + 1",style="dotted",fontname="Italic"]
BH3 [shape="box",label="black height i + 1",style="dotted",fontname="Italic"]
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 12.2.1 (20241206.2353)
-->
<!-- Pages: 1 -->
<svg width="441pt" height="260pt"
viewBox="0.00 0.00 441.25 260.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 256)">
<polygon fill="white" stroke="none" points="-4,4 -4,-256 437.25,-256 437.25,4 -4,4"/>
<!-- K2 -->
<g id="node1" class="node">
<title>K2</title>
<ellipse fill="none" stroke="black" cx="137.12" cy="-234" rx="27" ry="18"/>
<text text-anchor="middle" x="137.12" y="-228.95" font-family="Times,serif" font-size="14.00">K2</text>
</g>
<!-- K1 -->
<g id="node2" class="node">
<title>K1</title>
<ellipse fill="none" stroke="black" cx="57.12" cy="-162" rx="27" ry="18"/>
<text text-anchor="middle" x="57.12" y="-156.95" font-family="Times,serif" font-size="14.00">K1</text>
</g>
<!-- K2&#45;&gt;K1 -->
<g id="edge1" class="edge">
<title>K2&#45;&gt;K1</title>
<path fill="none" stroke="black" d="M121.32,-219.17C109.92,-209.2 94.33,-195.56 81.37,-184.21"/>
<polygon fill="black" stroke="black" points="83.87,-181.75 74.04,-177.8 79.26,-187.02 83.87,-181.75"/>
</g>
<!-- K4 -->
<g id="node3" class="node">
<title>K4</title>
<ellipse fill="none" stroke="red" cx="218.12" cy="-162" rx="55.96" ry="18"/>
<text text-anchor="middle" x="218.12" y="-156.95" font-family="Times,serif" font-size="14.00" fill="red">K4 (sibling)</text>
</g>
<!-- K2&#45;&gt;K4 -->
<g id="edge2" class="edge">
<title>K2&#45;&gt;K4</title>
<path fill="none" stroke="black" d="M153.13,-219.17C163.81,-209.94 178.14,-197.55 190.63,-186.76"/>
<polygon fill="black" stroke="black" points="192.89,-189.43 198.17,-180.25 188.31,-184.14 192.89,-189.43"/>
</g>
<!-- BH1 -->
<g id="node4" class="node">
<title>BH1</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="114.25,-108 0,-108 0,-72 114.25,-72 114.25,-108"/>
<text text-anchor="middle" x="57.12" y="-83.83" font-family="Italic" font-size="14.00">black height i + 1</text>
</g>
<!-- K1&#45;&gt;BH1 -->
<g id="edge3" class="edge">
<title>K1&#45;&gt;BH1</title>
<path fill="none" stroke="black" d="M51.25,-144.05C50.46,-136.68 50.21,-127.84 50.48,-119.51"/>
<polygon fill="black" stroke="black" points="53.96,-119.99 51.11,-109.79 46.97,-119.54 53.96,-119.99"/>
</g>
<!-- K1&#45;&gt;BH1 -->
<g id="edge4" class="edge">
<title>K1&#45;&gt;BH1</title>
<path fill="none" stroke="black" d="M63,-144.05C63.79,-136.68 64.04,-127.84 63.77,-119.51"/>
<polygon fill="black" stroke="black" points="67.28,-119.54 63.14,-109.79 60.29,-119.99 67.28,-119.54"/>
</g>
<!-- K3 -->
<g id="node5" class="node">
<title>K3</title>
<ellipse fill="none" stroke="black" cx="218.12" cy="-90" rx="86.15" ry="18"/>
<text text-anchor="middle" x="218.12" y="-84.95" font-family="Times,serif" font-size="14.00">K3 (distantNephew)</text>
</g>
<!-- K4&#45;&gt;K3 -->
<g id="edge5" class="edge">
<title>K4&#45;&gt;K3</title>
<path fill="none" stroke="black" d="M218.12,-143.7C218.12,-136.41 218.12,-127.73 218.12,-119.54"/>
<polygon fill="black" stroke="black" points="221.63,-119.62 218.13,-109.62 214.63,-119.62 221.63,-119.62"/>
</g>
<!-- K6 -->
<g id="node6" class="node">
<title>K6</title>
<ellipse fill="none" stroke="black" cx="376.12" cy="-90" rx="53.91" ry="18"/>
<text text-anchor="middle" x="376.12" y="-84.95" font-family="Times,serif" font-size="14.00">K6 (parent)</text>
</g>
<!-- K4&#45;&gt;K6 -->
<g id="edge6" class="edge">
<title>K4&#45;&gt;K6</title>
<path fill="none" stroke="black" d="M250.1,-146.83C274.27,-136.13 307.68,-121.32 334.02,-109.65"/>
<polygon fill="black" stroke="black" points="335.36,-112.89 343.09,-105.64 332.52,-106.49 335.36,-112.89"/>
</g>
<!-- BH2 -->
<g id="node7" class="node">
<title>BH2</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="275.25,-36 161,-36 161,0 275.25,0 275.25,-36"/>
<text text-anchor="middle" x="218.12" y="-11.82" font-family="Italic" font-size="14.00">black height i + 1</text>
</g>
<!-- K3&#45;&gt;BH2 -->
<g id="edge7" class="edge">
<title>K3&#45;&gt;BH2</title>
<path fill="none" stroke="black" d="M212.21,-71.7C211.46,-64.41 211.21,-55.73 211.48,-47.54"/>
<polygon fill="black" stroke="black" points="214.97,-47.82 212.13,-37.61 207.98,-47.36 214.97,-47.82"/>
</g>
<!-- K3&#45;&gt;BH2 -->
<g id="edge8" class="edge">
<title>K3&#45;&gt;BH2</title>
<path fill="none" stroke="black" d="M224.04,-71.7C224.79,-64.41 225.04,-55.73 224.77,-47.54"/>
<polygon fill="black" stroke="black" points="228.27,-47.36 224.12,-37.61 221.28,-47.82 228.27,-47.36"/>
</g>
<!-- BH3 -->
<g id="node8" class="node">
<title>BH3</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="433.25,-36 319,-36 319,0 433.25,0 433.25,-36"/>
<text text-anchor="middle" x="376.12" y="-11.82" font-family="Italic" font-size="14.00">black height i + 1</text>
</g>
<!-- K6&#45;&gt;BH3 -->
<g id="edge9" class="edge">
<title>K6&#45;&gt;BH3</title>
<path fill="none" stroke="black" d="M370.21,-71.7C369.46,-64.41 369.21,-55.73 369.48,-47.54"/>
<polygon fill="black" stroke="black" points="372.97,-47.82 370.13,-37.61 365.98,-47.36 372.97,-47.82"/>
</g>
<!-- K6&#45;&gt;BH3 -->
<g id="edge10" class="edge">
<title>K6&#45;&gt;BH3</title>
<path fill="none" stroke="black" d="M382.04,-71.7C382.79,-64.41 383.04,-55.73 382.77,-47.54"/>
<polygon fill="black" stroke="black" points="386.27,-47.36 382.12,-37.61 379.28,-47.82 386.27,-47.36"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

@ -0,0 +1,29 @@
digraph {
K2 -> K1
K2 -> K6
K6 -> K4
K6 -> BH3
K1 -> BH1
K1 -> BH1
K4 -> BH2
K4 -> K5
K5 -> BH4
K5 -> BH4
K1 [label="K1"]
K2 [label="K2"]
K4 [label="K4 (sibling)"]
K5 [label="K5 (closeNephew)",color="red",fontcolor="red"]
K6 [label="K6 (parent)",color="red",fontcolor="red"]
BH1 [shape="box",label="black height i + 1",style="dotted",fontname="Italic"]
BH2 [shape="box",label="black height i + 1",style="dotted",fontname="Italic"]
BH3 [shape="box",label="black height i + 1",style="dotted",fontname="Italic"]
BH4 [shape="box",label="black height i + 1",style="dotted",fontname="Italic"]
}

View File

@ -0,0 +1,126 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 12.2.1 (20241206.2353)
-->
<!-- Pages: 1 -->
<svg width="384pt" height="332pt"
viewBox="0.00 0.00 384.25 332.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 328)">
<polygon fill="white" stroke="none" points="-4,4 -4,-328 380.25,-328 380.25,4 -4,4"/>
<!-- K2 -->
<g id="node1" class="node">
<title>K2</title>
<ellipse fill="none" stroke="black" cx="122.12" cy="-306" rx="27" ry="18"/>
<text text-anchor="middle" x="122.12" y="-300.95" font-family="Times,serif" font-size="14.00">K2</text>
</g>
<!-- K1 -->
<g id="node2" class="node">
<title>K1</title>
<ellipse fill="none" stroke="black" cx="57.12" cy="-234" rx="27" ry="18"/>
<text text-anchor="middle" x="57.12" y="-228.95" font-family="Times,serif" font-size="14.00">K1</text>
</g>
<!-- K2&#45;&gt;K1 -->
<g id="edge1" class="edge">
<title>K2&#45;&gt;K1</title>
<path fill="none" stroke="black" d="M108.34,-290.15C99.72,-280.87 88.44,-268.73 78.66,-258.19"/>
<polygon fill="black" stroke="black" points="81.29,-255.88 71.92,-250.93 76.16,-260.64 81.29,-255.88"/>
</g>
<!-- K6 -->
<g id="node3" class="node">
<title>K6</title>
<ellipse fill="none" stroke="red" cx="188.12" cy="-234" rx="53.91" ry="18"/>
<text text-anchor="middle" x="188.12" y="-228.95" font-family="Times,serif" font-size="14.00" fill="red">K6 (parent)</text>
</g>
<!-- K2&#45;&gt;K6 -->
<g id="edge2" class="edge">
<title>K2&#45;&gt;K6</title>
<path fill="none" stroke="black" d="M136.12,-290.15C144.52,-281.25 155.4,-269.71 165.04,-259.48"/>
<polygon fill="black" stroke="black" points="167.41,-262.07 171.73,-252.39 162.32,-257.27 167.41,-262.07"/>
</g>
<!-- BH1 -->
<g id="node6" class="node">
<title>BH1</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="114.25,-180 0,-180 0,-144 114.25,-144 114.25,-180"/>
<text text-anchor="middle" x="57.12" y="-155.82" font-family="Italic" font-size="14.00">black height i + 1</text>
</g>
<!-- K1&#45;&gt;BH1 -->
<g id="edge5" class="edge">
<title>K1&#45;&gt;BH1</title>
<path fill="none" stroke="black" d="M51.25,-216.05C50.46,-208.68 50.21,-199.84 50.48,-191.51"/>
<polygon fill="black" stroke="black" points="53.96,-191.99 51.11,-181.79 46.97,-191.54 53.96,-191.99"/>
</g>
<!-- K1&#45;&gt;BH1 -->
<g id="edge6" class="edge">
<title>K1&#45;&gt;BH1</title>
<path fill="none" stroke="black" d="M63,-216.05C63.79,-208.68 64.04,-199.84 63.77,-191.51"/>
<polygon fill="black" stroke="black" points="67.28,-191.54 63.14,-181.79 60.29,-191.99 67.28,-191.54"/>
</g>
<!-- K4 -->
<g id="node4" class="node">
<title>K4</title>
<ellipse fill="none" stroke="black" cx="188.12" cy="-162" rx="55.96" ry="18"/>
<text text-anchor="middle" x="188.12" y="-156.95" font-family="Times,serif" font-size="14.00">K4 (sibling)</text>
</g>
<!-- K6&#45;&gt;K4 -->
<g id="edge3" class="edge">
<title>K6&#45;&gt;K4</title>
<path fill="none" stroke="black" d="M188.12,-215.7C188.12,-208.41 188.12,-199.73 188.12,-191.54"/>
<polygon fill="black" stroke="black" points="191.63,-191.62 188.13,-181.62 184.63,-191.62 191.63,-191.62"/>
</g>
<!-- BH3 -->
<g id="node5" class="node">
<title>BH3</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="376.25,-180 262,-180 262,-144 376.25,-144 376.25,-180"/>
<text text-anchor="middle" x="319.12" y="-155.82" font-family="Italic" font-size="14.00">black height i + 1</text>
</g>
<!-- K6&#45;&gt;BH3 -->
<g id="edge4" class="edge">
<title>K6&#45;&gt;BH3</title>
<path fill="none" stroke="black" d="M215.91,-218.15C233.56,-208.72 256.76,-196.33 276.69,-185.68"/>
<polygon fill="black" stroke="black" points="278.26,-188.81 285.43,-181.01 274.96,-182.63 278.26,-188.81"/>
</g>
<!-- BH2 -->
<g id="node7" class="node">
<title>BH2</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="167.25,-108 53,-108 53,-72 167.25,-72 167.25,-108"/>
<text text-anchor="middle" x="110.12" y="-83.83" font-family="Italic" font-size="14.00">black height i + 1</text>
</g>
<!-- K4&#45;&gt;BH2 -->
<g id="edge7" class="edge">
<title>K4&#45;&gt;BH2</title>
<path fill="none" stroke="black" d="M170.03,-144.76C160.45,-136.16 148.46,-125.41 137.74,-115.78"/>
<polygon fill="black" stroke="black" points="140.39,-113.46 130.61,-109.38 135.71,-118.67 140.39,-113.46"/>
</g>
<!-- K5 -->
<g id="node8" class="node">
<title>K5</title>
<ellipse fill="none" stroke="red" cx="266.12" cy="-90" rx="80.52" ry="18"/>
<text text-anchor="middle" x="266.12" y="-84.95" font-family="Times,serif" font-size="14.00" fill="red">K5 (closeNephew)</text>
</g>
<!-- K4&#45;&gt;K5 -->
<g id="edge8" class="edge">
<title>K4&#45;&gt;K5</title>
<path fill="none" stroke="black" d="M206.22,-144.76C215.95,-136.03 228.14,-125.09 238.98,-115.36"/>
<polygon fill="black" stroke="black" points="241.09,-118.17 246.19,-108.89 236.41,-112.96 241.09,-118.17"/>
</g>
<!-- BH4 -->
<g id="node9" class="node">
<title>BH4</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="323.25,-36 209,-36 209,0 323.25,0 323.25,-36"/>
<text text-anchor="middle" x="266.12" y="-11.82" font-family="Italic" font-size="14.00">black height i + 1</text>
</g>
<!-- K5&#45;&gt;BH4 -->
<g id="edge9" class="edge">
<title>K5&#45;&gt;BH4</title>
<path fill="none" stroke="black" d="M260.21,-71.7C259.46,-64.41 259.21,-55.73 259.48,-47.54"/>
<polygon fill="black" stroke="black" points="262.97,-47.82 260.13,-37.61 255.98,-47.36 262.97,-47.82"/>
</g>
<!-- K5&#45;&gt;BH4 -->
<g id="edge10" class="edge">
<title>K5&#45;&gt;BH4</title>
<path fill="none" stroke="black" d="M272.04,-71.7C272.79,-64.41 273.04,-55.73 272.77,-47.54"/>
<polygon fill="black" stroke="black" points="276.27,-47.36 272.12,-37.61 269.28,-47.82 276.27,-47.36"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.8 KiB

View File

@ -0,0 +1,28 @@
digraph {
K2 -> K1
K2 -> K6
K6 -> K5
K6 -> BH3
K1 -> BH1
K1 -> BH1
K5 -> K4
K5 -> BH4
K4 -> BH2
K1 [label="K1"]
K2 [label="K2"]
K4 [label="K4 (distantNephew)",color="red",fontcolor="red"]
K5 [label="K5 (sibling)"]
K6 [label="K6 (parent)",color="red",fontcolor="red"]
BH1 [shape="box",label="black height i + 1",style="dotted",fontname="Italic"]
BH2 [shape="box",label="black height i + 1",style="dotted",fontname="Italic"]
BH3 [shape="box",label="black height i + 1",style="dotted",fontname="Italic"]
BH4 [shape="box",label="black height i + 1",style="dotted",fontname="Italic"]
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 12.2.1 (20241206.2353)
-->
<!-- Pages: 1 -->
<svg width="384pt" height="332pt"
viewBox="0.00 0.00 384.25 332.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 328)">
<polygon fill="white" stroke="none" points="-4,4 -4,-328 380.25,-328 380.25,4 -4,4"/>
<!-- K2 -->
<g id="node1" class="node">
<title>K2</title>
<ellipse fill="none" stroke="black" cx="122.12" cy="-306" rx="27" ry="18"/>
<text text-anchor="middle" x="122.12" y="-300.95" font-family="Times,serif" font-size="14.00">K2</text>
</g>
<!-- K1 -->
<g id="node2" class="node">
<title>K1</title>
<ellipse fill="none" stroke="black" cx="57.12" cy="-234" rx="27" ry="18"/>
<text text-anchor="middle" x="57.12" y="-228.95" font-family="Times,serif" font-size="14.00">K1</text>
</g>
<!-- K2&#45;&gt;K1 -->
<g id="edge1" class="edge">
<title>K2&#45;&gt;K1</title>
<path fill="none" stroke="black" d="M108.34,-290.15C99.72,-280.87 88.44,-268.73 78.66,-258.19"/>
<polygon fill="black" stroke="black" points="81.29,-255.88 71.92,-250.93 76.16,-260.64 81.29,-255.88"/>
</g>
<!-- K6 -->
<g id="node3" class="node">
<title>K6</title>
<ellipse fill="none" stroke="red" cx="188.12" cy="-234" rx="53.91" ry="18"/>
<text text-anchor="middle" x="188.12" y="-228.95" font-family="Times,serif" font-size="14.00" fill="red">K6 (parent)</text>
</g>
<!-- K2&#45;&gt;K6 -->
<g id="edge2" class="edge">
<title>K2&#45;&gt;K6</title>
<path fill="none" stroke="black" d="M136.12,-290.15C144.52,-281.25 155.4,-269.71 165.04,-259.48"/>
<polygon fill="black" stroke="black" points="167.41,-262.07 171.73,-252.39 162.32,-257.27 167.41,-262.07"/>
</g>
<!-- BH1 -->
<g id="node6" class="node">
<title>BH1</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="114.25,-180 0,-180 0,-144 114.25,-144 114.25,-180"/>
<text text-anchor="middle" x="57.12" y="-155.82" font-family="Italic" font-size="14.00">black height i + 1</text>
</g>
<!-- K1&#45;&gt;BH1 -->
<g id="edge5" class="edge">
<title>K1&#45;&gt;BH1</title>
<path fill="none" stroke="black" d="M51.25,-216.05C50.46,-208.68 50.21,-199.84 50.48,-191.51"/>
<polygon fill="black" stroke="black" points="53.96,-191.99 51.11,-181.79 46.97,-191.54 53.96,-191.99"/>
</g>
<!-- K1&#45;&gt;BH1 -->
<g id="edge6" class="edge">
<title>K1&#45;&gt;BH1</title>
<path fill="none" stroke="black" d="M63,-216.05C63.79,-208.68 64.04,-199.84 63.77,-191.51"/>
<polygon fill="black" stroke="black" points="67.28,-191.54 63.14,-181.79 60.29,-191.99 67.28,-191.54"/>
</g>
<!-- K5 -->
<g id="node4" class="node">
<title>K5</title>
<ellipse fill="none" stroke="black" cx="188.12" cy="-162" rx="55.96" ry="18"/>
<text text-anchor="middle" x="188.12" y="-156.95" font-family="Times,serif" font-size="14.00">K5 (sibling)</text>
</g>
<!-- K6&#45;&gt;K5 -->
<g id="edge3" class="edge">
<title>K6&#45;&gt;K5</title>
<path fill="none" stroke="black" d="M188.12,-215.7C188.12,-208.41 188.12,-199.73 188.12,-191.54"/>
<polygon fill="black" stroke="black" points="191.63,-191.62 188.13,-181.62 184.63,-191.62 191.63,-191.62"/>
</g>
<!-- BH3 -->
<g id="node5" class="node">
<title>BH3</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="376.25,-180 262,-180 262,-144 376.25,-144 376.25,-180"/>
<text text-anchor="middle" x="319.12" y="-155.82" font-family="Italic" font-size="14.00">black height i + 1</text>
</g>
<!-- K6&#45;&gt;BH3 -->
<g id="edge4" class="edge">
<title>K6&#45;&gt;BH3</title>
<path fill="none" stroke="black" d="M215.91,-218.15C233.56,-208.72 256.76,-196.33 276.69,-185.68"/>
<polygon fill="black" stroke="black" points="278.26,-188.81 285.43,-181.01 274.96,-182.63 278.26,-188.81"/>
</g>
<!-- K4 -->
<g id="node7" class="node">
<title>K4</title>
<ellipse fill="none" stroke="red" cx="107.12" cy="-90" rx="86.15" ry="18"/>
<text text-anchor="middle" x="107.12" y="-84.95" font-family="Times,serif" font-size="14.00" fill="red">K4 (distantNephew)</text>
</g>
<!-- K5&#45;&gt;K4 -->
<g id="edge7" class="edge">
<title>K5&#45;&gt;K4</title>
<path fill="none" stroke="black" d="M169.34,-144.76C159.23,-136.03 146.57,-125.09 135.31,-115.36"/>
<polygon fill="black" stroke="black" points="137.66,-112.76 127.8,-108.87 133.08,-118.05 137.66,-112.76"/>
</g>
<!-- BH4 -->
<g id="node8" class="node">
<title>BH4</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="325.25,-108 211,-108 211,-72 325.25,-72 325.25,-108"/>
<text text-anchor="middle" x="268.12" y="-83.83" font-family="Italic" font-size="14.00">black height i + 1</text>
</g>
<!-- K5&#45;&gt;BH4 -->
<g id="edge8" class="edge">
<title>K5&#45;&gt;BH4</title>
<path fill="none" stroke="black" d="M206.68,-144.76C216.51,-136.16 228.8,-125.41 239.8,-115.78"/>
<polygon fill="black" stroke="black" points="241.91,-118.59 247.13,-109.37 237.3,-113.32 241.91,-118.59"/>
</g>
<!-- BH2 -->
<g id="node9" class="node">
<title>BH2</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="164.25,-36 50,-36 50,0 164.25,0 164.25,-36"/>
<text text-anchor="middle" x="107.12" y="-11.82" font-family="Italic" font-size="14.00">black height i + 1</text>
</g>
<!-- K4&#45;&gt;BH2 -->
<g id="edge9" class="edge">
<title>K4&#45;&gt;BH2</title>
<path fill="none" stroke="black" d="M107.12,-71.7C107.12,-64.41 107.12,-55.73 107.12,-47.54"/>
<polygon fill="black" stroke="black" points="110.63,-47.62 107.13,-37.62 103.63,-47.62 110.63,-47.62"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

@ -0,0 +1,27 @@
digraph {
K2 -> K1
K2 -> K5
K1 -> BH1
K1 -> BH1
K5 -> K4
K5 -> K6
K4 -> BH2
K4 -> BH2
K6 -> BH3
K6 -> BH3
K1 [label="K1"]
K2 [label="K2"]
K4 [label="K4 (distantNephew)"]
K5 [label="K5 (sibling)",color="red",fontcolor="red"]
K6 [label="K6 (parent)"]
BH1 [shape="box",label="black height i + 1",style="dotted",fontname="Italic"]
BH2 [shape="box",label="black height i + 1",style="dotted",fontname="Italic"]
BH3 [shape="box",label="black height i + 1",style="dotted",fontname="Italic"]
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 12.2.1 (20241206.2353)
-->
<!-- Pages: 1 -->
<svg width="441pt" height="260pt"
viewBox="0.00 0.00 441.25 260.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 256)">
<polygon fill="white" stroke="none" points="-4,4 -4,-256 437.25,-256 437.25,4 -4,4"/>
<!-- K2 -->
<g id="node1" class="node">
<title>K2</title>
<ellipse fill="none" stroke="black" cx="137.12" cy="-234" rx="27" ry="18"/>
<text text-anchor="middle" x="137.12" y="-228.95" font-family="Times,serif" font-size="14.00">K2</text>
</g>
<!-- K1 -->
<g id="node2" class="node">
<title>K1</title>
<ellipse fill="none" stroke="black" cx="57.12" cy="-162" rx="27" ry="18"/>
<text text-anchor="middle" x="57.12" y="-156.95" font-family="Times,serif" font-size="14.00">K1</text>
</g>
<!-- K2&#45;&gt;K1 -->
<g id="edge1" class="edge">
<title>K2&#45;&gt;K1</title>
<path fill="none" stroke="black" d="M121.32,-219.17C109.92,-209.2 94.33,-195.56 81.37,-184.21"/>
<polygon fill="black" stroke="black" points="83.87,-181.75 74.04,-177.8 79.26,-187.02 83.87,-181.75"/>
</g>
<!-- K5 -->
<g id="node3" class="node">
<title>K5</title>
<ellipse fill="none" stroke="red" cx="218.12" cy="-162" rx="55.96" ry="18"/>
<text text-anchor="middle" x="218.12" y="-156.95" font-family="Times,serif" font-size="14.00" fill="red">K5 (sibling)</text>
</g>
<!-- K2&#45;&gt;K5 -->
<g id="edge2" class="edge">
<title>K2&#45;&gt;K5</title>
<path fill="none" stroke="black" d="M153.13,-219.17C163.81,-209.94 178.14,-197.55 190.63,-186.76"/>
<polygon fill="black" stroke="black" points="192.89,-189.43 198.17,-180.25 188.31,-184.14 192.89,-189.43"/>
</g>
<!-- BH1 -->
<g id="node4" class="node">
<title>BH1</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="114.25,-108 0,-108 0,-72 114.25,-72 114.25,-108"/>
<text text-anchor="middle" x="57.12" y="-83.83" font-family="Italic" font-size="14.00">black height i + 1</text>
</g>
<!-- K1&#45;&gt;BH1 -->
<g id="edge3" class="edge">
<title>K1&#45;&gt;BH1</title>
<path fill="none" stroke="black" d="M51.25,-144.05C50.46,-136.68 50.21,-127.84 50.48,-119.51"/>
<polygon fill="black" stroke="black" points="53.96,-119.99 51.11,-109.79 46.97,-119.54 53.96,-119.99"/>
</g>
<!-- K1&#45;&gt;BH1 -->
<g id="edge4" class="edge">
<title>K1&#45;&gt;BH1</title>
<path fill="none" stroke="black" d="M63,-144.05C63.79,-136.68 64.04,-127.84 63.77,-119.51"/>
<polygon fill="black" stroke="black" points="67.28,-119.54 63.14,-109.79 60.29,-119.99 67.28,-119.54"/>
</g>
<!-- K4 -->
<g id="node5" class="node">
<title>K4</title>
<ellipse fill="none" stroke="black" cx="218.12" cy="-90" rx="86.15" ry="18"/>
<text text-anchor="middle" x="218.12" y="-84.95" font-family="Times,serif" font-size="14.00">K4 (distantNephew)</text>
</g>
<!-- K5&#45;&gt;K4 -->
<g id="edge5" class="edge">
<title>K5&#45;&gt;K4</title>
<path fill="none" stroke="black" d="M218.12,-143.7C218.12,-136.41 218.12,-127.73 218.12,-119.54"/>
<polygon fill="black" stroke="black" points="221.63,-119.62 218.13,-109.62 214.63,-119.62 221.63,-119.62"/>
</g>
<!-- K6 -->
<g id="node6" class="node">
<title>K6</title>
<ellipse fill="none" stroke="black" cx="376.12" cy="-90" rx="53.91" ry="18"/>
<text text-anchor="middle" x="376.12" y="-84.95" font-family="Times,serif" font-size="14.00">K6 (parent)</text>
</g>
<!-- K5&#45;&gt;K6 -->
<g id="edge6" class="edge">
<title>K5&#45;&gt;K6</title>
<path fill="none" stroke="black" d="M250.1,-146.83C274.27,-136.13 307.68,-121.32 334.02,-109.65"/>
<polygon fill="black" stroke="black" points="335.36,-112.89 343.09,-105.64 332.52,-106.49 335.36,-112.89"/>
</g>
<!-- BH2 -->
<g id="node7" class="node">
<title>BH2</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="275.25,-36 161,-36 161,0 275.25,0 275.25,-36"/>
<text text-anchor="middle" x="218.12" y="-11.82" font-family="Italic" font-size="14.00">black height i + 1</text>
</g>
<!-- K4&#45;&gt;BH2 -->
<g id="edge7" class="edge">
<title>K4&#45;&gt;BH2</title>
<path fill="none" stroke="black" d="M212.21,-71.7C211.46,-64.41 211.21,-55.73 211.48,-47.54"/>
<polygon fill="black" stroke="black" points="214.97,-47.82 212.13,-37.61 207.98,-47.36 214.97,-47.82"/>
</g>
<!-- K4&#45;&gt;BH2 -->
<g id="edge8" class="edge">
<title>K4&#45;&gt;BH2</title>
<path fill="none" stroke="black" d="M224.04,-71.7C224.79,-64.41 225.04,-55.73 224.77,-47.54"/>
<polygon fill="black" stroke="black" points="228.27,-47.36 224.12,-37.61 221.28,-47.82 228.27,-47.36"/>
</g>
<!-- BH3 -->
<g id="node8" class="node">
<title>BH3</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="433.25,-36 319,-36 319,0 433.25,0 433.25,-36"/>
<text text-anchor="middle" x="376.12" y="-11.82" font-family="Italic" font-size="14.00">black height i + 1</text>
</g>
<!-- K6&#45;&gt;BH3 -->
<g id="edge9" class="edge">
<title>K6&#45;&gt;BH3</title>
<path fill="none" stroke="black" d="M370.21,-71.7C369.46,-64.41 369.21,-55.73 369.48,-47.54"/>
<polygon fill="black" stroke="black" points="372.97,-47.82 370.13,-37.61 365.98,-47.36 372.97,-47.82"/>
</g>
<!-- K6&#45;&gt;BH3 -->
<g id="edge10" class="edge">
<title>K6&#45;&gt;BH3</title>
<path fill="none" stroke="black" d="M382.04,-71.7C382.79,-64.41 383.04,-55.73 382.77,-47.54"/>
<polygon fill="black" stroke="black" points="386.27,-47.36 382.12,-37.61 379.28,-47.82 386.27,-47.36"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

@ -0,0 +1,33 @@
digraph {
K2 -> K1
K2 -> K6
K6 -> K4
K6 -> BH3
K1 -> BH1
K1 -> BH1
K4 -> K3
K3 -> BH2
K3 -> BH2
K4 -> K5
K5 -> BH4
K5 -> BH4
K1 [label="K1"]
K2 [label="K2"]
K3 [label="K3 (distantNephew)"]
K4 [label="K4 (sibling)",color="red",fontcolor="red"]
K5 [label="K5 (closeNephew)"]
K6 [label="K6 (parent)"]
BH1 [shape="box",label="black height i + 1",style="dotted",fontname="Italic"]
BH2 [shape="box",label="black height i",style="dotted",fontname="Italic"]
BH3 [shape="box",label="black height i + 1",style="dotted",fontname="Italic"]
BH4 [shape="box",label="black height i",style="dotted",fontname="Italic"]
}

View File

@ -0,0 +1,144 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 12.2.1 (20241206.2353)
-->
<!-- Pages: 1 -->
<svg width="384pt" height="332pt"
viewBox="0.00 0.00 384.25 332.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 328)">
<polygon fill="white" stroke="none" points="-4,4 -4,-328 380.25,-328 380.25,4 -4,4"/>
<!-- K2 -->
<g id="node1" class="node">
<title>K2</title>
<ellipse fill="none" stroke="black" cx="122.12" cy="-306" rx="27" ry="18"/>
<text text-anchor="middle" x="122.12" y="-300.95" font-family="Times,serif" font-size="14.00">K2</text>
</g>
<!-- K1 -->
<g id="node2" class="node">
<title>K1</title>
<ellipse fill="none" stroke="black" cx="57.12" cy="-234" rx="27" ry="18"/>
<text text-anchor="middle" x="57.12" y="-228.95" font-family="Times,serif" font-size="14.00">K1</text>
</g>
<!-- K2&#45;&gt;K1 -->
<g id="edge1" class="edge">
<title>K2&#45;&gt;K1</title>
<path fill="none" stroke="black" d="M108.34,-290.15C99.72,-280.87 88.44,-268.73 78.66,-258.19"/>
<polygon fill="black" stroke="black" points="81.29,-255.88 71.92,-250.93 76.16,-260.64 81.29,-255.88"/>
</g>
<!-- K6 -->
<g id="node3" class="node">
<title>K6</title>
<ellipse fill="none" stroke="black" cx="188.12" cy="-234" rx="53.91" ry="18"/>
<text text-anchor="middle" x="188.12" y="-228.95" font-family="Times,serif" font-size="14.00">K6 (parent)</text>
</g>
<!-- K2&#45;&gt;K6 -->
<g id="edge2" class="edge">
<title>K2&#45;&gt;K6</title>
<path fill="none" stroke="black" d="M136.12,-290.15C144.52,-281.25 155.4,-269.71 165.04,-259.48"/>
<polygon fill="black" stroke="black" points="167.41,-262.07 171.73,-252.39 162.32,-257.27 167.41,-262.07"/>
</g>
<!-- BH1 -->
<g id="node6" class="node">
<title>BH1</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="114.25,-180 0,-180 0,-144 114.25,-144 114.25,-180"/>
<text text-anchor="middle" x="57.12" y="-155.82" font-family="Italic" font-size="14.00">black height i + 1</text>
</g>
<!-- K1&#45;&gt;BH1 -->
<g id="edge5" class="edge">
<title>K1&#45;&gt;BH1</title>
<path fill="none" stroke="black" d="M51.25,-216.05C50.46,-208.68 50.21,-199.84 50.48,-191.51"/>
<polygon fill="black" stroke="black" points="53.96,-191.99 51.11,-181.79 46.97,-191.54 53.96,-191.99"/>
</g>
<!-- K1&#45;&gt;BH1 -->
<g id="edge6" class="edge">
<title>K1&#45;&gt;BH1</title>
<path fill="none" stroke="black" d="M63,-216.05C63.79,-208.68 64.04,-199.84 63.77,-191.51"/>
<polygon fill="black" stroke="black" points="67.28,-191.54 63.14,-181.79 60.29,-191.99 67.28,-191.54"/>
</g>
<!-- K4 -->
<g id="node4" class="node">
<title>K4</title>
<ellipse fill="none" stroke="red" cx="188.12" cy="-162" rx="55.96" ry="18"/>
<text text-anchor="middle" x="188.12" y="-156.95" font-family="Times,serif" font-size="14.00" fill="red">K4 (sibling)</text>
</g>
<!-- K6&#45;&gt;K4 -->
<g id="edge3" class="edge">
<title>K6&#45;&gt;K4</title>
<path fill="none" stroke="black" d="M188.12,-215.7C188.12,-208.41 188.12,-199.73 188.12,-191.54"/>
<polygon fill="black" stroke="black" points="191.63,-191.62 188.13,-181.62 184.63,-191.62 191.63,-191.62"/>
</g>
<!-- BH3 -->
<g id="node5" class="node">
<title>BH3</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="376.25,-180 262,-180 262,-144 376.25,-144 376.25,-180"/>
<text text-anchor="middle" x="319.12" y="-155.82" font-family="Italic" font-size="14.00">black height i + 1</text>
</g>
<!-- K6&#45;&gt;BH3 -->
<g id="edge4" class="edge">
<title>K6&#45;&gt;BH3</title>
<path fill="none" stroke="black" d="M215.91,-218.15C233.56,-208.72 256.76,-196.33 276.69,-185.68"/>
<polygon fill="black" stroke="black" points="278.26,-188.81 285.43,-181.01 274.96,-182.63 278.26,-188.81"/>
</g>
<!-- K3 -->
<g id="node7" class="node">
<title>K3</title>
<ellipse fill="none" stroke="black" cx="95.12" cy="-90" rx="86.15" ry="18"/>
<text text-anchor="middle" x="95.12" y="-84.95" font-family="Times,serif" font-size="14.00">K3 (distantNephew)</text>
</g>
<!-- K4&#45;&gt;K3 -->
<g id="edge7" class="edge">
<title>K4&#45;&gt;K3</title>
<path fill="none" stroke="black" d="M167.02,-145.12C155,-136.07 139.72,-124.57 126.34,-114.49"/>
<polygon fill="black" stroke="black" points="128.75,-111.92 118.65,-108.71 124.54,-117.52 128.75,-111.92"/>
</g>
<!-- K5 -->
<g id="node9" class="node">
<title>K5</title>
<ellipse fill="none" stroke="black" cx="280.12" cy="-90" rx="80.52" ry="18"/>
<text text-anchor="middle" x="280.12" y="-84.95" font-family="Times,serif" font-size="14.00">K5 (closeNephew)</text>
</g>
<!-- K4&#45;&gt;K5 -->
<g id="edge10" class="edge">
<title>K4&#45;&gt;K5</title>
<path fill="none" stroke="black" d="M209,-145.12C220.89,-136.07 236.01,-124.57 249.25,-114.49"/>
<polygon fill="black" stroke="black" points="251,-117.55 256.84,-108.71 246.77,-111.98 251,-117.55"/>
</g>
<!-- BH2 -->
<g id="node8" class="node">
<title>BH2</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="140.25,-36 50,-36 50,0 140.25,0 140.25,-36"/>
<text text-anchor="middle" x="95.12" y="-11.82" font-family="Italic" font-size="14.00">black height i</text>
</g>
<!-- K3&#45;&gt;BH2 -->
<g id="edge8" class="edge">
<title>K3&#45;&gt;BH2</title>
<path fill="none" stroke="black" d="M89.21,-71.7C88.46,-64.41 88.21,-55.73 88.48,-47.54"/>
<polygon fill="black" stroke="black" points="91.97,-47.82 89.13,-37.61 84.98,-47.36 91.97,-47.82"/>
</g>
<!-- K3&#45;&gt;BH2 -->
<g id="edge9" class="edge">
<title>K3&#45;&gt;BH2</title>
<path fill="none" stroke="black" d="M101.04,-71.7C101.79,-64.41 102.04,-55.73 101.77,-47.54"/>
<polygon fill="black" stroke="black" points="105.27,-47.36 101.12,-37.61 98.28,-47.82 105.27,-47.36"/>
</g>
<!-- BH4 -->
<g id="node10" class="node">
<title>BH4</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="325.25,-36 235,-36 235,0 325.25,0 325.25,-36"/>
<text text-anchor="middle" x="280.12" y="-11.82" font-family="Italic" font-size="14.00">black height i</text>
</g>
<!-- K5&#45;&gt;BH4 -->
<g id="edge11" class="edge">
<title>K5&#45;&gt;BH4</title>
<path fill="none" stroke="black" d="M274.21,-71.7C273.46,-64.41 273.21,-55.73 273.48,-47.54"/>
<polygon fill="black" stroke="black" points="276.97,-47.82 274.13,-37.61 269.98,-47.36 276.97,-47.82"/>
</g>
<!-- K5&#45;&gt;BH4 -->
<g id="edge12" class="edge">
<title>K5&#45;&gt;BH4</title>
<path fill="none" stroke="black" d="M286.04,-71.7C286.79,-64.41 287.04,-55.73 286.77,-47.54"/>
<polygon fill="black" stroke="black" points="290.27,-47.36 286.12,-37.61 283.28,-47.82 290.27,-47.36"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@ -0,0 +1,19 @@
digraph {
K1 -> LTK1
K1 -> K2
K3 -> K1
K3 -> GTK3
K2 -> LTK2GTK1
K2 -> GTK2LTK3
K1 [label="K1 (node)",color="darkgray",fontcolor="darkgray"]
K2 [label="K2 (newChild)",color="darkgray",fontcolor="darkgray"]
K3 [label="K3 (newRoot)",color="darkgray",fontcolor="darkgray"]
LTK1 [shape="box",label="K < K1",style="dotted",fontname="Italic"]
GTK3 [shape="box",label="K > K3",style="dotted",fontname="Italic"]
LTK2GTK1 [shape="box",label="K1 < K < K2",style="dotted",fontname="Italic"]
GTK2LTK3 [shape="box",label="K2 < K < K3",style="dotted",fontname="Italic"]
}

View File

@ -0,0 +1,90 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 12.2.1 (20241206.2353)
-->
<!-- Pages: 1 -->
<svg width="251pt" height="260pt"
viewBox="0.00 0.00 250.50 260.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 256)">
<polygon fill="white" stroke="none" points="-4,4 -4,-256 246.5,-256 246.5,4 -4,4"/>
<!-- K1 -->
<g id="node1" class="node">
<title>K1</title>
<ellipse fill="none" stroke="darkgray" cx="86" cy="-162" rx="48.79" ry="18"/>
<text text-anchor="middle" x="86" y="-156.95" font-family="Times,serif" font-size="14.00" fill="darkgray">K1 (node)</text>
</g>
<!-- LTK1 -->
<g id="node2" class="node">
<title>LTK1</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="58,-108 0,-108 0,-72 58,-72 58,-108"/>
<text text-anchor="middle" x="29" y="-83.83" font-family="Italic" font-size="14.00">K &lt; K1</text>
</g>
<!-- K1&#45;&gt;LTK1 -->
<g id="edge1" class="edge">
<title>K1&#45;&gt;LTK1</title>
<path fill="none" stroke="black" d="M72.49,-144.41C65.87,-136.28 57.75,-126.31 50.32,-117.18"/>
<polygon fill="black" stroke="black" points="53.19,-115.16 44.16,-109.62 47.76,-119.58 53.19,-115.16"/>
</g>
<!-- K2 -->
<g id="node3" class="node">
<title>K2</title>
<ellipse fill="none" stroke="darkgray" cx="143" cy="-90" rx="66.71" ry="18"/>
<text text-anchor="middle" x="143" y="-84.95" font-family="Times,serif" font-size="14.00" fill="darkgray">K2 (newChild)</text>
</g>
<!-- K1&#45;&gt;K2 -->
<g id="edge2" class="edge">
<title>K1&#45;&gt;K2</title>
<path fill="none" stroke="black" d="M99.51,-144.41C106.22,-136.16 114.49,-126.01 122.01,-116.78"/>
<polygon fill="black" stroke="black" points="124.64,-119.09 128.24,-109.13 119.21,-114.67 124.64,-119.09"/>
</g>
<!-- LTK2GTK1 -->
<g id="node6" class="node">
<title>LTK2GTK1</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="133.5,-36 42.5,-36 42.5,0 133.5,0 133.5,-36"/>
<text text-anchor="middle" x="88" y="-11.82" font-family="Italic" font-size="14.00">K1 &lt; K &lt; K2</text>
</g>
<!-- K2&#45;&gt;LTK2GTK1 -->
<g id="edge5" class="edge">
<title>K2&#45;&gt;LTK2GTK1</title>
<path fill="none" stroke="black" d="M129.69,-72.05C123.36,-64.01 115.66,-54.2 108.61,-45.23"/>
<polygon fill="black" stroke="black" points="111.44,-43.17 102.51,-37.47 105.93,-47.49 111.44,-43.17"/>
</g>
<!-- GTK2LTK3 -->
<g id="node7" class="node">
<title>GTK2LTK3</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="242.5,-36 151.5,-36 151.5,0 242.5,0 242.5,-36"/>
<text text-anchor="middle" x="197" y="-11.82" font-family="Italic" font-size="14.00">K2 &lt; K &lt; K3</text>
</g>
<!-- K2&#45;&gt;GTK2LTK3 -->
<g id="edge6" class="edge">
<title>K2&#45;&gt;GTK2LTK3</title>
<path fill="none" stroke="black" d="M156.07,-72.05C162.28,-64.01 169.84,-54.2 176.77,-45.23"/>
<polygon fill="black" stroke="black" points="179.41,-47.53 182.75,-37.47 173.87,-43.25 179.41,-47.53"/>
</g>
<!-- K3 -->
<g id="node4" class="node">
<title>K3</title>
<ellipse fill="none" stroke="darkgray" cx="134" cy="-234" rx="64.15" ry="18"/>
<text text-anchor="middle" x="134" y="-228.95" font-family="Times,serif" font-size="14.00" fill="darkgray">K3 (newRoot)</text>
</g>
<!-- K3&#45;&gt;K1 -->
<g id="edge3" class="edge">
<title>K3&#45;&gt;K1</title>
<path fill="none" stroke="black" d="M122.38,-216.05C116.84,-207.97 110.08,-198.12 103.91,-189.11"/>
<polygon fill="black" stroke="black" points="106.91,-187.31 98.37,-181.04 101.14,-191.26 106.91,-187.31"/>
</g>
<!-- GTK3 -->
<g id="node5" class="node">
<title>GTK3</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="211,-180 153,-180 153,-144 211,-144 211,-180"/>
<text text-anchor="middle" x="182" y="-155.82" font-family="Italic" font-size="14.00">K &gt; K3</text>
</g>
<!-- K3&#45;&gt;GTK3 -->
<g id="edge4" class="edge">
<title>K3&#45;&gt;GTK3</title>
<path fill="none" stroke="black" d="M145.62,-216.05C151.08,-208.09 157.72,-198.41 163.82,-189.51"/>
<polygon fill="black" stroke="black" points="166.53,-191.75 169.3,-181.52 160.76,-187.79 166.53,-191.75"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -0,0 +1,19 @@
digraph {
K1 -> LTK1
K1 -> K3
K3 -> K2
K3 -> GTK3
K2 -> LTK2GTK1
K2 -> GTK2LTK3
K1 [label="K1 (node)",color="darkgray",fontcolor="darkgray"]
K3 [label="K3 (newRoot)",color="darkgray",fontcolor="darkgray"]
K2 [label="K2 (newChild)",color="darkgray",fontcolor="darkgray"]
LTK1 [shape="box",label="K < K1",style="dotted",fontname="Italic"]
GTK3 [shape="box",label="K > K3",style="dotted",fontname="Italic"]
LTK2GTK1 [shape="box",label="K1 < K < K2",style="dotted",fontname="Italic"]
GTK2LTK3 [shape="box",label="K2 < K < K3",style="dotted",fontname="Italic"]
}

View File

@ -0,0 +1,90 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 12.2.1 (20241206.2353)
-->
<!-- Pages: 1 -->
<svg width="251pt" height="260pt"
viewBox="0.00 0.00 250.50 260.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 256)">
<polygon fill="white" stroke="none" points="-4,4 -4,-256 246.5,-256 246.5,4 -4,4"/>
<!-- K1 -->
<g id="node1" class="node">
<title>K1</title>
<ellipse fill="none" stroke="darkgray" cx="100.5" cy="-234" rx="48.79" ry="18"/>
<text text-anchor="middle" x="100.5" y="-228.95" font-family="Times,serif" font-size="14.00" fill="darkgray">K1 (node)</text>
</g>
<!-- LTK1 -->
<g id="node2" class="node">
<title>LTK1</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="74.5,-180 16.5,-180 16.5,-144 74.5,-144 74.5,-180"/>
<text text-anchor="middle" x="45.5" y="-155.82" font-family="Italic" font-size="14.00">K &lt; K1</text>
</g>
<!-- K1&#45;&gt;LTK1 -->
<g id="edge1" class="edge">
<title>K1&#45;&gt;LTK1</title>
<path fill="none" stroke="black" d="M87.47,-216.41C81.15,-208.37 73.4,-198.51 66.3,-189.47"/>
<polygon fill="black" stroke="black" points="69.07,-187.34 60.14,-181.64 63.57,-191.66 69.07,-187.34"/>
</g>
<!-- K3 -->
<g id="node3" class="node">
<title>K3</title>
<ellipse fill="none" stroke="darkgray" cx="156.5" cy="-162" rx="64.15" ry="18"/>
<text text-anchor="middle" x="156.5" y="-156.95" font-family="Times,serif" font-size="14.00" fill="darkgray">K3 (newRoot)</text>
</g>
<!-- K1&#45;&gt;K3 -->
<g id="edge2" class="edge">
<title>K1&#45;&gt;K3</title>
<path fill="none" stroke="black" d="M113.77,-216.41C120.37,-208.16 128.49,-198.01 135.88,-188.78"/>
<polygon fill="black" stroke="black" points="138.48,-191.13 141.99,-181.14 133.01,-186.76 138.48,-191.13"/>
</g>
<!-- K2 -->
<g id="node4" class="node">
<title>K2</title>
<ellipse fill="none" stroke="darkgray" cx="99.5" cy="-90" rx="66.71" ry="18"/>
<text text-anchor="middle" x="99.5" y="-84.95" font-family="Times,serif" font-size="14.00" fill="darkgray">K2 (newChild)</text>
</g>
<!-- K3&#45;&gt;K2 -->
<g id="edge3" class="edge">
<title>K3&#45;&gt;K2</title>
<path fill="none" stroke="black" d="M142.7,-144.05C135.98,-135.8 127.76,-125.7 120.3,-116.54"/>
<polygon fill="black" stroke="black" points="123.16,-114.51 114.13,-108.96 117.73,-118.93 123.16,-114.51"/>
</g>
<!-- GTK3 -->
<g id="node5" class="node">
<title>GTK3</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="242.5,-108 184.5,-108 184.5,-72 242.5,-72 242.5,-108"/>
<text text-anchor="middle" x="213.5" y="-83.83" font-family="Italic" font-size="14.00">K &gt; K3</text>
</g>
<!-- K3&#45;&gt;GTK3 -->
<g id="edge4" class="edge">
<title>K3&#45;&gt;GTK3</title>
<path fill="none" stroke="black" d="M170.3,-144.05C176.92,-135.92 185,-126 192.38,-116.94"/>
<polygon fill="black" stroke="black" points="194.88,-119.41 198.48,-109.45 189.45,-114.99 194.88,-119.41"/>
</g>
<!-- LTK2GTK1 -->
<g id="node6" class="node">
<title>LTK2GTK1</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="91,-36 0,-36 0,0 91,0 91,-36"/>
<text text-anchor="middle" x="45.5" y="-11.82" font-family="Italic" font-size="14.00">K1 &lt; K &lt; K2</text>
</g>
<!-- K2&#45;&gt;LTK2GTK1 -->
<g id="edge5" class="edge">
<title>K2&#45;&gt;LTK2GTK1</title>
<path fill="none" stroke="black" d="M86.43,-72.05C80.22,-64.01 72.66,-54.2 65.73,-45.23"/>
<polygon fill="black" stroke="black" points="68.63,-43.25 59.75,-37.47 63.09,-47.53 68.63,-43.25"/>
</g>
<!-- GTK2LTK3 -->
<g id="node7" class="node">
<title>GTK2LTK3</title>
<polygon fill="none" stroke="black" stroke-dasharray="1,5" points="200,-36 109,-36 109,0 200,0 200,-36"/>
<text text-anchor="middle" x="154.5" y="-11.82" font-family="Italic" font-size="14.00">K2 &lt; K &lt; K3</text>
</g>
<!-- K2&#45;&gt;GTK2LTK3 -->
<g id="edge6" class="edge">
<title>K2&#45;&gt;GTK2LTK3</title>
<path fill="none" stroke="black" d="M112.81,-72.05C119.14,-64.01 126.84,-54.2 133.89,-45.23"/>
<polygon fill="black" stroke="black" points="136.57,-47.49 139.99,-37.47 131.06,-43.17 136.57,-47.49"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -0,0 +1,205 @@
// ======================================================================
// \title ExternalRedBlackTreeMapTest.cpp
// \author bocchino
// \brief cpp file for ExternalRedBlackTreeMap tests
// ======================================================================
#include "Fw/DataStructures/ExternalRedBlackTreeMap.hpp"
#include "Fw/DataStructures/test/ut/ExternalStackTester.hpp"
#include "Fw/DataStructures/test/ut/RedBlackTreeSetOrMapImplTester.hpp"
#include "Fw/DataStructures/test/ut/STest/MapTestRules.hpp"
#include "Fw/DataStructures/test/ut/STest/MapTestScenarios.hpp"
#include "STest/STest/Pick/Pick.hpp"
namespace Fw {
template <typename K, typename V>
class ExternalRedBlackTreeMapTester {
public:
ExternalRedBlackTreeMapTester<K, V>(const ExternalRedBlackTreeMap<K, V>& map) : m_map(map) {}
const RedBlackTreeSetOrMapImpl<K, V>& getImpl() const { return this->m_map.m_impl; }
private:
const ExternalRedBlackTreeMap<K, V>& m_map;
};
namespace MapTest {
using Impl = RedBlackTreeSetOrMapImpl<State::KeyType, State::ValueType>;
using ImplTester = RedBlackTreeSetOrMapImplTester<State::KeyType, State::ValueType>;
using Map = ExternalRedBlackTreeMap<State::KeyType, State::ValueType>;
using MapTester = ExternalRedBlackTreeMapTester<State::KeyType, State::ValueType>;
using StackTester = ExternalStackTester<ImplTester::Index>;
TEST(ExternalRedBlackTreeMap, ZeroArgConstructor) {
Map map;
ASSERT_EQ(map.getCapacity(), 0);
ASSERT_EQ(map.getSize(), 0);
}
TEST(ExternalRedBlackTreeMap, TypedStorageConstructor) {
ImplTester::Node nodes[State::capacity];
ImplTester::Index freeNodes[State::capacity];
Map map(nodes, freeNodes, State::capacity);
MapTester mapTester(map);
ImplTester implTester(mapTester.getImpl());
ASSERT_EQ(implTester.getNodes().getElements(), nodes);
StackTester stackTester(implTester.getFreeNodes());
ASSERT_EQ(stackTester.getItems().getElements(), freeNodes);
ASSERT_EQ(map.getCapacity(), FwSizeType(State::capacity));
ASSERT_EQ(map.getSize(), 0);
}
TEST(ExternalRedBlackTreeMap, UntypedStorageConstructor) {
constexpr auto alignment = Map::getByteArrayAlignment();
constexpr auto byteArraySize = Map::getByteArraySize(State::capacity);
alignas(alignment) U8 bytes[byteArraySize];
Map map(ByteArray(&bytes[0], sizeof bytes), State::capacity);
MapTester mapTester(map);
ImplTester implTester(mapTester.getImpl());
ASSERT_EQ(implTester.getNodes().getElements(), reinterpret_cast<Impl::Node*>(bytes));
ASSERT_EQ(map.getCapacity(), FwSizeType(State::capacity));
ASSERT_EQ(map.getSize(), 0);
}
TEST(ExternalRedBlackTreeMap, CopyConstructor) {
ImplTester::Node nodes[State::capacity];
ImplTester::Index freeNodes[State::capacity];
// Call the constructor providing backing storage
Map map1(nodes, freeNodes, State::capacity);
// Insert an item
const State::KeyType key = 0;
const State::ValueType value = 42;
const auto status = map1.insert(key, value);
ASSERT_EQ(status, Success::SUCCESS);
// Call the copy constructor
Map map2(map1);
MapTester mapTester1(map1);
MapTester mapTester2(map2);
ImplTester implTester1(mapTester1.getImpl());
ImplTester implTester2(mapTester2.getImpl());
ASSERT_EQ(implTester2.getNodes().getElements(), nodes);
ASSERT_EQ(implTester2.getNodes().getSize(), FwSizeType(State::capacity));
StackTester stackTester(implTester2.getFreeNodes());
ASSERT_EQ(stackTester.getItems().getElements(), freeNodes);
ASSERT_EQ(map2.getSize(), 1);
}
TEST(ExternalRedBlackTreeMap, CopyAssignmentOperator) {
ImplTester::Node nodes[State::capacity];
ImplTester::Index freeNodes[State::capacity];
// Call the constructor providing backing storage
Map map1(nodes, freeNodes, State::capacity);
// Insert an item
const State::KeyType key = 0;
const State::ValueType value = 42;
const auto status = map1.insert(key, value);
ASSERT_EQ(status, Success::SUCCESS);
// Call the default constructor
Map map2;
ASSERT_EQ(map2.getSize(), 0);
// Call the copy assignment operator
map2 = map1;
ASSERT_EQ(map2.getSize(), 1);
}
TEST(ExternalRedBlackTreeMap, CopyDataFrom) {
constexpr FwSizeType maxSize = 10;
constexpr FwSizeType smallSize = maxSize / 2;
ImplTester::Node nodes1[maxSize];
ImplTester::Node nodes2[maxSize];
ImplTester::Index freeNodes1[maxSize];
ImplTester::Index freeNodes2[maxSize];
Map m1(nodes1, freeNodes1, maxSize);
// size1 < capacity2
{
Map m2(nodes2, freeNodes2, maxSize);
State::testCopyDataFrom(m1, smallSize, m2);
}
// size1 == capacity2
{
Map m2(nodes2, freeNodes2, maxSize);
State::testCopyDataFrom(m1, maxSize, m2);
}
// size1 > capacity2
{
Map m2(nodes2, freeNodes2, smallSize);
State::testCopyDataFrom(m1, maxSize, m2);
}
}
TEST(ExternalRedBlackTreeMapScenarios, Clear) {
ImplTester::Node nodes[State::capacity];
ImplTester::Index freeNodes[State::capacity];
Map map(nodes, freeNodes, State::capacity);
State state(map);
Scenarios::clear(state);
}
TEST(ExternalRedBlackTreeMapScenarios, Find) {
ImplTester::Node nodes[State::capacity];
ImplTester::Index freeNodes[State::capacity];
Map map(nodes, freeNodes, State::capacity);
State state(map);
Scenarios::find(state);
}
TEST(ExternalRedBlackTreeMapScenarios, FindExisting) {
ImplTester::Node nodes[State::capacity];
ImplTester::Index freeNodes[State::capacity];
Map map(nodes, freeNodes, State::capacity);
State state(map);
Scenarios::findExisting(state);
}
TEST(ExternalRedBlackTreeMapScenarios, InsertExisting) {
ImplTester::Node nodes[State::capacity];
ImplTester::Index freeNodes[State::capacity];
Map map(nodes, freeNodes, State::capacity);
State state(map);
Scenarios::insertExisting(state);
}
TEST(ExternalRedBlackTreeMapScenarios, InsertFull) {
ImplTester::Node nodes[State::capacity];
ImplTester::Index freeNodes[State::capacity];
Map map(nodes, freeNodes, State::capacity);
State state(map);
Scenarios::insertFull(state);
}
TEST(ExternalRedBlackTreeMapScenarios, InsertNotFull) {
ImplTester::Node nodes[State::capacity];
ImplTester::Index freeNodes[State::capacity];
Map map(nodes, freeNodes, State::capacity);
State state(map);
Scenarios::insertNotFull(state);
}
TEST(ExternalRedBlackTreeMapScenarios, Remove) {
ImplTester::Node nodes[State::capacity];
ImplTester::Index freeNodes[State::capacity];
Map map(nodes, freeNodes, State::capacity);
State state(map);
Scenarios::remove(state);
}
TEST(ExternalRedBlackTreeMapScenarios, RemoveExisting) {
ImplTester::Node nodes[State::capacity];
ImplTester::Index freeNodes[State::capacity];
Map map(nodes, freeNodes, State::capacity);
State state(map);
Scenarios::removeExisting(state);
}
TEST(ExternalRedBlackTreeMapScenarios, Random) {
ImplTester::Node nodes[State::capacity];
ImplTester::Index freeNodes[State::capacity];
Map map(nodes, freeNodes, State::capacity);
State state(map);
Scenarios::random(Fw::String("ExternalRedBlackTreeMapRandom"), state, 1000);
}
} // namespace MapTest
} // namespace Fw

View File

@ -0,0 +1,205 @@
// ======================================================================
// \title ExternalRedBlackTreeSetTest.cpp
// \author bocchino
// \brief cpp file for ExternalRedBlackTreeSet tests
// ======================================================================
#include "Fw/DataStructures/ExternalRedBlackTreeSet.hpp"
#include "STest/STest/Pick/Pick.hpp"
#include "Fw/DataStructures/ExternalRedBlackTreeSet.hpp"
#include "Fw/DataStructures/test/ut/ExternalStackTester.hpp"
#include "Fw/DataStructures/test/ut/RedBlackTreeSetOrMapImplTester.hpp"
#include "Fw/DataStructures/test/ut/STest/SetTestRules.hpp"
#include "Fw/DataStructures/test/ut/STest/SetTestScenarios.hpp"
namespace Fw {
template <typename T>
class ExternalRedBlackTreeSetTester {
public:
ExternalRedBlackTreeSetTester<T>(const ExternalRedBlackTreeSet<T>& set) : m_set(set) {}
const RedBlackTreeSetOrMapImpl<T, Nil>& getImpl() const { return this->m_set.m_impl; }
private:
const ExternalRedBlackTreeSet<T>& m_set;
};
namespace SetTest {
using Impl = RedBlackTreeSetOrMapImpl<State::ElementType, Nil>;
using ImplTester = RedBlackTreeSetOrMapImplTester<State::ElementType, Nil>;
using Set = ExternalRedBlackTreeSet<State::ElementType>;
using SetTester = ExternalRedBlackTreeSetTester<State::ElementType>;
using StackTester = ExternalStackTester<ImplTester::Index>;
TEST(ExternalRedBlackTreeSet, ZeroArgConstructor) {
Set set;
ASSERT_EQ(set.getCapacity(), 0);
ASSERT_EQ(set.getSize(), 0);
}
TEST(ExternalRedBlackTreeSet, TypedStorageConstructor) {
ImplTester::Node nodes[State::capacity];
ImplTester::Index freeNodes[State::capacity];
Set set(nodes, freeNodes, State::capacity);
SetTester setTester(set);
ImplTester implTester(setTester.getImpl());
ASSERT_EQ(implTester.getNodes().getElements(), nodes);
StackTester stackTester(implTester.getFreeNodes());
ASSERT_EQ(stackTester.getItems().getElements(), freeNodes);
ASSERT_EQ(set.getCapacity(), FwSizeType(State::capacity));
ASSERT_EQ(set.getSize(), 0);
}
TEST(ExternalRedBlackTreeSet, UntypedStorageConstructor) {
constexpr auto alignment = Set::getByteArrayAlignment();
constexpr auto byteArraySize = Set::getByteArraySize(State::capacity);
alignas(alignment) U8 bytes[byteArraySize];
Set set(ByteArray(&bytes[0], sizeof bytes), State::capacity);
SetTester setTester(set);
ImplTester implTester(setTester.getImpl());
ASSERT_EQ(implTester.getNodes().getElements(), reinterpret_cast<Impl::Node*>(bytes));
ASSERT_EQ(set.getCapacity(), FwSizeType(State::capacity));
ASSERT_EQ(set.getSize(), 0);
}
TEST(ExternalRedBlackTreeSet, CopyConstructor) {
ImplTester::Node nodes[State::capacity];
ImplTester::Index freeNodes[State::capacity];
// Call the constructor providing backing storage
Set set1(nodes, freeNodes, State::capacity);
// Insert an item
const State::ElementType e = 42;
const auto status = set1.insert(e);
ASSERT_EQ(status, Success::SUCCESS);
// Call the copy constructor
Set set2(set1);
SetTester setTester1(set1);
SetTester setTester2(set2);
ImplTester implTester1(setTester1.getImpl());
ImplTester implTester2(setTester2.getImpl());
ASSERT_EQ(implTester2.getNodes().getElements(), nodes);
ASSERT_EQ(implTester2.getNodes().getSize(), FwSizeType(State::capacity));
StackTester stackTester(implTester2.getFreeNodes());
ASSERT_EQ(stackTester.getItems().getElements(), freeNodes);
ASSERT_EQ(set2.getSize(), 1);
}
TEST(ExternalRedBlackTreeSet, CopyAssignmentOperator) {
ImplTester::Node nodes[State::capacity];
ImplTester::Index freeNodes[State::capacity];
// Call the constructor providing backing storage
Set set1(nodes, freeNodes, State::capacity);
// Insert an item
const State::ElementType e = 42;
const auto status = set1.insert(e);
ASSERT_EQ(status, Success::SUCCESS);
// Call the default constructor
Set set2;
ASSERT_EQ(set2.getSize(), 0);
// Call the copy assignment operator
set2 = set1;
ASSERT_EQ(set2.getSize(), 1);
}
TEST(ExternalRedBlackTreeSet, CopyDataFrom) {
constexpr FwSizeType maxSize = 10;
constexpr FwSizeType smallSize = maxSize / 2;
ImplTester::Node nodes1[maxSize];
ImplTester::Node nodes2[maxSize];
ImplTester::Index freeNodes1[maxSize];
ImplTester::Index freeNodes2[maxSize];
Set s1(nodes1, freeNodes1, maxSize);
// size1 < capacity2
{
Set s2(nodes2, freeNodes2, maxSize);
State::testCopyDataFrom(s1, smallSize, s2);
}
// size1 == size2
{
Set s2(nodes2, freeNodes2, maxSize);
State::testCopyDataFrom(s1, maxSize, s2);
}
// size1 > size2
{
Set s2(nodes2, freeNodes2, smallSize);
State::testCopyDataFrom(s1, maxSize, s2);
}
}
TEST(ExternalRedBlackTreeSetScenarios, Clear) {
ImplTester::Node nodes[State::capacity];
ImplTester::Index freeNodes[State::capacity];
Set set(nodes, freeNodes, State::capacity);
State state(set);
Scenarios::clear(state);
}
TEST(ExternalRedBlackTreeSetScenarios, Find) {
ImplTester::Node nodes[State::capacity];
ImplTester::Index freeNodes[State::capacity];
Set set(nodes, freeNodes, State::capacity);
State state(set);
Scenarios::find(state);
}
TEST(ExternalRedBlackTreeSetScenarios, FindExisting) {
ImplTester::Node nodes[State::capacity];
ImplTester::Index freeNodes[State::capacity];
Set set(nodes, freeNodes, State::capacity);
State state(set);
Scenarios::findExisting(state);
}
TEST(ExternalRedBlackTreeSetScenarios, InsertExisting) {
ImplTester::Node nodes[State::capacity];
ImplTester::Index freeNodes[State::capacity];
Set set(nodes, freeNodes, State::capacity);
State state(set);
Scenarios::insertExisting(state);
}
TEST(ExternalRedBlackTreeSetScenarios, InsertFull) {
ImplTester::Node nodes[State::capacity];
ImplTester::Index freeNodes[State::capacity];
Set set(nodes, freeNodes, State::capacity);
State state(set);
Scenarios::insertFull(state);
}
TEST(ExternalRedBlackTreeSetScenarios, InsertNotFull) {
ImplTester::Node nodes[State::capacity];
ImplTester::Index freeNodes[State::capacity];
Set set(nodes, freeNodes, State::capacity);
State state(set);
Scenarios::insertNotFull(state);
}
TEST(ExternalRedBlackTreeSetScenarios, Remove) {
ImplTester::Node nodes[State::capacity];
ImplTester::Index freeNodes[State::capacity];
Set set(nodes, freeNodes, State::capacity);
State state(set);
Scenarios::remove(state);
}
TEST(ExternalRedBlackTreeSetScenarios, RemoveExisting) {
ImplTester::Node nodes[State::capacity];
ImplTester::Index freeNodes[State::capacity];
Set set(nodes, freeNodes, State::capacity);
State state(set);
Scenarios::removeExisting(state);
}
TEST(ExternalRedBlackTreeSetScenarios, Random) {
ImplTester::Node nodes[State::capacity];
ImplTester::Index freeNodes[State::capacity];
Set set(nodes, freeNodes, State::capacity);
State state(set);
Scenarios::random(Fw::String("ExternalRedBlackTreeSetRandom"), state, 1000);
}
} // namespace SetTest
} // namespace Fw

View File

@ -5,22 +5,12 @@
// ======================================================================
#include "Fw/DataStructures/ExternalStack.hpp"
#include "Fw/DataStructures/test/ut/ExternalStackTester.hpp"
#include "Fw/DataStructures/test/ut/STest/StackTestRules.hpp"
#include "Fw/DataStructures/test/ut/STest/StackTestScenarios.hpp"
namespace Fw {
template <typename T>
class ExternalStackTester {
public:
ExternalStackTester<T>(const ExternalStack<T>& stack) : m_stack(stack) {}
const ExternalArray<T> getItems() const { return this->m_stack.m_items; }
private:
const ExternalStack<T>& m_stack;
};
namespace StackTest {
using TestStack = ExternalStack<State::ItemType>;

View File

@ -0,0 +1,27 @@
// ======================================================================
// \title ExternalStackTester.hpp
// \author bocchino
// \brief Tester class for ExternalStack
// ======================================================================
#ifndef Fw_ExternalStackTester_HPP
#define Fw_ExternalStackTester_HPP
#include "Fw/DataStructures/ExternalStack.hpp"
namespace Fw {
template <typename T>
class ExternalStackTester {
public:
ExternalStackTester<T>(const ExternalStack<T>& stack) : m_stack(stack) {}
const ExternalArray<T> getItems() const { return this->m_stack.m_items; }
private:
const ExternalStack<T>& m_stack;
};
} // namespace Fw
#endif

View File

@ -0,0 +1,158 @@
// ======================================================================
// \title RedBlackTreeMapTest.cpp
// \author bocchino
// \brief cpp file for RedBlackTreeMap tests
// ======================================================================
#include "Fw/DataStructures/RedBlackTreeMap.hpp"
#include "STest/STest/Pick/Pick.hpp"
#include "Fw/DataStructures/RedBlackTreeMap.hpp"
#include "Fw/DataStructures/test/ut/RedBlackTreeSetOrMapImplTester.hpp"
#include "Fw/DataStructures/test/ut/STest/MapTestRules.hpp"
#include "Fw/DataStructures/test/ut/STest/MapTestScenarios.hpp"
namespace Fw {
template <typename K, typename V, FwSizeType C>
class RedBlackTreeMapTester {
public:
using Nodes = typename RedBlackTreeMap<K, V, C>::Node;
using FreeNodes = typename RedBlackTreeMap<K, V, C>::FreeNodes;
RedBlackTreeMapTester<K, V, C>(RedBlackTreeMap<K, V, C>& map) : m_map(map) {}
const ExternalRedBlackTreeMap<K, V>& getExtMap() const { return this->m_map.m_extMap; }
ExternalRedBlackTreeMap<K, V>& getExtMap() { return this->m_map.m_extMap; }
const Nodes& getNodes() const { return this->m_map.m_nodes; }
const FreeNodes& getFreeNodes() const { return this->m_map.m_freeNodes; }
private:
RedBlackTreeMap<K, V, C>& m_map;
};
namespace MapTest {
using Entry = SetOrMapImplEntry<State::KeyType, State::ValueType>;
using ImplTester = RedBlackTreeSetOrMapImplTester<State::KeyType, State::ValueType>;
using Map = RedBlackTreeMap<State::KeyType, State::ValueType, State::capacity>;
using MapTester = RedBlackTreeMapTester<State::KeyType, State::ValueType, State::capacity>;
TEST(RedBlackTreeMap, ZeroArgConstructor) {
Map map;
ASSERT_EQ(map.getCapacity(), FwSizeType(State::capacity));
ASSERT_EQ(map.getSize(), 0);
}
TEST(RedBlackTreeMap, CopyConstructor) {
Map m1;
// Insert an item
const State::KeyType key = 0;
const State::ValueType value = 42;
const auto status = m1.insert(key, value);
ASSERT_EQ(status, Success::SUCCESS);
// Call the copy constructor
Map m2(m1);
ASSERT_EQ(m2.getSize(), 1);
}
TEST(RedBlackTreeMap, CopyAssignmentOperator) {
Map m1;
// Insert an item
const State::KeyType key = 0;
State::ValueType value = 42;
auto status = m1.insert(key, value);
ASSERT_EQ(status, Success::SUCCESS);
// Call the default constructor
Map m2;
ASSERT_EQ(m2.getSize(), 0);
// Call the copy assignment operator
m2 = m1;
ASSERT_EQ(m2.getSize(), 1);
value = 0;
status = m2.find(key, value);
ASSERT_EQ(status, Success::SUCCESS);
ASSERT_EQ(value, 42);
}
TEST(RedBlackTreeMap, CopyDataFrom) {
constexpr FwSizeType maxSize = State::capacity;
constexpr FwSizeType smallSize = maxSize / 2;
Map m1;
// size1 < capacity2
{
Map m2;
State::testCopyDataFrom(m1, smallSize, m2);
}
// size1 == capacity2
{
Map m2;
State::testCopyDataFrom(m1, maxSize, m2);
}
// size1 > capacity2
{
RedBlackTreeMap<State::KeyType, State::ValueType, smallSize> m2;
State::testCopyDataFrom(m1, maxSize, m2);
}
}
TEST(RedBlackTreeMapScenarios, Clear) {
Map map;
State state(map);
Scenarios::clear(state);
}
TEST(RedBlackTreeMapScenarios, Find) {
Map map;
State state(map);
Scenarios::find(state);
}
TEST(RedBlackTreeMapScenarios, FindExisting) {
Map map;
State state(map);
Scenarios::findExisting(state);
}
TEST(RedBlackTreeMapScenarios, InsertExisting) {
Map map;
State state(map);
Scenarios::insertExisting(state);
}
TEST(RedBlackTreeMapScenarios, InsertFull) {
Map map;
State state(map);
Scenarios::insertFull(state);
}
TEST(RedBlackTreeMapScenarios, InsertNotFull) {
Map map;
State state(map);
Scenarios::insertNotFull(state);
}
TEST(RedBlackTreeMapScenarios, Remove) {
Map map;
State state(map);
Scenarios::remove(state);
}
TEST(RedBlackTreeMapScenarios, RemoveExisting) {
Map map;
State state(map);
Scenarios::removeExisting(state);
}
TEST(RedBlackTreeMapScenarios, Random) {
Map map;
State state(map);
Scenarios::random(Fw::String("RedBlackTreeMapRandom"), state, 1000);
}
} // namespace MapTest
} // namespace Fw

View File

@ -0,0 +1,380 @@
// ======================================================================
// \title RedBlackTreeSetOrMapImplTest.cpp
// \author bocchino
// \brief cpp file for RedBlackTreeSetOrMapImpl tests
// ======================================================================
#include <gtest/gtest.h>
#include "Fw/DataStructures/RedBlackTreeSetOrMapImpl.hpp"
#include "STest/STest/Pick/Pick.hpp"
#include "Fw/DataStructures/test/ut/ExternalStackTester.hpp"
#include "Fw/DataStructures/test/ut/RedBlackTreeSetOrMapImplTester.hpp"
#include "Fw/DataStructures/test/ut/STest/RedBlackTreeSetOrMapImplTestRules.hpp"
#include "Fw/DataStructures/test/ut/STest/RedBlackTreeSetOrMapImplTestScenarios.hpp"
namespace Fw {
namespace RedBlackTreeSetOrMapImplTest {
using ImplTester = RedBlackTreeSetOrMapImplTester<State::KeyType, State::ValueType>;
TEST(RedBlackTreeSetOrMapImpl, ZeroArgConstructor) {
State::Impl impl;
ASSERT_EQ(impl.getCapacity(), 0U);
ASSERT_EQ(impl.getSize(), 0U);
}
TEST(RedBlackTreeSetOrMapImpl, TypedStorageConstructor) {
ImplTester::Node nodes[State::capacity];
ImplTester::Index freeNodes[State::capacity];
State::Impl impl(nodes, freeNodes, State::capacity);
State state(impl);
ASSERT_EQ(state.tester.getNodes().getElements(), nodes);
ExternalStackTester<ImplTester::Index> stackTester(state.tester.getFreeNodes());
ASSERT_EQ(stackTester.getItems().getElements(), freeNodes);
ASSERT_EQ(impl.getCapacity(), FwSizeType(State::capacity));
ASSERT_EQ(impl.getSize(), 0U);
}
TEST(RedBlackTreeSetOrMapImpl, UntypedStorageConstructor) {
constexpr auto alignment = State::Impl::getByteArrayAlignment();
constexpr auto byteArraySize = State::Impl::getByteArraySize(State::capacity);
alignas(alignment) U8 bytes[byteArraySize];
State::Impl impl(ByteArray(&bytes[0], sizeof bytes), State::capacity);
State::Tester tester(impl);
ASSERT_EQ(tester.getNodes().getElements(), reinterpret_cast<ImplTester::Node*>(bytes));
ASSERT_EQ(impl.getCapacity(), FwSizeType(State::capacity));
ASSERT_EQ(impl.getSize(), 0U);
}
TEST(RedBlackTreeSetOrMapImpl, CopyConstructor) {
ImplTester::Node nodes[State::capacity];
ImplTester::Index freeNodes[State::capacity];
// Call the constructor providing backing storage
State::Impl impl1(nodes, freeNodes, State::capacity);
// Insert an item
const State::KeyType key = 0;
const State::ValueType value = 42;
const auto status = impl1.insert(key, value);
ASSERT_EQ(status, Success::SUCCESS);
// Call the copy constructor
State::Impl impl2(impl1);
State::Tester tester1(impl1);
State::Tester tester2(impl2);
ASSERT_EQ(tester2.getNodes().getElements(), nodes);
ASSERT_EQ(tester2.getNodes().getSize(), FwSizeType(State::capacity));
ExternalStackTester<ImplTester::Index> stackTester(tester2.getFreeNodes());
ASSERT_EQ(stackTester.getItems().getElements(), freeNodes);
ASSERT_EQ(impl2.getSize(), 1U);
}
TEST(RedBlackTreeSetOrMapImpl, CopyAssignmentOperator) {
ImplTester::Node nodes[State::capacity];
ImplTester::Index freeNodes[State::capacity];
// Call the constructor providing backing storage
State::Impl impl1(nodes, freeNodes, State::capacity);
// Insert an item
const State::KeyType key = 0;
const State::ValueType value = 42;
const auto status = impl1.insert(key, value);
ASSERT_EQ(status, Success::SUCCESS);
// Call the default constructor
State::Impl impl2;
ASSERT_EQ(impl2.getSize(), 0U);
// Call the copy assignment operator
impl2 = impl1;
ASSERT_EQ(impl2.getSize(), 1U);
}
TEST(ArraySetOrMapImpl, IteratorConstruction) {
State::Impl impl;
State::Impl::ConstIterator it(impl);
}
TEST(RedBlackTreeSetOrMapImpl, IteratorComparison) {
// Test comparison in default case
State::Impl::ConstIterator it1;
State::Impl::ConstIterator it2;
ASSERT_TRUE(it1.compareEqual(it2));
}
TEST(RedBlackTreeSetOrMapImplScenarios, Clear) {
State::Tester::Node nodes[State::capacity];
State::Tester::Index freeNodes[State::capacity];
State::Impl impl(nodes, freeNodes, State::capacity);
State state(impl);
Rules::insertNotFull.apply(state);
ASSERT_EQ(state.impl.getSize(), 1U);
Rules::clear.apply(state);
ASSERT_EQ(state.impl.getSize(), 0U);
}
TEST(RedBlackTreeSetOrMapImplScenarios, Find) {
State::Tester::Node nodes[State::capacity];
State::Tester::Index freeNodes[State::capacity];
State::Impl impl(nodes, freeNodes, State::capacity);
State state(impl);
Rules::find.apply(state);
state.useStoredKey = true;
Rules::insertNotFull.apply(state);
Rules::find.apply(state);
}
TEST(RedBlackTreeSetOrMapImplScenarios, FindExisting) {
State::Tester::Node nodes[State::capacity];
State::Tester::Index freeNodes[State::capacity];
State::Impl impl(nodes, freeNodes, State::capacity);
State state(impl);
Rules::insertNotFull.apply(state);
Rules::findExisting.apply(state);
}
TEST(RedBlackTreeSetOrMapImplScenarios, InsertExisting) {
State::Tester::Node nodes[State::capacity];
State::Tester::Index freeNodes[State::capacity];
State::Impl impl(nodes, freeNodes, State::capacity);
State state(impl);
Rules::insertNotFull.apply(state);
Rules::insertExisting.apply(state);
}
TEST(RedBlackTreeSetOrMapImplScenarios, InsertFull) {
State::Tester::Node nodes[State::capacity];
State::Tester::Index freeNodes[State::capacity];
State::Impl impl(nodes, freeNodes, State::capacity);
State state(impl);
state.useStoredKey = true;
for (FwSizeType i = 0; i < State::capacity; i++) {
state.storedKey = static_cast<State::KeyType>(i);
Rules::insertNotFull.apply(state);
}
state.useStoredKey = false;
Rules::insertFull.apply(state);
}
TEST(RedBlackTreeSetOrMapImplScenarios, InsertNotFull) {
State::Tester::Node nodes[State::capacity];
State::Tester::Index freeNodes[State::capacity];
State::Impl impl(nodes, freeNodes, State::capacity);
State state(impl);
const FwSizeType n = 30;
for (FwSizeType i = 0; i < n; i++) {
Rules::insertNotFull.apply(state);
}
state.tester.printTree();
std::cout << "size is " << impl.getSize() << "\n";
state.tester.printBlackHeight();
}
TEST(RedBlackTreeSetOrMapImplScenarios, RemoveRoot) {
State::Tester::Node nodes[State::capacity];
State::Tester::Index freeNodes[State::capacity];
State::Impl impl(nodes, freeNodes, State::capacity);
State state(impl);
state.useStoredKey = true;
Rules::insertNotFull.apply(state);
std::cout << "Before:\n";
state.tester.printTree();
std::cout << "size is " << impl.getSize() << "\n";
Rules::remove.apply(state);
std::cout << "After:\n";
state.tester.printTree();
std::cout << "size is " << impl.getSize() << "\n";
}
TEST(RedBlackTreeSetOrMapImplScenarios, RemoveRedLeaf) {
State::Tester::Node nodes[State::capacity];
State::Tester::Index freeNodes[State::capacity];
State::Impl impl(nodes, freeNodes, State::capacity);
State state(impl);
state.useStoredKey = true;
Rules::insertNotFull.apply(state);
state.storedKey = 1;
Rules::insertNotFull.apply(state);
std::cout << "Before:\n";
state.tester.printTree();
std::cout << "size is " << impl.getSize() << "\n";
Rules::remove.apply(state);
std::cout << "After:\n";
state.tester.printTree();
std::cout << "size is " << impl.getSize() << "\n";
}
TEST(RedBlackTreeSetOrMapImplScenarios, RemoveNodeWithOneChildAtRoot) {
State::Tester::Node nodes[State::capacity];
State::Tester::Index freeNodes[State::capacity];
State::Impl impl(nodes, freeNodes, State::capacity);
State state(impl);
state.useStoredKey = true;
for (FwSizeType i = 0; i < 2; i++) {
state.storedKey = static_cast<State::KeyType>(i);
Rules::insertNotFull.apply(state);
}
std::cout << "Before:\n";
state.tester.printTree();
std::cout << "size is " << impl.getSize() << "\n";
state.storedKey = 0;
Rules::remove.apply(state);
std::cout << "After:\n";
state.tester.printTree();
std::cout << "size is " << impl.getSize() << "\n";
}
TEST(RedBlackTreeSetOrMapImplScenarios, RemoveNodeWithOneChildAwayFromRoot) {
State::Tester::Node nodes[State::capacity];
State::Tester::Index freeNodes[State::capacity];
State::Impl impl(nodes, freeNodes, State::capacity);
State state(impl);
state.useStoredKey = true;
for (FwSizeType i = 0; i < 6; i++) {
state.storedKey = static_cast<State::KeyType>(i);
Rules::insertNotFull.apply(state);
}
std::cout << "Before:\n";
state.tester.printTree();
std::cout << "size is " << impl.getSize() << "\n";
state.storedKey = 4;
Rules::remove.apply(state);
std::cout << "After:\n";
state.tester.printTree();
std::cout << "size is " << impl.getSize() << "\n";
}
TEST(RedBlackTreeSetOrMapImplScenarios, RemoveNodeWithTwoChildren) {
State::Tester::Node nodes[State::capacity];
State::Tester::Index freeNodes[State::capacity];
State::Impl impl(nodes, freeNodes, State::capacity);
State state(impl);
state.useStoredKey = true;
for (FwSizeType i = 0; i < 3; i++) {
state.storedKey = static_cast<State::KeyType>(i);
Rules::insertNotFull.apply(state);
}
std::cout << "Before:\n";
state.tester.printTree();
std::cout << "size is " << impl.getSize() << "\n";
state.storedKey = 1;
Rules::remove.apply(state);
std::cout << "After:\n";
state.tester.printTree();
std::cout << "size is " << impl.getSize() << "\n";
}
TEST(RedBlackTreeSetOrMapImplScenarios, RemoveBlackLeafWithRedDistantNephew) {
State::Tester::Node nodes[State::capacity];
State::Tester::Index freeNodes[State::capacity];
State::Impl impl(nodes, freeNodes, State::capacity);
State state(impl);
state.useStoredKey = true;
for (FwSizeType i = 0; i < 10; i++) {
state.storedKey = static_cast<State::KeyType>(i);
Rules::insertNotFull.apply(state);
}
std::cout << "Before:\n";
state.tester.printTree();
std::cout << "size is " << impl.getSize() << "\n";
state.storedKey = 6;
Rules::remove.apply(state);
std::cout << "After:\n";
state.tester.printTree();
std::cout << "size is " << impl.getSize() << "\n";
}
TEST(RedBlackTreeSetOrMapImplScenarios, RemoveBlackLeafWithRedCloseNephew) {
State::Tester::Node nodes[State::capacity];
State::Tester::Index freeNodes[State::capacity];
State::Impl impl(nodes, freeNodes, State::capacity);
State state(impl);
state.useStoredKey = true;
const State::KeyType keys[] = {10313, 13047, 30597, 41133, 11108, 44775, 25209, 12493, 9954, 37137,
55775, 43881, 45994, 34609, 58674, 16217, 20766, 37020, 26979, 42589,
34189, 54346, 32929, 41537, 14284, 54076, 19044, 61246, 63806, 14754};
const FwSizeType numKeys = FW_NUM_ARRAY_ELEMENTS(keys);
for (FwSizeType i = 0; i < numKeys; i++) {
state.storedKey = keys[i];
Rules::insertNotFull.apply(state);
}
std::cout << "Before:\n";
state.tester.printTree();
std::cout << "size is " << impl.getSize() << "\n";
state.storedKey = 19044;
Rules::remove.apply(state);
std::cout << "After:\n";
state.tester.printTree();
std::cout << "size is " << impl.getSize() << "\n";
}
TEST(RedBlackTreeSetOrMapImplScenarios, RemoveBlackLeafWithRedParent) {
State::Tester::Node nodes[State::capacity];
State::Tester::Index freeNodes[State::capacity];
State::Impl impl(nodes, freeNodes, State::capacity);
State state(impl);
state.useStoredKey = true;
for (FwSizeType i = 0; i < 6; i++) {
state.storedKey = static_cast<State::KeyType>(i);
Rules::insertNotFull.apply(state);
}
state.storedKey = 4;
Rules::remove.apply(state);
std::cout << "Before:\n";
state.tester.printTree();
std::cout << "size is " << impl.getSize() << "\n";
state.storedKey = 2;
Rules::remove.apply(state);
std::cout << "After:\n";
state.tester.printTree();
std::cout << "size is " << impl.getSize() << "\n";
}
TEST(RedBlackTreeSetOrMapImplScenarios, RemoveBlackLeafWithRedSibling) {
State::Tester::Node nodes[State::capacity];
State::Tester::Index freeNodes[State::capacity];
State::Impl impl(nodes, freeNodes, State::capacity);
State state(impl);
state.useStoredKey = true;
for (FwSizeType i = 0; i < 6; i++) {
state.storedKey = static_cast<State::KeyType>(i);
Rules::insertNotFull.apply(state);
}
state.storedKey = 4;
Rules::remove.apply(state);
std::cout << "Before:\n";
state.tester.printTree();
std::cout << "size is " << impl.getSize() << "\n";
state.storedKey = 0;
Rules::remove.apply(state);
std::cout << "After:\n";
state.tester.printTree();
std::cout << "size is " << impl.getSize() << "\n";
}
TEST(RedBlackTreeSetOrMapImplScenarios, RemoveExisting) {
State::Tester::Node nodes[State::capacity];
State::Tester::Index freeNodes[State::capacity];
State::Impl impl(nodes, freeNodes, State::capacity);
State state(impl);
const FwSizeType m = 10;
const FwSizeType n = 10;
for (FwSizeType i = 0; i < m; i++) {
for (FwSizeType j = 0; j < n; j++) {
Rules::insertNotFull.apply(state);
}
for (FwSizeType j = 0; j < n / 2; j++) {
Rules::removeExisting.apply(state);
}
}
}
TEST(RedBlackTreeSetOrMapImplScenarios, Random) {
State::Tester::Node nodes[State::capacity];
State::Tester::Index freeNodes[State::capacity];
State::Impl impl(nodes, freeNodes, State::capacity);
State state(impl);
Scenarios::random(Fw::String("RedBlackTreeSetOrMapImplRandom"), state, 1000);
}
} // namespace RedBlackTreeSetOrMapImplTest
} // namespace Fw

View File

@ -0,0 +1,245 @@
// ======================================================================
// \title RedBlackTreeSetOrMapImplTester.hpp
// \author bocchino
// \brief Class template for access to RedBlackTreeSetOrMapImpl members
// ======================================================================
#ifndef Fw_RedBlackTreeSetOrMapImplTester_HPP
#define Fw_RedBlackTreeSetOrMapImplTester_HPP
#include <gtest/gtest.h>
#include <ostream>
#include "Fw/DataStructures/RedBlackTreeSetOrMapImpl.hpp"
#include "STest/STest/Pick/Pick.hpp"
namespace Fw {
template <typename KE, typename VN>
class RedBlackTreeSetOrMapImplTester {
public:
using Impl = RedBlackTreeSetOrMapImpl<KE, VN>;
using Color = typename Impl::Color;
using Direction = typename Impl::Direction;
using FreeNodes = typename Impl::FreeNodes;
using Index = typename Impl::Index;
using Node = typename Impl::Node;
using Nodes = typename Impl::Nodes;
RedBlackTreeSetOrMapImplTester<KE, VN>(const Impl& impl) : m_impl(impl) {
const auto capacity = this->m_impl.getCapacity();
this->blackHeights.setStorage(new FwSizeType[capacity], capacity);
}
~RedBlackTreeSetOrMapImplTester<KE, VN>() {
auto* const elements = this->blackHeights.getElements();
if (elements != nullptr) {
delete[] elements;
}
}
const Nodes& getNodes() const { return this->m_impl.m_nodes; }
const FreeNodes& getFreeNodes() const { return this->m_impl.m_freeNodes; }
Index getRoot() const { return this->m_impl.m_root; }
// Check properties of the tree
void checkProperties() {
this->checkBstProperty();
this->checkRbtProperties();
}
// Check the BST property of the tree
void checkBstProperty() const {
const auto capacity = this->m_impl.getCapacity();
auto it = this->m_impl.begin();
FwSizeType size = 0;
for (FwSizeType i = 0; i < capacity; i++) {
if (!it.isInRange()) {
break;
}
const KE key1 = it.getEntry().getKey();
size++;
it.increment();
if (!it.isInRange()) {
break;
}
const KE key2 = it.getEntry().getKey();
ASSERT_LT(key1, key2);
}
ASSERT_EQ(size, this->m_impl.getSize());
}
// Check the red-black tree properties of the tree. Return the black height.
void checkRbtProperties() {
const auto& nodes = this->m_impl.m_nodes;
auto node = this->m_impl.getOuterNodeUnder(this->m_impl.m_root, Direction::LEFT);
const auto capacity = this->m_impl.getCapacity();
bool done = (capacity > 0);
for (FwSizeType i = 0; i < capacity; i++) {
if (node == Node::NONE) {
done = true;
break;
}
const auto rightChild = nodes[node].getChild(Direction::RIGHT);
if (rightChild != Node::NONE) {
// There is a right child. Go to the leftmost node under that child.
node = this->m_impl.getOuterNodeUnder(rightChild, Direction::LEFT);
} else {
// There is no right child. Go upwards until we pass through a left child
// or we hit the root.
for (FwSizeType j = 0; j < capacity; j++) {
this->checkForRedViolation(node);
this->updateBlackHeight(node);
const auto previousNode = node;
node = nodes[node].m_parent;
if ((node == Node::NONE) or (nodes[node].getChild(Direction::LEFT) == previousNode)) {
break;
}
}
}
}
ASSERT_TRUE(done);
}
// Get the black height of a node
FwSizeType getBlackHeight(Index node) const { return (node == Node::NONE) ? 1 : this->blackHeights[node]; }
// Check for a red violation at a node
void checkForRedViolation(Index node) const {
if (this->m_impl.getNodeColor(node) == Color::RED) {
const auto& nodes = this->m_impl.m_nodes;
const auto leftChild = nodes[node].getChild(Direction::LEFT);
ASSERT_NE(this->m_impl.getNodeColor(leftChild), Color::RED)
<< "Red child violation at left child\n"
<< " node index is " << node << "\n"
<< " node key is " << nodes[node].m_entry.getKeyOrElement() << "\n"
<< " left child index is " << leftChild << "\n"
<< " left child key is " << nodes[leftChild].m_entry.getKeyOrElement() << "\n";
const auto rightChild = nodes[node].getChild(Direction::RIGHT);
ASSERT_NE(this->m_impl.getNodeColor(rightChild), Color::RED)
<< "Red child violation at right child\n"
<< " node index is " << node << "\n"
<< " node key is " << nodes[node].m_entry.getKeyOrElement() << "\n"
<< " right child index is " << rightChild << "\n"
<< " right child key is " << nodes[rightChild].m_entry.getKeyOrElement() << "\n";
}
}
// Update the black height of a node, after visiting all its descendants.
// Check for a black height violation.
void updateBlackHeight(Index node) {
const auto& nodes = this->m_impl.m_nodes;
if (node != Node::NONE) {
const auto leftChild = nodes[node].getChild(Direction::LEFT);
const auto leftHeight = getBlackHeight(leftChild);
const auto rightChild = nodes[node].getChild(Direction::RIGHT);
const auto rightHeight = getBlackHeight(rightChild);
ASSERT_EQ(leftHeight, rightHeight) << "Black height violation at node " << node << "\n"
<< " left child index is " << leftChild << "\n"
<< " right child index is " << rightChild << "\n";
const FwSizeType nodeHeight = (this->m_impl.getNodeColor(node) == Color::BLACK) ? 1 : 0;
const FwSizeType blackHeight = leftHeight + nodeHeight;
this->blackHeights[node] = blackHeight;
}
}
// Print the black height
void printBlackHeight() { std::cout << "black height is " << getBlackHeight(this->m_impl.m_root) << "\n"; }
// Print the tree
void printTree() {
auto node = this->m_impl.m_root;
auto child = Node::NONE;
const auto capacity = this->m_impl.getCapacity();
I32 indent = 0;
constexpr I32 indentIncrement = 2;
const FwSizeType loopBound = 3 * capacity;
for (FwSizeType i = 0; i < loopBound; i++) {
if (node == Node::NONE) {
break;
}
const auto& nodeObject = this->m_impl.m_nodes[node];
const auto leftChild = nodeObject.m_left;
const auto rightChild = nodeObject.m_right;
if (child == Node::NONE) {
this->printNode(indent, node);
if (leftChild != Node::NONE) {
indent += indentIncrement;
node = leftChild;
} else if (rightChild != Node::NONE) {
indent += indentIncrement;
node = rightChild;
} else {
indent -= indentIncrement;
child = node;
node = nodeObject.m_parent;
}
} else if ((child == leftChild) && (rightChild != Node::NONE)) {
indent += indentIncrement;
node = rightChild;
child = Node::NONE;
} else {
indent -= indentIncrement;
child = node;
node = nodeObject.m_parent;
}
}
}
// Print a node
void printNode(I32 indent, Index node) {
for (I32 i = 0; i < indent; i++) {
std::cout << " ";
}
if (node == Node::NONE) {
std::cout << "NONE\n";
} else {
const auto& nodeObject = this->m_impl.m_nodes[node];
const auto parent = nodeObject.m_parent;
if (parent != Node::NONE) {
const auto parentDirection = this->m_impl.getDirectionFromParent(node);
std::cout << directionToString(parentDirection) << " ";
}
Fw::String parentStr;
indexToString(parent, parentStr);
std::cout << "Node " << node << " { parent=" << parentStr.toChar()
<< ", key=" << nodeObject.m_entry.getKeyOrElement()
<< ", value=" << nodeObject.m_entry.getValueOrNil()
<< ", color=" << colorToString(nodeObject.m_color) << " }\n";
}
}
// Convert an index to a string
void indexToString(Index node, Fw::StringBase& str) {
if (node == Node::NONE) {
str = "NONE";
} else {
str.format("%" PRI_FwSizeType, node);
}
}
// Convert a color to a string
static const char* colorToString(Color color) { return (color == Color::RED) ? "RED" : "BLACK"; }
// Convert a direction to a string
static const char* directionToString(Direction direction) {
return (direction == Direction::LEFT) ? "LEFT" : "RIGHT";
}
private:
const Impl& m_impl;
// Array for storing black heights
ExternalArray<FwSizeType> blackHeights = {};
};
} // namespace Fw
#endif

View File

@ -0,0 +1,154 @@
// ======================================================================
// \title RedBlackTreeSetTest.cpp
// \author bocchino
// \brief cpp file for RedBlackTreeSet tests
// ======================================================================
#include "Fw/DataStructures/RedBlackTreeSet.hpp"
#include "STest/STest/Pick/Pick.hpp"
#include "Fw/DataStructures/RedBlackTreeSet.hpp"
#include "Fw/DataStructures/test/ut/RedBlackTreeSetOrMapImplTester.hpp"
#include "Fw/DataStructures/test/ut/STest/SetTestRules.hpp"
#include "Fw/DataStructures/test/ut/STest/SetTestScenarios.hpp"
namespace Fw {
template <typename T, FwSizeType C>
class RedBlackTreeSetTester {
public:
using Nodes = typename RedBlackTreeSet<T, C>::Node;
using FreeNodes = typename RedBlackTreeSet<T, C>::FreeNodes;
RedBlackTreeSetTester<T, C>(RedBlackTreeSet<T, C>& map) : m_map(map) {}
const ExternalRedBlackTreeSet<T>& getExtMap() const { return this->m_map.m_extMap; }
ExternalRedBlackTreeSet<T>& getExtMap() { return this->m_map.m_extMap; }
const Nodes& getNodes() const { return this->m_map.m_nodes; }
const FreeNodes& getFreeNodes() const { return this->m_map.m_freeNodes; }
private:
RedBlackTreeSet<T, C>& m_map;
};
namespace SetTest {
using Entry = SetOrMapImplEntry<State::ElementType, Nil>;
using ImplTester = RedBlackTreeSetOrMapImplTester<State::ElementType, Nil>;
using Set = RedBlackTreeSet<State::ElementType, State::capacity>;
using SetTester = RedBlackTreeSetTester<State::ElementType, State::capacity>;
TEST(RedBlackTreeSet, ZeroArgConstructor) {
Set set;
ASSERT_EQ(set.getCapacity(), FwSizeType(State::capacity));
ASSERT_EQ(set.getSize(), 0);
}
TEST(RedBlackTreeSet, CopyConstructor) {
Set s1;
// Insert an item
const State::ElementType e = 42;
const auto status = s1.insert(e);
ASSERT_EQ(status, Success::SUCCESS);
// Call the copy constructor
Set s2(s1);
ASSERT_EQ(s2.getSize(), 1);
}
TEST(RedBlackTreeSet, CopyAssignmentOperator) {
Set s1;
// Insert an item
const State::ElementType e = 42;
auto status = s1.insert(e);
ASSERT_EQ(status, Success::SUCCESS);
// Call the default constructor
Set s2;
ASSERT_EQ(s2.getSize(), 0);
// Call the copy assignment operator
s2 = s1;
ASSERT_EQ(s2.getSize(), 1);
status = s2.find(e);
ASSERT_EQ(status, Success::SUCCESS);
}
TEST(RedBlackTreeSet, CopyDataFrom) {
constexpr FwSizeType maxSize = State::capacity;
constexpr FwSizeType smallSize = maxSize / 2;
Set s1;
// size1 < capacity2
{
Set s2;
State::testCopyDataFrom(s1, smallSize, s2);
}
// size1 == capacity2
{
Set s2;
State::testCopyDataFrom(s1, maxSize, s2);
}
// size1 > capacity2
{
RedBlackTreeSet<State::ElementType, smallSize> s2;
State::testCopyDataFrom(s1, maxSize, s2);
}
}
TEST(RedBlackTreeSetScenarios, Clear) {
Set set;
State state(set);
Scenarios::clear(state);
}
TEST(RedBlackTreeSetScenarios, Find) {
Set set;
State state(set);
Scenarios::find(state);
}
TEST(RedBlackTreeSetScenarios, FindExisting) {
Set set;
State state(set);
Scenarios::findExisting(state);
}
TEST(RedBlackTreeSetScenarios, InsertExisting) {
Set set;
State state(set);
Scenarios::insertExisting(state);
}
TEST(RedBlackTreeSetScenarios, InsertFull) {
Set set;
State state(set);
Scenarios::insertFull(state);
}
TEST(RedBlackTreeSetScenarios, InsertNotFull) {
Set set;
State state(set);
Scenarios::insertNotFull(state);
}
TEST(RedBlackTreeSetScenarios, Remove) {
Set set;
State state(set);
Scenarios::remove(state);
}
TEST(RedBlackTreeSetScenarios, RemoveExisting) {
Set set;
State state(set);
Scenarios::removeExisting(state);
}
TEST(RedBlackTreeSetScenarios, Random) {
Set set;
State state(set);
Scenarios::random(Fw::String("RedBlackTreeSetRandom"), state, 1000);
}
} // namespace SetTest
} // namespace Fw

View File

@ -0,0 +1,35 @@
// ======================================================================
// \title RedBlackTreeSetOrMapImplTestRules.cpp
// \author Rob Bocchino
// \brief cpp file for RedBlackTreeSetOrMapImpl test rules
// ======================================================================
#include "Fw/DataStructures/test/ut/STest/RedBlackTreeSetOrMapImplTestRules.hpp"
namespace Fw {
namespace RedBlackTreeSetOrMapImplTest {
namespace Rules {
Clear clear;
Find find;
FindExisting findExisting;
InsertExisting insertExisting;
InsertFull insertFull;
InsertNotFull insertNotFull;
Remove remove;
RemoveExisting removeExisting;
} // namespace Rules
} // namespace RedBlackTreeSetOrMapImplTest
} // namespace Fw

View File

@ -0,0 +1,199 @@
// ======================================================================
// \title RedBlackTreeSetOrMapImplTestRules.hpp
// \author bocchino
// \brief hpp file for RedBlackTreeSetOrMapImpl test rules
// ======================================================================
#ifndef RedBlackTreeSetOrMapImplTestRules_HPP
#define RedBlackTreeSetOrMapImplTestRules_HPP
#include <gtest/gtest.h>
#include "Fw/DataStructures/test/ut/STest/RedBlackTreeSetOrMapImplTestState.hpp"
#include "STest/STest/Pick/Pick.hpp"
#include "STest/STest/Rule/Rule.hpp"
namespace Fw {
namespace RedBlackTreeSetOrMapImplTest {
using Rule = STest::Rule<State>;
namespace Rules {
struct Clear : public Rule {
Clear() : Rule("Clear") {}
bool precondition(const State& state) { return state.impl.getSize() > 0; }
void action(State& state) {
state.impl.clear();
ASSERT_EQ(state.impl.getSize(), 0U);
state.modelMap.clear();
}
};
struct Find : public Rule {
Find() : Rule("Find") {}
bool precondition(const State& state) { return true; }
void action(State& state) {
const auto key = state.getKey();
State::ValueType value = 0;
const auto status = state.impl.find(key, value);
if (state.modelMapContains(key)) {
ASSERT_EQ(status, Success::SUCCESS);
ASSERT_EQ(value, state.modelMap[key]);
} else {
ASSERT_EQ(status, Success::FAILURE);
}
}
};
struct FindExisting : public Rule {
FindExisting() : Rule("FindExisting") {}
bool precondition(const State& state) { return static_cast<FwSizeType>(state.impl.getSize()) > 0; }
void action(State& state) {
const auto size = state.impl.getSize();
const auto index = STest::Pick::startLength(0, static_cast<U32>(size));
auto it = state.impl.begin();
for (FwSizeType i = 0; i < index; i++) {
ASSERT_TRUE(it.isInRange());
it.increment();
}
ASSERT_TRUE(it.isInRange());
const auto key = it.getEntry().getKeyOrElement();
const auto expectedValue = state.modelMap[key];
State::ValueType value = 0;
const auto status = state.impl.find(key, value);
ASSERT_EQ(status, Success::SUCCESS);
ASSERT_EQ(value, expectedValue);
}
};
struct InsertExisting : public Rule {
InsertExisting() : Rule("InsertExisting") {}
bool precondition(const State& state) { return static_cast<FwSizeType>(state.impl.getSize()) > 0; }
void action(State& state) {
state.tester.checkProperties();
const auto size = state.impl.getSize();
const auto index = STest::Pick::startLength(0, static_cast<U32>(size));
auto it = state.impl.begin();
for (FwSizeType i = 0; i < index; i++) {
ASSERT_TRUE(it.isInRange());
it.increment();
}
ASSERT_TRUE(it.isInRange());
const auto key = it.getEntry().getKeyOrElement();
const auto value = state.getValue();
const auto status = state.impl.insert(key, value);
ASSERT_EQ(status, Success::SUCCESS);
state.modelMap[key] = value;
ASSERT_EQ(state.impl.getSize(), size);
state.tester.checkProperties();
}
};
struct InsertFull : public Rule {
InsertFull() : Rule("InsertFull") {}
bool precondition(const State& state) { return static_cast<FwSizeType>(state.impl.getSize()) >= State::capacity; }
void action(State& state) {
state.tester.checkProperties();
const auto key = state.getKey();
const auto value = state.getValue();
const auto size = state.impl.getSize();
const auto expectedStatus = state.modelMapContains(key) ? Success::SUCCESS : Success::FAILURE;
const auto status = state.impl.insert(key, value);
ASSERT_EQ(status, expectedStatus);
ASSERT_EQ(state.impl.getSize(), size);
state.tester.checkProperties();
}
};
struct InsertNotFull : public Rule {
InsertNotFull() : Rule("InsertNotFull") {}
bool precondition(const State& state) { return static_cast<FwSizeType>(state.impl.getSize()) < State::capacity; }
void action(State& state) {
state.tester.checkProperties();
const auto key = state.getKey();
const auto value = state.getValue();
const auto size = state.impl.getSize();
const auto expectedSize = state.modelMapContains(key) ? size : size + 1;
const auto status = state.impl.insert(key, value);
ASSERT_EQ(status, Success::SUCCESS);
ASSERT_EQ(state.impl.getSize(), expectedSize);
state.modelMap[key] = value;
state.tester.checkProperties();
}
};
struct Remove : public Rule {
Remove() : Rule("Remove") {}
bool precondition(const State& state) { return true; }
void action(State& state) {
state.tester.checkProperties();
const auto size = state.impl.getSize();
ASSERT_EQ(size, state.modelMap.size());
const auto key = state.getKey();
State::ValueType value = 0;
const auto status = state.impl.remove(key, value);
if (state.modelMap.count(key) != 0) {
ASSERT_EQ(status, Success::SUCCESS);
ASSERT_EQ(value, state.modelMap[key]);
ASSERT_EQ(state.impl.getSize(), size - 1);
} else {
ASSERT_EQ(status, Success::FAILURE);
ASSERT_EQ(state.impl.getSize(), size);
}
(void)state.modelMap.erase(key);
ASSERT_EQ(state.impl.getSize(), state.modelMap.size());
state.tester.checkProperties();
}
};
struct RemoveExisting : public Rule {
RemoveExisting() : Rule("RemoveExisting") {}
bool precondition(const State& state) { return static_cast<FwSizeType>(state.impl.getSize()) > 0; }
void action(State& state) {
state.tester.checkProperties();
const auto size = state.impl.getSize();
const auto index = STest::Pick::startLength(0, static_cast<U32>(size));
auto it = state.impl.begin();
for (FwSizeType i = 0; i < index; i++) {
ASSERT_TRUE(it.isInRange());
it.increment();
}
ASSERT_TRUE(it.isInRange());
const auto key = it.getEntry().getKeyOrElement();
const auto expectedValue = state.modelMap[key];
State::ValueType value = 0;
const auto status = state.impl.remove(key, value);
ASSERT_EQ(status, Success::SUCCESS);
ASSERT_EQ(value, expectedValue);
const auto n = state.modelMap.erase(key);
ASSERT_EQ(n, 1U);
ASSERT_EQ(state.impl.getSize(), state.modelMap.size());
state.tester.checkProperties();
}
};
extern Clear clear;
extern Find find;
extern FindExisting findExisting;
extern InsertExisting insertExisting;
extern InsertFull insertFull;
extern InsertNotFull insertNotFull;
extern Remove remove;
extern RemoveExisting removeExisting;
} // namespace Rules
} // namespace RedBlackTreeSetOrMapImplTest
} // namespace Fw
#endif

View File

@ -0,0 +1,33 @@
// ======================================================================
// \title RedBlackTreeSetOrMapImplTestScenarios.cpp
// \author Rob Bocchino
// \brief RedBlackTreeSetOrMapImpl test scenarios
// ======================================================================
#include "Fw/DataStructures/test/ut/STest/RedBlackTreeSetOrMapImplTestScenarios.hpp"
#include "Fw/DataStructures/test/ut/STest/RedBlackTreeSetOrMapImplTestRules.hpp"
#include "STest/Scenario/BoundedScenario.hpp"
#include "STest/Scenario/RandomScenario.hpp"
namespace Fw {
namespace RedBlackTreeSetOrMapImplTest {
namespace Scenarios {
void random(const Fw::StringBase& name, State& state, U32 maxNumSteps) {
Rule* rules[] = {//&Rules::clear,
&Rules::find, &Rules::findExisting, &Rules::insertExisting, &Rules::insertFull,
&Rules::insertNotFull, &Rules::remove, &Rules::removeExisting};
STest::RandomScenario<State> scenario("RandomScenario", rules,
sizeof(rules) / sizeof(STest::RandomScenario<State>*));
STest::BoundedScenario<State> boundedScenario(name.toChar(), scenario, maxNumSteps);
const U32 numSteps = boundedScenario.run(state);
printf("Ran %u steps.\n", numSteps);
}
} // namespace Scenarios
} // namespace RedBlackTreeSetOrMapImplTest
} // namespace Fw

View File

@ -0,0 +1,26 @@
// ======================================================================
// \title RedBlackTreeSetOrMapImplTestScenarios.hpp
// \author Rob Bocchino
// \brief RedBlackTreeSetOrMapImpl test scenarios
// ======================================================================
#ifndef RedBlackTreeSetOrMapImplTestScenarios_HPP
#define RedBlackTreeSetOrMapImplTestScenarios_HPP
#include "Fw/DataStructures/test/ut/STest/RedBlackTreeSetOrMapImplTestState.hpp"
namespace Fw {
namespace RedBlackTreeSetOrMapImplTest {
namespace Scenarios {
void random(const Fw::StringBase& name, State& state, U32 maxNumSteps);
} // namespace Scenarios
} // namespace RedBlackTreeSetOrMapImplTest
} // namespace Fw
#endif

View File

@ -0,0 +1,61 @@
// ======================================================================
// \title RedBlackTreeSetOrMapImplTestState.hpp
// \author bocchino
// \brief hpp file for RedBlackTreeSetOrMapImpl test state
// ======================================================================
#ifndef RedBlackTreeSetOrMapImplTestState_HPP
#define RedBlackTreeSetOrMapImplTestState_HPP
#include <map>
#include "Fw/DataStructures/RedBlackTreeSetOrMapImpl.hpp"
#include "Fw/DataStructures/test/ut/RedBlackTreeSetOrMapImplTester.hpp"
#include "STest/STest/Pick/Pick.hpp"
namespace Fw {
namespace RedBlackTreeSetOrMapImplTest {
struct State {
//! The key type
using KeyType = U16;
//! The value type
using ValueType = U32;
//! The array set or map capacity
static constexpr FwSizeType capacity = 1024;
//! The Impl type
using Impl = RedBlackTreeSetOrMapImpl<KeyType, ValueType>;
//! The Tester type
using Tester = RedBlackTreeSetOrMapImplTester<KeyType, ValueType>;
//! The entry type
using Entry = SetOrMapImplEntry<U16, U32>;
//! Constructor
State(Impl& a_impl) : impl(a_impl), tester(a_impl) {}
//! The array set or map under test
Impl& impl;
//! The tester
Tester tester;
//! The map for modeling correct behavior
std::map<KeyType, ValueType> modelMap;
//! Whether to use the stored key
bool useStoredKey = false;
//! The stored key
KeyType storedKey = 0;
//! Whether to use the stored value
bool useStoredValue = false;
//! The stored value
ValueType storedValue = 0;
//! Get a key
KeyType getKey() const { return useStoredKey ? storedKey : static_cast<KeyType>(STest::Pick::any()); }
//! Get a value
ValueType getValue() const { return useStoredValue ? storedValue : static_cast<ValueType>(STest::Pick::any()); }
//! Check whether the model map contains the specified key
bool modelMapContains(KeyType key) const { return modelMap.count(key) != 0; }
};
} // namespace RedBlackTreeSetOrMapImplTest
} // namespace Fw
#endif