|
|
|
@ -43,294 +43,265 @@ |
|
|
|
* The maximum height of a red-black tree is 2lg (n+1). |
|
|
|
*/ |
|
|
|
|
|
|
|
#include "common/assert.h" |
|
|
|
namespace Common::freebsd { |
|
|
|
|
|
|
|
namespace Common { |
|
|
|
template <typename T> |
|
|
|
class RBHead { |
|
|
|
public: |
|
|
|
[[nodiscard]] T* Root() { |
|
|
|
return rbh_root; |
|
|
|
} |
|
|
|
|
|
|
|
[[nodiscard]] const T* Root() const { |
|
|
|
return rbh_root; |
|
|
|
} |
|
|
|
|
|
|
|
void SetRoot(T* root) { |
|
|
|
rbh_root = root; |
|
|
|
} |
|
|
|
|
|
|
|
[[nodiscard]] bool IsEmpty() const { |
|
|
|
return Root() == nullptr; |
|
|
|
} |
|
|
|
|
|
|
|
private: |
|
|
|
T* rbh_root = nullptr; |
|
|
|
}; |
|
|
|
|
|
|
|
enum class EntryColor { |
|
|
|
Black, |
|
|
|
Red, |
|
|
|
enum class RBColor { |
|
|
|
RB_BLACK = 0, |
|
|
|
RB_RED = 1, |
|
|
|
}; |
|
|
|
|
|
|
|
#pragma pack(push, 4) |
|
|
|
template <typename T> |
|
|
|
class RBEntry { |
|
|
|
public: |
|
|
|
[[nodiscard]] T* Left() { |
|
|
|
return rbe_left; |
|
|
|
} |
|
|
|
constexpr RBEntry() = default; |
|
|
|
|
|
|
|
[[nodiscard]] const T* Left() const { |
|
|
|
return rbe_left; |
|
|
|
[[nodiscard]] constexpr T* Left() { |
|
|
|
return m_rbe_left; |
|
|
|
} |
|
|
|
|
|
|
|
void SetLeft(T* left) { |
|
|
|
rbe_left = left; |
|
|
|
[[nodiscard]] constexpr const T* Left() const { |
|
|
|
return m_rbe_left; |
|
|
|
} |
|
|
|
|
|
|
|
[[nodiscard]] T* Right() { |
|
|
|
return rbe_right; |
|
|
|
constexpr void SetLeft(T* e) { |
|
|
|
m_rbe_left = e; |
|
|
|
} |
|
|
|
|
|
|
|
[[nodiscard]] const T* Right() const { |
|
|
|
return rbe_right; |
|
|
|
[[nodiscard]] constexpr T* Right() { |
|
|
|
return m_rbe_right; |
|
|
|
} |
|
|
|
|
|
|
|
void SetRight(T* right) { |
|
|
|
rbe_right = right; |
|
|
|
[[nodiscard]] constexpr const T* Right() const { |
|
|
|
return m_rbe_right; |
|
|
|
} |
|
|
|
|
|
|
|
[[nodiscard]] T* Parent() { |
|
|
|
return rbe_parent; |
|
|
|
constexpr void SetRight(T* e) { |
|
|
|
m_rbe_right = e; |
|
|
|
} |
|
|
|
|
|
|
|
[[nodiscard]] const T* Parent() const { |
|
|
|
return rbe_parent; |
|
|
|
[[nodiscard]] constexpr T* Parent() { |
|
|
|
return m_rbe_parent; |
|
|
|
} |
|
|
|
|
|
|
|
void SetParent(T* parent) { |
|
|
|
rbe_parent = parent; |
|
|
|
[[nodiscard]] constexpr const T* Parent() const { |
|
|
|
return m_rbe_parent; |
|
|
|
} |
|
|
|
|
|
|
|
[[nodiscard]] bool IsBlack() const { |
|
|
|
return rbe_color == EntryColor::Black; |
|
|
|
constexpr void SetParent(T* e) { |
|
|
|
m_rbe_parent = e; |
|
|
|
} |
|
|
|
|
|
|
|
[[nodiscard]] bool IsRed() const { |
|
|
|
return rbe_color == EntryColor::Red; |
|
|
|
[[nodiscard]] constexpr bool IsBlack() const { |
|
|
|
return m_rbe_color == RBColor::RB_BLACK; |
|
|
|
} |
|
|
|
|
|
|
|
[[nodiscard]] EntryColor Color() const { |
|
|
|
return rbe_color; |
|
|
|
[[nodiscard]] constexpr bool IsRed() const { |
|
|
|
return m_rbe_color == RBColor::RB_RED; |
|
|
|
} |
|
|
|
[[nodiscard]] constexpr RBColor Color() const { |
|
|
|
return m_rbe_color; |
|
|
|
} |
|
|
|
|
|
|
|
void SetColor(EntryColor color) { |
|
|
|
rbe_color = color; |
|
|
|
constexpr void SetColor(RBColor c) { |
|
|
|
m_rbe_color = c; |
|
|
|
} |
|
|
|
|
|
|
|
private: |
|
|
|
T* rbe_left = nullptr; |
|
|
|
T* rbe_right = nullptr; |
|
|
|
T* rbe_parent = nullptr; |
|
|
|
EntryColor rbe_color{}; |
|
|
|
T* m_rbe_left{}; |
|
|
|
T* m_rbe_right{}; |
|
|
|
T* m_rbe_parent{}; |
|
|
|
RBColor m_rbe_color{RBColor::RB_BLACK}; |
|
|
|
}; |
|
|
|
#pragma pack(pop) |
|
|
|
|
|
|
|
template <typename Node> |
|
|
|
[[nodiscard]] RBEntry<Node>& RB_ENTRY(Node* node) { |
|
|
|
return node->GetEntry(); |
|
|
|
} |
|
|
|
template <typename T> |
|
|
|
struct CheckRBEntry { |
|
|
|
static constexpr bool value = false; |
|
|
|
}; |
|
|
|
template <typename T> |
|
|
|
struct CheckRBEntry<RBEntry<T>> { |
|
|
|
static constexpr bool value = true; |
|
|
|
}; |
|
|
|
|
|
|
|
template <typename Node> |
|
|
|
[[nodiscard]] const RBEntry<Node>& RB_ENTRY(const Node* node) { |
|
|
|
return node->GetEntry(); |
|
|
|
} |
|
|
|
template <typename T> |
|
|
|
concept IsRBEntry = CheckRBEntry<T>::value; |
|
|
|
|
|
|
|
template <typename Node> |
|
|
|
[[nodiscard]] Node* RB_PARENT(Node* node) { |
|
|
|
return RB_ENTRY(node).Parent(); |
|
|
|
} |
|
|
|
template <typename T> |
|
|
|
concept HasRBEntry = requires(T& t, const T& ct) { |
|
|
|
{ t.GetRBEntry() } -> std::same_as<RBEntry<T>&>; |
|
|
|
{ ct.GetRBEntry() } -> std::same_as<const RBEntry<T>&>; |
|
|
|
}; |
|
|
|
|
|
|
|
template <typename Node> |
|
|
|
[[nodiscard]] const Node* RB_PARENT(const Node* node) { |
|
|
|
return RB_ENTRY(node).Parent(); |
|
|
|
} |
|
|
|
template <typename T> |
|
|
|
requires HasRBEntry<T> |
|
|
|
class RBHead { |
|
|
|
private: |
|
|
|
T* m_rbh_root = nullptr; |
|
|
|
|
|
|
|
template <typename Node> |
|
|
|
void RB_SET_PARENT(Node* node, Node* parent) { |
|
|
|
return RB_ENTRY(node).SetParent(parent); |
|
|
|
public: |
|
|
|
[[nodiscard]] constexpr T* Root() { |
|
|
|
return m_rbh_root; |
|
|
|
} |
|
|
|
|
|
|
|
template <typename Node> |
|
|
|
[[nodiscard]] Node* RB_LEFT(Node* node) { |
|
|
|
return RB_ENTRY(node).Left(); |
|
|
|
[[nodiscard]] constexpr const T* Root() const { |
|
|
|
return m_rbh_root; |
|
|
|
} |
|
|
|
constexpr void SetRoot(T* root) { |
|
|
|
m_rbh_root = root; |
|
|
|
} |
|
|
|
|
|
|
|
template <typename Node> |
|
|
|
[[nodiscard]] const Node* RB_LEFT(const Node* node) { |
|
|
|
return RB_ENTRY(node).Left(); |
|
|
|
[[nodiscard]] constexpr bool IsEmpty() const { |
|
|
|
return this->Root() == nullptr; |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
template <typename Node> |
|
|
|
void RB_SET_LEFT(Node* node, Node* left) { |
|
|
|
return RB_ENTRY(node).SetLeft(left); |
|
|
|
template <typename T> |
|
|
|
requires HasRBEntry<T> |
|
|
|
[[nodiscard]] constexpr RBEntry<T>& RB_ENTRY(T* t) { |
|
|
|
return t->GetRBEntry(); |
|
|
|
} |
|
|
|
template <typename T> |
|
|
|
requires HasRBEntry<T> |
|
|
|
[[nodiscard]] constexpr const RBEntry<T>& RB_ENTRY(const T* t) { |
|
|
|
return t->GetRBEntry(); |
|
|
|
} |
|
|
|
|
|
|
|
template <typename Node> |
|
|
|
[[nodiscard]] Node* RB_RIGHT(Node* node) { |
|
|
|
return RB_ENTRY(node).Right(); |
|
|
|
template <typename T> |
|
|
|
requires HasRBEntry<T> |
|
|
|
[[nodiscard]] constexpr T* RB_LEFT(T* t) { |
|
|
|
return RB_ENTRY(t).Left(); |
|
|
|
} |
|
|
|
template <typename T> |
|
|
|
requires HasRBEntry<T> |
|
|
|
[[nodiscard]] constexpr const T* RB_LEFT(const T* t) { |
|
|
|
return RB_ENTRY(t).Left(); |
|
|
|
} |
|
|
|
|
|
|
|
template <typename Node> |
|
|
|
[[nodiscard]] const Node* RB_RIGHT(const Node* node) { |
|
|
|
return RB_ENTRY(node).Right(); |
|
|
|
template <typename T> |
|
|
|
requires HasRBEntry<T> |
|
|
|
[[nodiscard]] constexpr T* RB_RIGHT(T* t) { |
|
|
|
return RB_ENTRY(t).Right(); |
|
|
|
} |
|
|
|
template <typename T> |
|
|
|
requires HasRBEntry<T> |
|
|
|
[[nodiscard]] constexpr const T* RB_RIGHT(const T* t) { |
|
|
|
return RB_ENTRY(t).Right(); |
|
|
|
} |
|
|
|
|
|
|
|
template <typename Node> |
|
|
|
void RB_SET_RIGHT(Node* node, Node* right) { |
|
|
|
return RB_ENTRY(node).SetRight(right); |
|
|
|
template <typename T> |
|
|
|
requires HasRBEntry<T> |
|
|
|
[[nodiscard]] constexpr T* RB_PARENT(T* t) { |
|
|
|
return RB_ENTRY(t).Parent(); |
|
|
|
} |
|
|
|
template <typename T> |
|
|
|
requires HasRBEntry<T> |
|
|
|
[[nodiscard]] constexpr const T* RB_PARENT(const T* t) { |
|
|
|
return RB_ENTRY(t).Parent(); |
|
|
|
} |
|
|
|
|
|
|
|
template <typename Node> |
|
|
|
[[nodiscard]] bool RB_IS_BLACK(const Node* node) { |
|
|
|
return RB_ENTRY(node).IsBlack(); |
|
|
|
template <typename T> |
|
|
|
requires HasRBEntry<T> |
|
|
|
constexpr void RB_SET_LEFT(T* t, T* e) { |
|
|
|
RB_ENTRY(t).SetLeft(e); |
|
|
|
} |
|
|
|
template <typename T> |
|
|
|
requires HasRBEntry<T> |
|
|
|
constexpr void RB_SET_RIGHT(T* t, T* e) { |
|
|
|
RB_ENTRY(t).SetRight(e); |
|
|
|
} |
|
|
|
template <typename T> |
|
|
|
requires HasRBEntry<T> |
|
|
|
constexpr void RB_SET_PARENT(T* t, T* e) { |
|
|
|
RB_ENTRY(t).SetParent(e); |
|
|
|
} |
|
|
|
|
|
|
|
template <typename Node> |
|
|
|
[[nodiscard]] bool RB_IS_RED(const Node* node) { |
|
|
|
return RB_ENTRY(node).IsRed(); |
|
|
|
template <typename T> |
|
|
|
requires HasRBEntry<T> |
|
|
|
[[nodiscard]] constexpr bool RB_IS_BLACK(const T* t) { |
|
|
|
return RB_ENTRY(t).IsBlack(); |
|
|
|
} |
|
|
|
template <typename T> |
|
|
|
requires HasRBEntry<T> |
|
|
|
[[nodiscard]] constexpr bool RB_IS_RED(const T* t) { |
|
|
|
return RB_ENTRY(t).IsRed(); |
|
|
|
} |
|
|
|
|
|
|
|
template <typename Node> |
|
|
|
[[nodiscard]] EntryColor RB_COLOR(const Node* node) { |
|
|
|
return RB_ENTRY(node).Color(); |
|
|
|
template <typename T> |
|
|
|
requires HasRBEntry<T> |
|
|
|
[[nodiscard]] constexpr RBColor RB_COLOR(const T* t) { |
|
|
|
return RB_ENTRY(t).Color(); |
|
|
|
} |
|
|
|
|
|
|
|
template <typename Node> |
|
|
|
void RB_SET_COLOR(Node* node, EntryColor color) { |
|
|
|
return RB_ENTRY(node).SetColor(color); |
|
|
|
template <typename T> |
|
|
|
requires HasRBEntry<T> |
|
|
|
constexpr void RB_SET_COLOR(T* t, RBColor c) { |
|
|
|
RB_ENTRY(t).SetColor(c); |
|
|
|
} |
|
|
|
|
|
|
|
template <typename Node> |
|
|
|
void RB_SET(Node* node, Node* parent) { |
|
|
|
auto& entry = RB_ENTRY(node); |
|
|
|
entry.SetParent(parent); |
|
|
|
entry.SetLeft(nullptr); |
|
|
|
entry.SetRight(nullptr); |
|
|
|
entry.SetColor(EntryColor::Red); |
|
|
|
template <typename T> |
|
|
|
requires HasRBEntry<T> |
|
|
|
constexpr void RB_SET(T* elm, T* parent) { |
|
|
|
auto& rb_entry = RB_ENTRY(elm); |
|
|
|
rb_entry.SetParent(parent); |
|
|
|
rb_entry.SetLeft(nullptr); |
|
|
|
rb_entry.SetRight(nullptr); |
|
|
|
rb_entry.SetColor(RBColor::RB_RED); |
|
|
|
} |
|
|
|
|
|
|
|
template <typename Node> |
|
|
|
void RB_SET_BLACKRED(Node* black, Node* red) { |
|
|
|
RB_SET_COLOR(black, EntryColor::Black); |
|
|
|
RB_SET_COLOR(red, EntryColor::Red); |
|
|
|
template <typename T> |
|
|
|
requires HasRBEntry<T> |
|
|
|
constexpr void RB_SET_BLACKRED(T* black, T* red) { |
|
|
|
RB_SET_COLOR(black, RBColor::RB_BLACK); |
|
|
|
RB_SET_COLOR(red, RBColor::RB_RED); |
|
|
|
} |
|
|
|
|
|
|
|
template <typename Node> |
|
|
|
void RB_ROTATE_LEFT(RBHead<Node>* head, Node* elm, Node*& tmp) { |
|
|
|
template <typename T> |
|
|
|
requires HasRBEntry<T> |
|
|
|
constexpr void RB_ROTATE_LEFT(RBHead<T>& head, T* elm, T*& tmp) { |
|
|
|
tmp = RB_RIGHT(elm); |
|
|
|
RB_SET_RIGHT(elm, RB_LEFT(tmp)); |
|
|
|
if (RB_RIGHT(elm) != nullptr) { |
|
|
|
if (RB_SET_RIGHT(elm, RB_LEFT(tmp)); RB_RIGHT(elm) != nullptr) { |
|
|
|
RB_SET_PARENT(RB_LEFT(tmp), elm); |
|
|
|
} |
|
|
|
|
|
|
|
RB_SET_PARENT(tmp, RB_PARENT(elm)); |
|
|
|
if (RB_PARENT(tmp) != nullptr) { |
|
|
|
if (RB_SET_PARENT(tmp, RB_PARENT(elm)); RB_PARENT(tmp) != nullptr) { |
|
|
|
if (elm == RB_LEFT(RB_PARENT(elm))) { |
|
|
|
RB_SET_LEFT(RB_PARENT(elm), tmp); |
|
|
|
} else { |
|
|
|
RB_SET_RIGHT(RB_PARENT(elm), tmp); |
|
|
|
} |
|
|
|
} else { |
|
|
|
head->SetRoot(tmp); |
|
|
|
head.SetRoot(tmp); |
|
|
|
} |
|
|
|
|
|
|
|
RB_SET_LEFT(tmp, elm); |
|
|
|
RB_SET_PARENT(elm, tmp); |
|
|
|
} |
|
|
|
|
|
|
|
template <typename Node> |
|
|
|
void RB_ROTATE_RIGHT(RBHead<Node>* head, Node* elm, Node*& tmp) { |
|
|
|
template <typename T> |
|
|
|
requires HasRBEntry<T> |
|
|
|
constexpr void RB_ROTATE_RIGHT(RBHead<T>& head, T* elm, T*& tmp) { |
|
|
|
tmp = RB_LEFT(elm); |
|
|
|
RB_SET_LEFT(elm, RB_RIGHT(tmp)); |
|
|
|
if (RB_LEFT(elm) != nullptr) { |
|
|
|
if (RB_SET_LEFT(elm, RB_RIGHT(tmp)); RB_LEFT(elm) != nullptr) { |
|
|
|
RB_SET_PARENT(RB_RIGHT(tmp), elm); |
|
|
|
} |
|
|
|
|
|
|
|
RB_SET_PARENT(tmp, RB_PARENT(elm)); |
|
|
|
if (RB_PARENT(tmp) != nullptr) { |
|
|
|
if (RB_SET_PARENT(tmp, RB_PARENT(elm)); RB_PARENT(tmp) != nullptr) { |
|
|
|
if (elm == RB_LEFT(RB_PARENT(elm))) { |
|
|
|
RB_SET_LEFT(RB_PARENT(elm), tmp); |
|
|
|
} else { |
|
|
|
RB_SET_RIGHT(RB_PARENT(elm), tmp); |
|
|
|
} |
|
|
|
} else { |
|
|
|
head->SetRoot(tmp); |
|
|
|
head.SetRoot(tmp); |
|
|
|
} |
|
|
|
|
|
|
|
RB_SET_RIGHT(tmp, elm); |
|
|
|
RB_SET_PARENT(elm, tmp); |
|
|
|
} |
|
|
|
|
|
|
|
template <typename Node> |
|
|
|
void RB_INSERT_COLOR(RBHead<Node>* head, Node* elm) { |
|
|
|
Node* parent = nullptr; |
|
|
|
Node* tmp = nullptr; |
|
|
|
|
|
|
|
while ((parent = RB_PARENT(elm)) != nullptr && RB_IS_RED(parent)) { |
|
|
|
Node* gparent = RB_PARENT(parent); |
|
|
|
if (parent == RB_LEFT(gparent)) { |
|
|
|
tmp = RB_RIGHT(gparent); |
|
|
|
if (tmp && RB_IS_RED(tmp)) { |
|
|
|
RB_SET_COLOR(tmp, EntryColor::Black); |
|
|
|
RB_SET_BLACKRED(parent, gparent); |
|
|
|
elm = gparent; |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
if (RB_RIGHT(parent) == elm) { |
|
|
|
RB_ROTATE_LEFT(head, parent, tmp); |
|
|
|
tmp = parent; |
|
|
|
parent = elm; |
|
|
|
elm = tmp; |
|
|
|
} |
|
|
|
|
|
|
|
RB_SET_BLACKRED(parent, gparent); |
|
|
|
RB_ROTATE_RIGHT(head, gparent, tmp); |
|
|
|
} else { |
|
|
|
tmp = RB_LEFT(gparent); |
|
|
|
if (tmp && RB_IS_RED(tmp)) { |
|
|
|
RB_SET_COLOR(tmp, EntryColor::Black); |
|
|
|
RB_SET_BLACKRED(parent, gparent); |
|
|
|
elm = gparent; |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
if (RB_LEFT(parent) == elm) { |
|
|
|
RB_ROTATE_RIGHT(head, parent, tmp); |
|
|
|
tmp = parent; |
|
|
|
parent = elm; |
|
|
|
elm = tmp; |
|
|
|
} |
|
|
|
|
|
|
|
RB_SET_BLACKRED(parent, gparent); |
|
|
|
RB_ROTATE_LEFT(head, gparent, tmp); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
RB_SET_COLOR(head->Root(), EntryColor::Black); |
|
|
|
} |
|
|
|
|
|
|
|
template <typename Node> |
|
|
|
void RB_REMOVE_COLOR(RBHead<Node>* head, Node* parent, Node* elm) { |
|
|
|
Node* tmp; |
|
|
|
while ((elm == nullptr || RB_IS_BLACK(elm)) && elm != head->Root() && parent != nullptr) { |
|
|
|
template <typename T> |
|
|
|
requires HasRBEntry<T> |
|
|
|
constexpr void RB_REMOVE_COLOR(RBHead<T>& head, T* parent, T* elm) { |
|
|
|
T* tmp; |
|
|
|
while ((elm == nullptr || RB_IS_BLACK(elm)) && elm != head.Root()) { |
|
|
|
if (RB_LEFT(parent) == elm) { |
|
|
|
tmp = RB_RIGHT(parent); |
|
|
|
if (!tmp) { |
|
|
|
ASSERT_MSG(false, "tmp is invalid!"); |
|
|
|
break; |
|
|
|
} |
|
|
|
if (RB_IS_RED(tmp)) { |
|
|
|
RB_SET_BLACKRED(tmp, parent); |
|
|
|
RB_ROTATE_LEFT(head, parent, tmp); |
|
|
|
@ -339,29 +310,29 @@ void RB_REMOVE_COLOR(RBHead<Node>* head, Node* parent, Node* elm) { |
|
|
|
|
|
|
|
if ((RB_LEFT(tmp) == nullptr || RB_IS_BLACK(RB_LEFT(tmp))) && |
|
|
|
(RB_RIGHT(tmp) == nullptr || RB_IS_BLACK(RB_RIGHT(tmp)))) { |
|
|
|
RB_SET_COLOR(tmp, EntryColor::Red); |
|
|
|
RB_SET_COLOR(tmp, RBColor::RB_RED); |
|
|
|
elm = parent; |
|
|
|
parent = RB_PARENT(elm); |
|
|
|
} else { |
|
|
|
if (RB_RIGHT(tmp) == nullptr || RB_IS_BLACK(RB_RIGHT(tmp))) { |
|
|
|
Node* oleft; |
|
|
|
T* oleft; |
|
|
|
if ((oleft = RB_LEFT(tmp)) != nullptr) { |
|
|
|
RB_SET_COLOR(oleft, EntryColor::Black); |
|
|
|
RB_SET_COLOR(oleft, RBColor::RB_BLACK); |
|
|
|
} |
|
|
|
|
|
|
|
RB_SET_COLOR(tmp, EntryColor::Red); |
|
|
|
RB_SET_COLOR(tmp, RBColor::RB_RED); |
|
|
|
RB_ROTATE_RIGHT(head, tmp, oleft); |
|
|
|
tmp = RB_RIGHT(parent); |
|
|
|
} |
|
|
|
|
|
|
|
RB_SET_COLOR(tmp, RB_COLOR(parent)); |
|
|
|
RB_SET_COLOR(parent, EntryColor::Black); |
|
|
|
RB_SET_COLOR(parent, RBColor::RB_BLACK); |
|
|
|
if (RB_RIGHT(tmp)) { |
|
|
|
RB_SET_COLOR(RB_RIGHT(tmp), EntryColor::Black); |
|
|
|
RB_SET_COLOR(RB_RIGHT(tmp), RBColor::RB_BLACK); |
|
|
|
} |
|
|
|
|
|
|
|
RB_ROTATE_LEFT(head, parent, tmp); |
|
|
|
elm = head->Root(); |
|
|
|
elm = head.Root(); |
|
|
|
break; |
|
|
|
} |
|
|
|
} else { |
|
|
|
@ -372,68 +343,56 @@ void RB_REMOVE_COLOR(RBHead<Node>* head, Node* parent, Node* elm) { |
|
|
|
tmp = RB_LEFT(parent); |
|
|
|
} |
|
|
|
|
|
|
|
if (!tmp) { |
|
|
|
ASSERT_MSG(false, "tmp is invalid!"); |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
if ((RB_LEFT(tmp) == nullptr || RB_IS_BLACK(RB_LEFT(tmp))) && |
|
|
|
(RB_RIGHT(tmp) == nullptr || RB_IS_BLACK(RB_RIGHT(tmp)))) { |
|
|
|
RB_SET_COLOR(tmp, EntryColor::Red); |
|
|
|
RB_SET_COLOR(tmp, RBColor::RB_RED); |
|
|
|
elm = parent; |
|
|
|
parent = RB_PARENT(elm); |
|
|
|
} else { |
|
|
|
if (RB_LEFT(tmp) == nullptr || RB_IS_BLACK(RB_LEFT(tmp))) { |
|
|
|
Node* oright; |
|
|
|
T* oright; |
|
|
|
if ((oright = RB_RIGHT(tmp)) != nullptr) { |
|
|
|
RB_SET_COLOR(oright, EntryColor::Black); |
|
|
|
RB_SET_COLOR(oright, RBColor::RB_BLACK); |
|
|
|
} |
|
|
|
|
|
|
|
RB_SET_COLOR(tmp, EntryColor::Red); |
|
|
|
RB_SET_COLOR(tmp, RBColor::RB_RED); |
|
|
|
RB_ROTATE_LEFT(head, tmp, oright); |
|
|
|
tmp = RB_LEFT(parent); |
|
|
|
} |
|
|
|
|
|
|
|
RB_SET_COLOR(tmp, RB_COLOR(parent)); |
|
|
|
RB_SET_COLOR(parent, EntryColor::Black); |
|
|
|
RB_SET_COLOR(parent, RBColor::RB_BLACK); |
|
|
|
|
|
|
|
if (RB_LEFT(tmp)) { |
|
|
|
RB_SET_COLOR(RB_LEFT(tmp), EntryColor::Black); |
|
|
|
RB_SET_COLOR(RB_LEFT(tmp), RBColor::RB_BLACK); |
|
|
|
} |
|
|
|
|
|
|
|
RB_ROTATE_RIGHT(head, parent, tmp); |
|
|
|
elm = head->Root(); |
|
|
|
elm = head.Root(); |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (elm) { |
|
|
|
RB_SET_COLOR(elm, EntryColor::Black); |
|
|
|
RB_SET_COLOR(elm, RBColor::RB_BLACK); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
template <typename Node> |
|
|
|
Node* RB_REMOVE(RBHead<Node>* head, Node* elm) { |
|
|
|
Node* child = nullptr; |
|
|
|
Node* parent = nullptr; |
|
|
|
Node* old = elm; |
|
|
|
EntryColor color{}; |
|
|
|
|
|
|
|
const auto finalize = [&] { |
|
|
|
if (color == EntryColor::Black) { |
|
|
|
RB_REMOVE_COLOR(head, parent, child); |
|
|
|
} |
|
|
|
|
|
|
|
return old; |
|
|
|
}; |
|
|
|
template <typename T> |
|
|
|
requires HasRBEntry<T> |
|
|
|
constexpr T* RB_REMOVE(RBHead<T>& head, T* elm) { |
|
|
|
T* child = nullptr; |
|
|
|
T* parent = nullptr; |
|
|
|
T* old = elm; |
|
|
|
RBColor color = RBColor::RB_BLACK; |
|
|
|
|
|
|
|
if (RB_LEFT(elm) == nullptr) { |
|
|
|
child = RB_RIGHT(elm); |
|
|
|
} else if (RB_RIGHT(elm) == nullptr) { |
|
|
|
child = RB_LEFT(elm); |
|
|
|
} else { |
|
|
|
Node* left; |
|
|
|
T* left; |
|
|
|
elm = RB_RIGHT(elm); |
|
|
|
while ((left = RB_LEFT(elm)) != nullptr) { |
|
|
|
elm = left; |
|
|
|
@ -446,6 +405,7 @@ Node* RB_REMOVE(RBHead<Node>* head, Node* elm) { |
|
|
|
if (child) { |
|
|
|
RB_SET_PARENT(child, parent); |
|
|
|
} |
|
|
|
|
|
|
|
if (parent) { |
|
|
|
if (RB_LEFT(parent) == elm) { |
|
|
|
RB_SET_LEFT(parent, child); |
|
|
|
@ -453,14 +413,14 @@ Node* RB_REMOVE(RBHead<Node>* head, Node* elm) { |
|
|
|
RB_SET_RIGHT(parent, child); |
|
|
|
} |
|
|
|
} else { |
|
|
|
head->SetRoot(child); |
|
|
|
head.SetRoot(child); |
|
|
|
} |
|
|
|
|
|
|
|
if (RB_PARENT(elm) == old) { |
|
|
|
parent = elm; |
|
|
|
} |
|
|
|
|
|
|
|
elm->SetEntry(old->GetEntry()); |
|
|
|
elm->SetRBEntry(old->GetRBEntry()); |
|
|
|
|
|
|
|
if (RB_PARENT(old)) { |
|
|
|
if (RB_LEFT(RB_PARENT(old)) == old) { |
|
|
|
@ -469,17 +429,24 @@ Node* RB_REMOVE(RBHead<Node>* head, Node* elm) { |
|
|
|
RB_SET_RIGHT(RB_PARENT(old), elm); |
|
|
|
} |
|
|
|
} else { |
|
|
|
head->SetRoot(elm); |
|
|
|
head.SetRoot(elm); |
|
|
|
} |
|
|
|
|
|
|
|
RB_SET_PARENT(RB_LEFT(old), elm); |
|
|
|
|
|
|
|
if (RB_RIGHT(old)) { |
|
|
|
RB_SET_PARENT(RB_RIGHT(old), elm); |
|
|
|
} |
|
|
|
|
|
|
|
if (parent) { |
|
|
|
left = parent; |
|
|
|
} |
|
|
|
|
|
|
|
return finalize(); |
|
|
|
if (color == RBColor::RB_BLACK) { |
|
|
|
RB_REMOVE_COLOR(head, parent, child); |
|
|
|
} |
|
|
|
|
|
|
|
return old; |
|
|
|
} |
|
|
|
|
|
|
|
parent = RB_PARENT(elm); |
|
|
|
@ -495,17 +462,69 @@ Node* RB_REMOVE(RBHead<Node>* head, Node* elm) { |
|
|
|
RB_SET_RIGHT(parent, child); |
|
|
|
} |
|
|
|
} else { |
|
|
|
head->SetRoot(child); |
|
|
|
head.SetRoot(child); |
|
|
|
} |
|
|
|
|
|
|
|
if (color == RBColor::RB_BLACK) { |
|
|
|
RB_REMOVE_COLOR(head, parent, child); |
|
|
|
} |
|
|
|
|
|
|
|
return old; |
|
|
|
} |
|
|
|
|
|
|
|
return finalize(); |
|
|
|
template <typename T> |
|
|
|
requires HasRBEntry<T> |
|
|
|
constexpr void RB_INSERT_COLOR(RBHead<T>& head, T* elm) { |
|
|
|
T *parent = nullptr, *tmp = nullptr; |
|
|
|
while ((parent = RB_PARENT(elm)) != nullptr && RB_IS_RED(parent)) { |
|
|
|
T* gparent = RB_PARENT(parent); |
|
|
|
if (parent == RB_LEFT(gparent)) { |
|
|
|
tmp = RB_RIGHT(gparent); |
|
|
|
if (tmp && RB_IS_RED(tmp)) { |
|
|
|
RB_SET_COLOR(tmp, RBColor::RB_BLACK); |
|
|
|
RB_SET_BLACKRED(parent, gparent); |
|
|
|
elm = gparent; |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
if (RB_RIGHT(parent) == elm) { |
|
|
|
RB_ROTATE_LEFT(head, parent, tmp); |
|
|
|
tmp = parent; |
|
|
|
parent = elm; |
|
|
|
elm = tmp; |
|
|
|
} |
|
|
|
|
|
|
|
// Inserts a node into the RB tree |
|
|
|
template <typename Node, typename CompareFunction> |
|
|
|
Node* RB_INSERT(RBHead<Node>* head, Node* elm, CompareFunction cmp) { |
|
|
|
Node* parent = nullptr; |
|
|
|
Node* tmp = head->Root(); |
|
|
|
RB_SET_BLACKRED(parent, gparent); |
|
|
|
RB_ROTATE_RIGHT(head, gparent, tmp); |
|
|
|
} else { |
|
|
|
tmp = RB_LEFT(gparent); |
|
|
|
if (tmp && RB_IS_RED(tmp)) { |
|
|
|
RB_SET_COLOR(tmp, RBColor::RB_BLACK); |
|
|
|
RB_SET_BLACKRED(parent, gparent); |
|
|
|
elm = gparent; |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
if (RB_LEFT(parent) == elm) { |
|
|
|
RB_ROTATE_RIGHT(head, parent, tmp); |
|
|
|
tmp = parent; |
|
|
|
parent = elm; |
|
|
|
elm = tmp; |
|
|
|
} |
|
|
|
|
|
|
|
RB_SET_BLACKRED(parent, gparent); |
|
|
|
RB_ROTATE_LEFT(head, gparent, tmp); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
RB_SET_COLOR(head.Root(), RBColor::RB_BLACK); |
|
|
|
} |
|
|
|
|
|
|
|
template <typename T, typename Compare> |
|
|
|
requires HasRBEntry<T> |
|
|
|
constexpr T* RB_INSERT(RBHead<T>& head, T* elm, Compare cmp) { |
|
|
|
T* parent = nullptr; |
|
|
|
T* tmp = head.Root(); |
|
|
|
int comp = 0; |
|
|
|
|
|
|
|
while (tmp) { |
|
|
|
@ -529,17 +548,17 @@ Node* RB_INSERT(RBHead<Node>* head, Node* elm, CompareFunction cmp) { |
|
|
|
RB_SET_RIGHT(parent, elm); |
|
|
|
} |
|
|
|
} else { |
|
|
|
head->SetRoot(elm); |
|
|
|
head.SetRoot(elm); |
|
|
|
} |
|
|
|
|
|
|
|
RB_INSERT_COLOR(head, elm); |
|
|
|
return nullptr; |
|
|
|
} |
|
|
|
|
|
|
|
// Finds the node with the same key as elm |
|
|
|
template <typename Node, typename CompareFunction> |
|
|
|
Node* RB_FIND(RBHead<Node>* head, Node* elm, CompareFunction cmp) { |
|
|
|
Node* tmp = head->Root(); |
|
|
|
template <typename T, typename Compare> |
|
|
|
requires HasRBEntry<T> |
|
|
|
constexpr T* RB_FIND(RBHead<T>& head, T* elm, Compare cmp) { |
|
|
|
T* tmp = head.Root(); |
|
|
|
|
|
|
|
while (tmp) { |
|
|
|
const int comp = cmp(elm, tmp); |
|
|
|
@ -555,11 +574,11 @@ Node* RB_FIND(RBHead<Node>* head, Node* elm, CompareFunction cmp) { |
|
|
|
return nullptr; |
|
|
|
} |
|
|
|
|
|
|
|
// Finds the first node greater than or equal to the search key |
|
|
|
template <typename Node, typename CompareFunction> |
|
|
|
Node* RB_NFIND(RBHead<Node>* head, Node* elm, CompareFunction cmp) { |
|
|
|
Node* tmp = head->Root(); |
|
|
|
Node* res = nullptr; |
|
|
|
template <typename T, typename Compare> |
|
|
|
requires HasRBEntry<T> |
|
|
|
constexpr T* RB_NFIND(RBHead<T>& head, T* elm, Compare cmp) { |
|
|
|
T* tmp = head.Root(); |
|
|
|
T* res = nullptr; |
|
|
|
|
|
|
|
while (tmp) { |
|
|
|
const int comp = cmp(elm, tmp); |
|
|
|
@ -576,13 +595,13 @@ Node* RB_NFIND(RBHead<Node>* head, Node* elm, CompareFunction cmp) { |
|
|
|
return res; |
|
|
|
} |
|
|
|
|
|
|
|
// Finds the node with the same key as lelm |
|
|
|
template <typename Node, typename CompareFunction> |
|
|
|
Node* RB_FIND_LIGHT(RBHead<Node>* head, const void* lelm, CompareFunction lcmp) { |
|
|
|
Node* tmp = head->Root(); |
|
|
|
template <typename T, typename U, typename Compare> |
|
|
|
requires HasRBEntry<T> |
|
|
|
constexpr T* RB_FIND_KEY(RBHead<T>& head, const U& key, Compare cmp) { |
|
|
|
T* tmp = head.Root(); |
|
|
|
|
|
|
|
while (tmp) { |
|
|
|
const int comp = lcmp(lelm, tmp); |
|
|
|
const int comp = cmp(key, tmp); |
|
|
|
if (comp < 0) { |
|
|
|
tmp = RB_LEFT(tmp); |
|
|
|
} else if (comp > 0) { |
|
|
|
@ -595,14 +614,14 @@ Node* RB_FIND_LIGHT(RBHead<Node>* head, const void* lelm, CompareFunction lcmp) |
|
|
|
return nullptr; |
|
|
|
} |
|
|
|
|
|
|
|
// Finds the first node greater than or equal to the search key |
|
|
|
template <typename Node, typename CompareFunction> |
|
|
|
Node* RB_NFIND_LIGHT(RBHead<Node>* head, const void* lelm, CompareFunction lcmp) { |
|
|
|
Node* tmp = head->Root(); |
|
|
|
Node* res = nullptr; |
|
|
|
template <typename T, typename U, typename Compare> |
|
|
|
requires HasRBEntry<T> |
|
|
|
constexpr T* RB_NFIND_KEY(RBHead<T>& head, const U& key, Compare cmp) { |
|
|
|
T* tmp = head.Root(); |
|
|
|
T* res = nullptr; |
|
|
|
|
|
|
|
while (tmp) { |
|
|
|
const int comp = lcmp(lelm, tmp); |
|
|
|
const int comp = cmp(key, tmp); |
|
|
|
if (comp < 0) { |
|
|
|
res = tmp; |
|
|
|
tmp = RB_LEFT(tmp); |
|
|
|
@ -616,8 +635,43 @@ Node* RB_NFIND_LIGHT(RBHead<Node>* head, const void* lelm, CompareFunction lcmp) |
|
|
|
return res; |
|
|
|
} |
|
|
|
|
|
|
|
template <typename Node> |
|
|
|
Node* RB_NEXT(Node* elm) { |
|
|
|
template <typename T, typename Compare> |
|
|
|
requires HasRBEntry<T> |
|
|
|
constexpr T* RB_FIND_EXISTING(RBHead<T>& head, T* elm, Compare cmp) { |
|
|
|
T* tmp = head.Root(); |
|
|
|
|
|
|
|
while (true) { |
|
|
|
const int comp = cmp(elm, tmp); |
|
|
|
if (comp < 0) { |
|
|
|
tmp = RB_LEFT(tmp); |
|
|
|
} else if (comp > 0) { |
|
|
|
tmp = RB_RIGHT(tmp); |
|
|
|
} else { |
|
|
|
return tmp; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
template <typename T, typename U, typename Compare> |
|
|
|
requires HasRBEntry<T> |
|
|
|
constexpr T* RB_FIND_EXISTING_KEY(RBHead<T>& head, const U& key, Compare cmp) { |
|
|
|
T* tmp = head.Root(); |
|
|
|
|
|
|
|
while (true) { |
|
|
|
const int comp = cmp(key, tmp); |
|
|
|
if (comp < 0) { |
|
|
|
tmp = RB_LEFT(tmp); |
|
|
|
} else if (comp > 0) { |
|
|
|
tmp = RB_RIGHT(tmp); |
|
|
|
} else { |
|
|
|
return tmp; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
template <typename T> |
|
|
|
requires HasRBEntry<T> |
|
|
|
constexpr T* RB_NEXT(T* elm) { |
|
|
|
if (RB_RIGHT(elm)) { |
|
|
|
elm = RB_RIGHT(elm); |
|
|
|
while (RB_LEFT(elm)) { |
|
|
|
@ -636,8 +690,9 @@ Node* RB_NEXT(Node* elm) { |
|
|
|
return elm; |
|
|
|
} |
|
|
|
|
|
|
|
template <typename Node> |
|
|
|
Node* RB_PREV(Node* elm) { |
|
|
|
template <typename T> |
|
|
|
requires HasRBEntry<T> |
|
|
|
constexpr T* RB_PREV(T* elm) { |
|
|
|
if (RB_LEFT(elm)) { |
|
|
|
elm = RB_LEFT(elm); |
|
|
|
while (RB_RIGHT(elm)) { |
|
|
|
@ -656,30 +711,32 @@ Node* RB_PREV(Node* elm) { |
|
|
|
return elm; |
|
|
|
} |
|
|
|
|
|
|
|
template <typename Node> |
|
|
|
Node* RB_MINMAX(RBHead<Node>* head, bool is_min) { |
|
|
|
Node* tmp = head->Root(); |
|
|
|
Node* parent = nullptr; |
|
|
|
template <typename T> |
|
|
|
requires HasRBEntry<T> |
|
|
|
constexpr T* RB_MIN(RBHead<T>& head) { |
|
|
|
T* tmp = head.Root(); |
|
|
|
T* parent = nullptr; |
|
|
|
|
|
|
|
while (tmp) { |
|
|
|
parent = tmp; |
|
|
|
if (is_min) { |
|
|
|
tmp = RB_LEFT(tmp); |
|
|
|
} else { |
|
|
|
tmp = RB_RIGHT(tmp); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return parent; |
|
|
|
} |
|
|
|
|
|
|
|
template <typename Node> |
|
|
|
Node* RB_MIN(RBHead<Node>* head) { |
|
|
|
return RB_MINMAX(head, true); |
|
|
|
template <typename T> |
|
|
|
requires HasRBEntry<T> |
|
|
|
constexpr T* RB_MAX(RBHead<T>& head) { |
|
|
|
T* tmp = head.Root(); |
|
|
|
T* parent = nullptr; |
|
|
|
|
|
|
|
while (tmp) { |
|
|
|
parent = tmp; |
|
|
|
tmp = RB_RIGHT(tmp); |
|
|
|
} |
|
|
|
|
|
|
|
template <typename Node> |
|
|
|
Node* RB_MAX(RBHead<Node>* head) { |
|
|
|
return RB_MINMAX(head, false); |
|
|
|
return parent; |
|
|
|
} |
|
|
|
} // namespace Common |
|
|
|
|
|
|
|
} // namespace Common::freebsd |