【轻松掌握数据结构与算法】树的奥秘:从基础到高级应用

1 什么是树?

树是一种非线性的数据结构,它由节点组成,每个节点可以有多个子节点,但只有一个父节点。树的顶部节点称为根节点,它是树的起点。树的结构使得数据可以以层次化的方式进行组织和存储,这在很多实际应用中都非常有用,比如文件系统的目录结构、组织架构图等。

2 术语解释

在树的结构中,有一些基本的术语需要了解:

  • 根节点:树的顶部节点,没有父节点。

  • :连接父节点和子节点的线。

  • 叶子节点:没有子节点的节点。

  • 兄弟节点:具有相同父节点的节点。

  • 祖先节点:从根节点到该节点路径上的所有节点。

  • 后代节点:以该节点为祖先的所有节点。

  • 深度:从根节点到该节点的路径长度。

  • 高度:从该节点到最远叶子节点的路径长度。

3 二叉树

二叉树是树的一种特殊形式,其中每个节点最多有两个子节点,通常称为左子节点和右子节点。二叉树因其结构简单且易于操作,被广泛应用于各种算法和数据处理中。

代码示例
typedef struct TreeNode {
    int data;
    struct TreeNode *left, *right;
} TreeNode;

// 创建二叉树节点
TreeNode* createTreeNode(int data) {
    TreeNode *newNode = (TreeNode*)malloc(sizeof(TreeNode));
    newNode->data = data;
    newNode->left = newNode->right = NULL;
    return newNode;
}

4 二叉树的类型

二叉树有多种类型,每种类型都有其特定的性质和应用场景:

  • 严格二叉树:每个节点都有两个或没有子节点。

  • 满二叉树:每个节点都有两个子节点,并且所有叶子节点都在同一层。

  • 完全二叉树:除了最后一层外,每一层都被完全填满,并且所有节点都尽可能地向左对齐。

代码示例
// 检查是否为完全二叉树
int isCompleteBinaryTree(TreeNode *root, int index, int nodeCount) {
    if (root == NULL) {
        return 1;
    }
    if (index >= nodeCount) {
        return 0;
    }
    return isCompleteBinaryTree(root->left, 2 * index + 1, nodeCount) &&
           isCompleteBinaryTree(root->right, 2 * index + 2, nodeCount);
}

// 计算节点数
int countNodes(TreeNode *root) {
    if (root == NULL) {
        return 0;
    }
    return 1 + countNodes(root->left) + countNodes(root->right);
}

5 二叉树的性质

二叉树的性质对于理解和操作二叉树至关重要:

  • 节点数:满二叉树的节点数为 2^{h+1} - 1,其中 h 是树的高度。
  • 叶子节点数:满二叉树的叶子节点数为 2^h
  • 空链接数:完全二叉树的空链接数为 n + 1,其中 n 是节点数。
代码示例
// 计算二叉树的高度
int getHeight(TreeNode *root) {
    if (root == NULL) {
        return 0;
    }
    return 1 + fmax(getHeight(root->left), getHeight(root->right));
}

// 计算叶子节点数
int countLeaves(TreeNode *root) {
    if (root == NULL) {
        return 0;
    }
    if (root->left == NULL && root->right == NULL) {
        return 1;
    }
    return countLeaves(root->left) + countLeaves(root->right);
}

6 二叉树遍历

二叉树的遍历是按照特定的顺序访问树中的每个节点。常见的遍历方式有:

  • 前序遍历(DLR):先访问根节点,然后遍历左子树,最后遍历右子树。

  • 中序遍历(LDR):先遍历左子树,然后访问根节点,最后遍历右子树。

  • 后序遍历(LRD):先遍历左子树,然后遍历右子树,最后访问根节点。

  • 层次遍历:按照层次顺序从上到下,从左到右遍历节点。

代码示例
// 前序遍历二叉树
void preOrderTraversal(TreeNode *root) {
    if (root == NULL) {
        return;
    }
    printf("%d ", root->data);
    preOrderTraversal(root->left);
    preOrderTraversal(root->right);
}

