二叉搜尋樹 (BST) 退化為鏈表時查詢效率降為 O(n)。紅黑樹 (Red-Black Tree) 作為一種自平衡二叉搜尋樹,透過「旋轉」與「重新著色」維持近似平衡,保證查詢、插入、刪除均為 O(log n)。C++ STL std::map、std::set 底層皆採用紅黑樹。
旋轉是紅黑樹調整結構的核心原語,分為左旋與右旋,兩者互為逆操作。
將節點 x 向左旋轉,使其右子節點 y 升為父節點,x 降為 y 的左子節點。y 原左子樹 (y->left) 成為 x 的新右子樹。
前提:x->right != NULL。
y = x->right。y->left 掛到 x->right (處理 y 原左子樹)。x 的父節點 px。y 掛到 px 相應位置 (若 px==NULL 則 y 成為新根)。x 設為 y->left,完成旋轉。// 節點結構假設包含 pLeft, pRight, item 等成員
// parent(x, head) 為查找父節點輔助函數
// root 為指向樹根的全域/類成員指標
void left_rotate(NODE *head, NODE *x)
{
if (x->pRight != NULL)
{
NODE *y = x->pRight; // 1. 目標節點
if (y->pLeft != NULL) // 2. 轉移 y 的左子樹
x->pRight = y->pLeft;
NODE *px = parent(x, head); // 3. 找父節點
if (px == NULL) // 4. 掛接到父節點或更新根
root = y;
else if (px->pLeft == x)
px->pLeft = y;
else
px->pRight = y;
y->pLeft = x; // 5. 完成旋轉
}
else
{
printf("節點 %ld 無右子,無法左旋!\n", x->item);
}
}
邏輯鏡像對稱:將 y 向右旋,x = y->left 升為父節點。
void right_rotate(NODE *head, NODE *y)
{
if (y->pLeft != NULL)
{
NODE *x = y->pLeft;
if (x->pRight != NULL)
y->pLeft = x->pRight;
NODE *py = parent(y, head);
if (py == NULL)
root = x;
else if (py->pLeft == y)
py->pLeft = x;
else
py->pRight = x;
x->pRight = y;
}
else
{
printf("節點 %ld 無左子,無法右旋!\n", y->item);
}
}
遞歸遍歷樹查找目標節點的父節點。
NODE *parent(NODE *pNode, NODE *head)
{
NODE *result = NULL;
if (head != NULL)
{
if (head->pLeft == pNode || head->pRight == pNode)
return head;
if (head->pLeft != NULL)
{
result = parent(pNode, head->pLeft);
if (result != NULL) return result;
}
if (head->pRight != NULL)
{
result = parent(pNode, head->pRight);
if (result != NULL) return result;
}
}
return NULL; // 未找到
}
root。掌握旋轉,即掌握了紅黑樹、AVL樹等所有平衡樹的結構調整核心。