// 中序遍历二叉树
void inOrderTraversal(TreeNode *root) {
    if (root == NULL) {
        return;
    }
    inOrderTraversal(root->left);
    printf("%d ", root->data);
    inOrderTraversal(root->right);
}

// 后序遍历二叉树
void postOrderTraversal(TreeNode *root) {
    if (root == NULL) {
        return;
    }
    postOrderTraversal(root->left);
    postOrderTraversal(root->right);
    printf("%d ", root->data);
}

// 层次遍历二叉树
void levelOrderTraversal(TreeNode *root) {
    if (root == NULL) {
        return;
    }
    Queue *queue = createQueue();
    enqueue(queue, root);
    while (!isEmpty(queue)) {
        TreeNode *node = dequeue(queue);
        printf("%d ", node->data);
        if (node->left != NULL) {
            enqueue(queue, node->left);
        }
        if (node->right != NULL) {
            enqueue(queue, node->right);
        }
    }
    freeQueue(queue);
}

输入输出示例

假设我们有以下二叉树:

    1
   / \
  2   3
 / \
4   5
  • 前序遍历:1 2 4 5 3

  • 中序遍历:4 2 5 1 3

  • 后序遍历:4 5 2 3 1

  • 层次遍历:1 2 3 4 5

7 N-ary 树(多叉树)

N-ary 树是一种更通用的树结构,其中每个节点可以有任意数量的子节点。这种树结构在某些应用场景中比二叉树更为灵活。

代码示例
typedef struct NaryTreeNode {
    int data;
    struct NaryTreeNode **children;
    int numChildren;
} NaryTreeNode;

// 创建N-ary树节点
NaryTreeNode* createNaryTreeNode(int data, int numChildren) {
    NaryTreeNode *newNode = (NaryTreeNode*)malloc(sizeof(NaryTreeNode));
    newNode->data = data;
    newNode->numChildren = numChildren;
    newNode->children = (NaryTreeNode**)malloc(numChildren * sizeof(NaryTreeNode*));
    for (int i = 0; i < numChildren; i++) {
        newNode->children[i] = NULL;
    }
    return newNode;
}

// 添加子节点
void addNaryTreeNode(NaryTreeNode *parent, NaryTreeNode *child, int index) {
    if (index < parent->numChildren) {
        parent->children[index] = child;
    }
}

8 线索二叉树遍历(无栈或无队列遍历)

线索二叉树是一种特殊的二叉树,它通过在节点中添加线索(指向前驱和后继的指针)来实现无需栈或队列的遍历。这种方式可以节省存储空间,并且在某些情况下可以提高遍历效率。

代码示例
typedef struct ThreadedNode {
    int data;
    struct ThreadedNode *left, *right;
    int lTag, rTag; // 0表示指针,1表示线索
} ThreadedNode;

// 创建线索二叉树节点
ThreadedNode* createThreadedNode(int data) {
    ThreadedNode *newNode = (ThreadedNode*)malloc(sizeof(ThreadedNode));
    newNode->data = data;
    newNode->left = newNode->right = NULL;
    newNode->lTag = newNode->rTag = 0;
    return newNode;
}

// 中序线索化
void inorderThreading(ThreadedNode *root, ThreadedNode **pre) {
    if (root != NULL) {
        inorderThreading(root->left, pre);
        if (root->left == NULL) {
            root->left = *pre;
            root->lTag = 1;
        }
        if (*pre != NULL && (*pre)->right == NULL) {
            (*pre)->right = root;
            (*pre)->rTag = 1;
        }
        *pre = root;
        inorderThreading(root->right, pre);
    }
}

// 中序遍历线索二叉树
void inorderTraversalThreaded(ThreadedNode *root) {
    ThreadedNode *current = root;
    while (current != NULL) {
        while (current->lTag == 0) {
            current = current->left;
        }
        printf("%d ", current->data);
        while (current->rTag == 1 && current->right != NULL) {
            current = current->right;
            printf("%d ", current->data);
        }
        current = current->right;
    }
}

输入输出示例

假设我们有以下线索二叉树:

    1
   / \
  2   3
 / \
4   5

中序遍历结果:4 2 5 1 3

9 表达式树

表达式树是一种用于表示数学表达式的二叉树。在表达式树中,叶子节点代表操作数,非叶子节点代表运算符。表达式树可以方便地进行表达式的求值和转换。

代码示例
typedef struct ExpressionNode {
    char data;
    struct ExpressionNode *left, *right;
} ExpressionNode;

// 创建表达式树节点
ExpressionNode* createExpressionNode(char data) {
    ExpressionNode *newNode = (ExpressionNode*)malloc(sizeof(ExpressionNode));
    newNode->data = data;
    newNode->left = newNode->right = NULL;
    return newNode;
}

// 构建表达式树
ExpressionNode* buildExpressionTree(char *expression) {
    // 假设表达式是中缀表达式,使用栈来构建表达式树
    // 这里只是一个简单的示例,实际实现会更复杂
    // 例如:(A+B)*(C-D)
    ExpressionNode *root = createExpressionNode('*');
    root->left = createExpressionNode('+');
    root->right = createExpressionNode('-');
    root->left->left = createExpressionNode('A');
    root->left->right = createExpressionNode('B');
    root->right->left = createExpressionNode('C');
    root->right->right = createExpressionNode('D');
    return root;
}

// 中序遍历表达式树
void inorderTraversalExpression(ExpressionNode *root) {
    if (root != NULL) {
        inorderTraversalExpression(root->left);
        printf("%c ", root->data);
        inorderTraversalExpression(root->right);
    }
}

// 求值表达式树
int evaluateExpressionTree(ExpressionNode *root) {
    if (root == NULL) {
        return 0;
    }
    if (root->left == NULL && root->right == NULL) {
        return root->data - '0'; // 假设操作数是单个字符
    }
    int leftVal = evaluateExpressionTree(root->left);
    int rightVal = evaluateExpressionTree(root->right);
    switch (root->data) {
        case '+': return leftVal + rightVal;
        case '-': return leftVal - rightVal;
        case '*': return leftVal * rightVal;
        case '/': return leftVal / rightVal;
    }
    return 0;
}

int main() {
    char expression[] = "(A+B)*(C-D)";
    ExpressionNode *root = buildExpressionTree(expression);
    printf("Inorder traversal of expression tree: ");
    inorderTraversalExpression(root);
    printf("\n");

    int result = evaluateExpressionTree(root);
    printf("Result of expression: %d\n", result);

    return 0;
}

输入输出示例

假设我们有表达式

(A+B)*(C-D)

(A+B)∗(C−D)

,构建的表达式树如下:

    *
   / \
  +   -
 / \ / \
A B C D
  • 中序遍历:A + B * C - D

  • 求值结果:假设 A=1, B=2, C=3, D=1,结果为 4

10 XOR 树

XOR 树是一种特殊的二叉树,它使用异或运算来存储和检索数据。这种树结构在某些特定的应用场景中可以提供高效的存储和检索性能。

代码示例
typedef struct XORNode {
    int data;
    struct XORNode *xorLink; // 异或链接
} XORNode;

// 创建XOR树节点
XORNode* createXORNode(int data) {
    XORNode *newNode = (XORNode*)malloc(sizeof(XORNode));
    newNode->data = data;
    newNode->xorLink = NULL;
    return newNode;
}

// 添加XOR树节点
void addXORNode(XORNode *root, XORNode *newNode, int position) {
    // 假设position为0表示左子节点,1表示右子节点
    if (position == 0) {
        root->xorLink = (XORNode*)((int)root->xorLink ^ (int)newNode);
    } else {
        root->xorLink = (XORNode*)((int)root->xorLink ^ (int)newNode);
    }
}

// 遍历XOR树
void traverseXORTree(XORNode *root) {
    XORNode *prev = NULL, *curr = root, *next;
    while (curr != NULL) {
        printf("%d ", curr->data);
        next = (XORNode*)((int)curr->xorLink ^ (int)prev);
        prev = curr;
        curr = next;
    }
}

int main() {
    XORNode *root = createXORNode(1);
    XORNode *node1 = createXORNode(2);
    XORNode *node2 = createXORNode(3);
    addXORNode(root, node1, 0);
    addXORNode(root, node2, 1);
    printf("XOR Tree traversal: ");
    traverseXORTree(root);
    printf("\n");
    return 0;
}

输入输出示例

假设我们有以下XOR树:

    1
   / \
  2   3

遍历结果:1 2 3

11 二叉搜索树(BST)

二叉搜索树是一种特殊的二叉树,其中每个节点的值都大于其左子树中所有节点的值,并且小于其右子树中所有节点的值。二叉搜索树可以高效地进行查找、插入和删除操作。

代码示例
typedef struct BSTNode {
    int data;
    struct BSTNode *left, *right;
} BSTNode;

// 创建二叉搜索树节点
BSTNode* createBSTNode(int data) {
    BSTNode *newNode = (BSTNode*)malloc(sizeof(BSTNode));
    newNode->data = data;
    newNode->left = newNode->right = NULL;
    return newNode;
}

// 插入节点
BSTNode* insertBSTNode(BSTNode *root, int data) {
    if (root == NULL) {
        return createBSTNode(data);
    }
    if (data < root->data) {
        root->left = insertBSTNode(root->left, data);
    } else if (data > root->data) {
        root->right = insertBSTNode(root->right, data);
    }
    return root;
}

// 查找节点
BSTNode* searchBSTNode(BSTNode *root, int data) {
    if (root == NULL || root->data == data) {
        return root;
    }
    if (data < root->data) {
        return searchBSTNode(root->left, data);
    }
    return searchBSTNode(root->right, data);
}

// 删除节点
BSTNode* deleteBSTNode(BSTNode *root, int data) {
    if (root == NULL) {
        return root;
    }
    if (data < root->data) {
        root->left = deleteBSTNode(root->left, data);
    } else if (data > root->data) {
        root->right = deleteBSTNode(root->right, data);
    } else {
        if (root->left == NULL) {
            BSTNode *temp = root->right;
            free(root);
            return temp;
        } else if (root->right == NULL) {
            BSTNode *temp = root->left;
            free(root);
            return temp;
        }
        BSTNode *temp = minValueNode(root->right);
        root->data = temp->data;
        root->right = deleteBSTNode(root->right, temp->data);
    }
    return root;
}

// 查找最小值节点
BSTNode* minValueNode(BSTNode *node) {
    BSTNode *current = node;
    while (current && current->left != NULL) {
        current = current->left;
    }
    return current;
}

// 中序遍历二叉搜索树
void inorderTraversalBST(BSTNode *root) {
    if (root != NULL) {
        inorderTraversalBST(root->left);
        printf("%d ", root->data);
        inorderTraversalBST(root->right);
    }
}

int main() {
    BSTNode *root = NULL;
    root = insertBSTNode(root, 50);
    insertBSTNode(root, 30);
    insertBSTNode(root, 20);
    insertBSTNode(root, 40);
    insertBSTNode(root, 70);
    insertBSTNode(root, 60);
    insertBSTNode(root, 80);

    printf("Inorder traversal of BST: ");
    inorderTraversalBST(root);
    printf("\n");

    BSTNode *searchNode = searchBSTNode(root, 40);
    if (searchNode != NULL) {
        printf("Node with data 40 found.\n");
    } else {
        printf("Node with data 40 not found.\n");
    }

    root = deleteBSTNode(root, 20);
    printf("Inorder traversal of BST after deleting 20: ");
    inorderTraversalBST(root);
    printf("\n");

    return 0;
}

输入输出示例

假设我们有以下二叉搜索树:

        50
       /  \
     30    70
    /  \  /  \
  20   40 60  80
  • 中序遍历:20 30 40 50 60 70 80

  • 查找节点 40:Node with data 40 found.

  • 删除节点 20

  • 中序遍历:30 40 50 60 70 80

12 平衡二叉搜索树

平衡二叉搜索树(如 AVL 树)是一种特殊的二叉搜索树,它通过自动调整树的结构来保持树的高度平衡,从而确保查找、插入和删除操作的时间复杂度为 O(log⁡n)

代码示例
typedef struct AVLNode {
    int data;
    struct AVLNode *left, *right;
    int height;
} AVLNode;

// 创建AVL树节点
AVLNode* createAVLNode(int data) {
    AVLNode *newNode = (AVLNode*)malloc(sizeof(AVLNode));
    newNode->data = data;
    newNode->left = newNode->right = NULL;
    newNode->height = 1; // 新节点的高度为1
    return newNode;
}

// 获取节点高度
int getHeight(AVLNode *node) {
    if (node == NULL) {
        return 0;
    }
    return node->height;
}

// 获取平衡因子
int getBalance(AVLNode *node) {
    if (node == NULL) {
        return 0;
    }
    return getHeight(node->left) - getHeight(node->right);
}

// 右旋转
AVLNode* rightRotate(AVLNode *y) {
    AVLNode *x = y->left;
    AVLNode *T2 = x->right;

    // 执行旋转
    x->right = y;
    y->left = T2;

    // 更新高度
    y->height = 1 + fmax(getHeight(y->left), getHeight(y->right));
    x->height = 1 + fmax(getHeight(x->left), getHeight(x->right));

    // 返回新的根节点
    return x;
}

// 左旋转
AVLNode* leftRotate(AVLNode *x) {
    AVLNode *y = x->right;
    AVLNode *T2 = y->left;

    // 执行旋转
    y->left = x;
    x->right = T2;

    // 更新高度
    x->height = 1 + fmax(getHeight(x->left), getHeight(x->right));
    y->height = 1 + fmax(getHeight(y->left), getHeight(y->right));

    // 返回新的根节点
    return y;
}

// 插入节点
AVLNode* insertAVLNode(AVLNode *root, int data) {
    if (root == NULL) {
        return createAVLNode(data);
    }

    if (data < root->data) {
        root->left = insertAVLNode(root->left, data);
    } else if (data > root->data) {
        root->right = insertAVLNode(root->right, data);
    } else {
        return root; // 重复值不插入
    }

    // 更新高度
    root->height = 1 + fmax(getHeight(root->left), getHeight(root->right));

    // 获取平衡因子
    int balance = getBalance(root);

    // 如果节点不平衡,则进行旋转
    if (balance > 1 && data < root->left->data) {
        return rightRotate(root);
    }

    if (balance < -1 && data > root->right->data) {
        return leftRotate(root);
    }

    if (balance > 1 && data > root->left->data) {
        root->left = leftRotate(root->left);
        return rightRotate(root);
    }

    if (balance < -1 && data < root->right->data) {
        root->right = rightRotate(root->right);
        return leftRotate(root);
    }

    return root;
}

// 中序遍历AVL树
void inorderTraversalAVL(AVLNode *root) {
    if (root != NULL) {
        inorderTraversalAVL(root->left);
        printf("%d ", root->data);
        inorderTraversalAVL(root->right);
    }
}

int main() {
    AVLNode *root = NULL;
    root = insertAVLNode(root, 10);
    root = insertAVLNode(root, 20);
    root = insertAVLNode(root, 30);
    root = insertAVLNode(root, 40);
    root = insertAVLNode(root, 50);
    root = insertAVLNode(root, 25);

    printf("Inorder traversal of AVL: ");
    inorderTraversalAVL(root);
    printf("\n");

    return 0;
}

输入输出示例

假设我们有以下AVL树:

        30
       /  \
     20    40
    /  \    \
  10   25   50
  • 中序遍历:10 20 25 30 40 50

13 AVL 树(Adelson-Velskii 和 Landis 树)

AVL 树是一种自平衡的二叉搜索树,它通过在插入和删除操作后进行旋转来保持树的高度平衡。AVL 树是平衡二叉搜索树的一种实现,它确保树的高度始终在

O(\log n)

O(log⁡n)

的范围内。

代码示例
// AVL树的插入和旋转操作已经在上一节中详细展示,这里不再重复。

14 树的其他变体

除了上述提到的树结构,还有许多其他类型的树,如 B 树、B+树、红黑树等。这些树结构在数据库、文件系统、网络路由等领域有着广泛的应用。

B 树

B 树是一种多路平衡查找树,每个节点可以有多个子节点。B 树的每个节点最多有 M 个子节点,最少有 M/2 个子节点。B 树的插入和删除操作会自动调整树的结构,以保持树的平衡。

B+ 树

B+ 树是 B 树的一种变体,主要用于数据库索引。B+ 树的所有叶子节点都包含指向相邻叶子节点的指针,这使得范围查询更加高效。B+ 树的叶子节点存储实际的数据记录,而非叶子节点只存储键值和指针。

红黑树

红黑树是一种自平衡的二叉搜索树,它通过在节点上添加颜色属性(红色或黑色)来保持树的平衡。红黑树的插入和删除操作会自动调整树的结构和颜色,以保持树的平衡。红黑树的平衡条件如下:

  1. 每个节点要么是红色,要么是黑色。

  2. 根节点是黑色。

  3. 每个叶子节点(NIL节点,空节点)是黑色。

  4. 每个红色节点的两个子节点都是黑色。

  5. 从任一节点到其每个叶子节点的所有路径都包含相同数量的黑色节点。

代码示例
typedef struct RBTreeNode {
    int data;
    struct RBTreeNode *left, *right, *parent;
    int color; // 0表示黑色,1表示红色
} RBTreeNode;

// 创建红黑树节点
RBTreeNode* createRBTreeNode(int data) {
    RBTreeNode *newNode = (RBTreeNode*)malloc(sizeof(RBTreeNode));
    newNode->data = data;
    newNode->left = newNode->right = newNode->parent = NULL;
    newNode->color = 1; // 新节点默认为红色
    return newNode;
}

// 左旋
void leftRotate(RBTreeNode **root, RBTreeNode *x) {
    RBTreeNode *y = x->right;
    x->right = y->left;
    if (y->left != NULL) {
        y->left->parent = x;
    }
    y->parent = x->parent;
    if (x->parent == NULL) {
        *root = y;
    } else if (x == x->parent->left) {
        x->parent->left = y;
    } else {
        x->parent->right = y;
    }
    y->left = x;
    x->parent = y;
}

// 右旋
void rightRotate(RBTreeNode **root, RBTreeNode *y) {
    RBTreeNode *x = y->left;
    y->left = x->right;
    if (x->right != NULL) {
        x->right->parent = y;
    }
    x->parent = y->parent;
    if (y->parent == NULL) {
        *root = x;
    } else if (y == y->parent->right) {
        y->parent->right = x;
    } else {
        y->parent->left = x;
    }
    x->right = y;
    y->parent = x;
}

// 插入后调整
void insertFixup(RBTreeNode **root, RBTreeNode *newNode) {
    RBTreeNode *uncle;
    while (newNode->parent != NULL && newNode->parent->color == 1) {
        if (newNode->parent == newNode->parent->parent->left) {
            uncle = newNode->parent->parent->right;
            if (uncle != NULL && uncle->color == 1) {
                newNode->parent->color = 0;
                uncle->color = 0;
                newNode->parent->parent->color = 1;
                newNode = newNode->parent->parent;
            } else {
                if (newNode == newNode->parent->right) {
                    newNode = newNode->parent;
                    leftRotate(root, newNode);
                }
                newNode->parent->color = 0;
                newNode->parent->parent->color = 1;
                rightRotate(root, newNode->parent->parent);
            }
        } else {
            uncle = newNode->parent->parent->left;
            if (uncle != NULL && uncle->color == 1) {
                newNode->parent->color = 0;
                uncle->color = 0;
                newNode->parent->parent->color = 1;
                newNode = newNode->parent->parent;
            } else {
                if (newNode == newNode->parent->left) {
                    newNode = newNode->parent;
                    rightRotate(root, newNode);
                }
                newNode->parent->color = 0;
                newNode->parent->parent->color = 1;
                leftRotate(root, newNode->parent->parent);
            }
        }
    }
    (*root)->color = 0; // 根节点为黑色
}

// 插入节点
void insertRBTree(RBTreeNode **root, int data) {
    RBTreeNode *newNode = createRBTreeNode(data);
    RBTreeNode *y = NULL;
    RBTreeNode *x = *root;

    // 查找插入位置
    while (x != NULL) {
        y = x;
        if (newNode->data < x->data) {
            x = x->left;
        } else {
            x = x->right;
        }
    }
    newNode->parent = y;
    if (y == NULL) {
        *root = newNode;
    } else if (newNode->data < y->data) {
        y->left = newNode;
    } else {
        y->right = newNode;
    }

    // 插入后调整
    insertFixup(root, newNode);
}

// 找到后继节点
RBTreeNode* treeSuccessor(RBTreeNode *x) {
    RBTreeNode *y = x->right;
    while (y->left != NULL) {
        y = y->left;
    }
    return y;
}

// 删除后调整
void deleteFixup(RBTreeNode **root, RBTreeNode *x) {
    RBTreeNode *w;
    while (x != *root && x->color == 0) {
        if (x == x->parent->left) {
            w = x->parent->right;
            if (w->color == 1) {
                w->color = 0;
                x->parent->color = 1;
                leftRotate(root, x->parent);
                w = x->parent->right;
            }
            if (w->left->color == 0 && w->right->color == 0) {
                w->color = 1;
                x = x->parent;
            } else {
                if (w->right->color == 0) {
                    w->left->color = 0;
                    w->color = 1;
                    rightRotate(root, w);
                    w = x->parent->right;
                }
                w->color = x->parent->color;
                x->parent->color = 0;
                w->right->color = 0;
                leftRotate(root, x->parent);
                x = *root;
            }
        } else {
            w = x->parent->left;
            if (w->color == 1) {
                w->color = 0;
                x->parent->color = 1;
                rightRotate(root, x->parent);
                w = x->parent->left;
            }
            if (w->right->color == 0 && w->left->color == 0) {
                w->color = 1;
                x = x->parent;
            } else {
                if (w->left->color == 0) {
                    w->right->color = 0;
                    w->color = 1;
                    leftRotate(root, w);
                    w = x->parent->left;
                }
                w->color = x->parent->color;
                x->parent->color = 0;
                w->left->color = 0;
                rightRotate(root, x->parent);
                x = *root;
            }
        }
    }
    x->color = 0;
}

// 删除节点
void deleteRBTree(RBTreeNode **root, int data) {
    RBTreeNode *z = *root;
    RBTreeNode *x, *y;
    int y_original_color;

    // 查找要删除的节点
    while (z != NULL && z->data != data) {
        if (data < z->data) {
            z = z->left;
        } else {
            z = z->right;
        }
    }

    if (z == NULL) {
        return; // 没有找到要删除的节点
    }

    y = z;
    y_original_color = y->color;

    if (z->left == NULL) {
        x = z->right;
        if (z->parent == NULL) {
            *root = z->right;
        } else if (z == z->parent->left) {
            z->parent->left = z->right;
        } else {
            z->parent->right = z->right;
        }
        if (z->right != NULL) {
            z->right->parent = z->parent;
        }
    } else if (z->right == NULL) {
        x = z->left;
        if (z->parent == NULL) {
            *root = z->left;
        } else if (z == z->parent->left) {
            z->parent->left = z->left;
        } else {
            z->parent->right = z->left;
        }
        if (z->left != NULL) {
            z->left->parent = z->parent;
        }
    } else {
        y = treeSuccessor(z);
        y_original_color = y->color;
        x = y->right;
        if (y->parent == z) {
            x->parent = y;
        } else {
            if (y->right != NULL) {
                y->right->parent = y->parent;
            }
            y->parent->left = y->right;
            y->right = z->right;
            y->right->parent = y;
        }
        y->parent = z->parent;
        if (z->parent == NULL) {
            *root = y;
        } else if (z == z->parent->left) {
            z->parent->left = y;
        } else {
            z->parent->right = y;
        }
        y->left = z->left;
        y->left->parent = y;
        y->color = z->color;
    }

    if (y_original_color == 0) {
        deleteFixup(root, x);
    }

    free(z);
}
输入输出示例

假设我们有以下红黑树:

        8(B)
       /    \
    18(R)   20(R)
   /   \    /   \
 10(B) 22(B) 25(B) 40(B)
  • 中序遍历:10 18 20 22 25 40

通过以上对树的深入探讨,我们可以看到树不仅是一种基本的数据结构,而且在计算机科学的各个领域都有着广泛的应用。无论是在算法设计、数据存储还是网络通信中,树都扮演着不可或缺的角色。希望这篇文章能帮助你更好地理解和应用树这一强大的数据结构。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值