1135 Is It A Red-Black Tree (30分)

121 篇文章 0 订阅
115 篇文章 0 订阅

There is a kind of balanced binary search tree named red-black tree in the data structure. It has the following 5 properties:

  • (1) Every node is either red or black.
  • (2) The root is black.
  • (3) Every leaf (NULL) is black.
  • (4) If a node is red, then both its children are black.
  • (5) For each node, all simple paths from the node to descendant leaves contain the same number of black nodes.

For example, the tree in Figure 1 is a red-black tree, while the ones in Figure 2 and 3 are not.

rbf1.jpgrbf2.jpgrbf3.jpg
Figure 1Figure 2Figure 3

For each given binary search tree, you are supposed to tell if it is a legal red-black tree.

Input Specification:

Each input file contains several test cases. The first line gives a positive integer K (≤30) which is the total number of cases. For each case, the first line gives a positive integer N (≤30), the total number of nodes in the binary tree. The second line gives the preorder traversal sequence of the tree. While all the keys in a tree are positive integers, we use negative signs to represent red nodes. All the numbers in a line are separated by a space. The sample input cases correspond to the trees shown in Figure 1, 2 and 3.

Output Specification:

For each test case, print in a line "Yes" if the given tree is a red-black tree, or "No" if not.

Sample Input:

3
9
7 -2 1 5 -4 -11 8 14 -15
9
11 -2 1 -7 5 -4 8 14 -15
8
10 -7 5 -6 8 15 -11 17

Sample Output:

Yes
No
No

 

题解: 

 

#include <iostream>
#include <algorithm>
#include <unordered_map>

using namespace std;

const int N = 40;

int pre[N], in[N];
unordered_map<int, int> pos;
bool ans;

int build(int il, int ir, int pl, int pr, int& sum)
{
    int root = pre[pl];
    int k = pos[abs(root)];

    if (k < il || k > ir)
    {
        ans = false;
        return 0;
    }

    int left = 0, right = 0, ls = 0, rs = 0;
    if (il < k) left = build(il, k - 1, pl + 1, pl + 1 + k - 1 - il, ls);
    if (k < ir) right = build(k + 1, ir, pl + 1 + k - 1 - il + 1, pr, rs);

    if (ls != rs) ans = false;
    sum = ls;
    if (root < 0)
    {
        if (left < 0 || right < 0) ans = false;
    }
    else sum ++ ;

    return root;
}

int main()
{
    int T;
    cin >> T;
    while (T -- )
    {
        int n;
        cin >> n;
        for (int i = 0; i < n; i ++ )
        {
            cin >> pre[i];
            in[i] = abs(pre[i]);
        }

        sort(in, in + n);

        pos.clear();
        for (int i = 0; i < n; i ++ ) pos[in[i]] = i;

        ans = true;
        int sum;
        int root = build(0, n - 1, 0, n - 1, sum);

        if (root < 0) ans = false;
        if (ans) puts("Yes");
        else puts("No");
    }

    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 红黑树有下面几种操作:1. 插入:在红黑树中插入一个新的节点;2. 删除:从红黑树中删除一个节点;3. 查找:在红黑树中查找一个特定的节点;4. 遍历:遍历红黑树中的所有节点。使用C语言实现红黑树的操作代码可以参考下面的示例:1. 插入:/* Insert a node into the Red-Black Tree */ void rb_insert(struct rb_node *node, struct rb_root *root) { struct rb_node *parent = NULL; struct rb_node **link = &root->rb_node; /* Find the place to insert the new node */ while (*link) { parent = *link; if (node->key < parent->key) link = &(*link)->rb_left; else link = &(*link)->rb_right; } /* Insert the new node into the tree */ node->rb_parent = parent; node->rb_left = node->rb_right = NULL; *link = node; /* Fix any violations of the Red-Black Tree properties */ rb_insert_fixup(node, root); }2. 删除:/* Delete a node from the Red-Black Tree */ void rb_delete(struct rb_node *node, struct rb_root *root) { struct rb_node *child, *parent; /* If the node to be deleted has two children, replace it with its successor */ if (node->rb_left && node->rb_right) { struct rb_node *successor = rb_successor(node); node->key = successor->key; node = successor; } /* Get a pointer to the node's parent and child */ parent = node->rb_parent; child = node->rb_left ? node->rb_left : node->rb_right; /* Remove the node from the tree */ if (child) child->rb_parent = parent; if (parent) { if (node == parent->rb_left) parent->rb_left = child; else parent->rb_right = child; } else root->rb_node = child; /* Fix any violations of the Red-Black Tree properties */ rb_delete_fixup(node, root); }3. 查找:/* Find a node in the Red-Black Tree */ struct rb_node *rb_search(int key, struct rb_root *root) { struct rb_node *node = root->rb_node; while (node) { if (key < node->key) node = node->rb_left; else if (key > node->key) node = node->rb_right; else return node; } return NULL; }4. 遍历:/* Traverse the Red-Black Tree in-order */ void rb_inorder_traverse(struct rb_node *node, void (*func)(struct rb_node *)) { if (!node) return; rb_inorder_traverse(node->rb_left, func); func(node); rb_inorder_traverse(node->rb_right, func); } ### 回答2: 红黑树是一种自平衡的二叉搜索树,它具有以下特点:节点要么是红色,要么是黑色;根节点是黑色;每个叶子节点(NIL节点,空节点)是黑色;如果一个节点是红色,则它的两个子节点都是黑色;对于每个节点,从该节点到其所有后代叶子节点的简单路径上,均包含相同数量的黑色节点。 以下是使用C语言实现红黑树的所有操作的代码: ```c #include <stdio.h> #include <stdlib.h> enum Color {RED, BLACK}; typedef struct Node { int data; enum Color color; struct Node *left, *right, *parent; } Node; Node* createNode(int data) { Node* newNode = (Node*)malloc(sizeof(Node)); newNode->data = data; newNode->color = RED; newNode->left = newNode->right = newNode->parent = NULL; return newNode; } Node* bstInsert(Node* root, Node* newNode) { if (root == NULL) return newNode; if (newNode->data < root->data) { root->left = bstInsert(root->left, newNode); root->left->parent = root; } else if (newNode->data > root->data) { root->right = bstInsert(root->right, newNode); root->right->parent = root; } return root; } void swapColors(Node* a, Node* b) { enum Color temp; temp = a->color; a->color = b->color; b->color = temp; } void rotateLeft(Node** root, Node* x) { Node* 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 rotateRight(Node** root, Node* x) { Node* y = x->left; x->left = y->right; if (y->right != NULL) y->right->parent = x; y->parent = x->parent; if (x->parent == NULL) *root = y; else if (x == x->parent->right) x->parent->right = y; else x->parent->left = y; y->right = x; x->parent = y; } void fixViolation(Node** root, Node* newNode) { Node* parent = NULL; Node* grandParent = NULL; while ((newNode != *root) && (newNode->color != BLACK) && (newNode->parent->color == RED)) { parent = newNode->parent; grandParent = newNode->parent->parent; if (parent == grandParent->left) { Node* uncle = grandParent->right; if (uncle != NULL && uncle->color == RED) { grandParent->color = RED; parent->color = BLACK; uncle->color = BLACK; newNode = grandParent; } else { if (newNode == parent->right) { rotateLeft(root, parent); newNode = parent; parent = newNode->parent; } rotateRight(root, grandParent); swapColors(parent, grandParent); newNode = parent; } } else { Node* uncle = grandParent->left; if ((uncle != NULL) && (uncle->color == RED)) { grandParent->color = RED; parent->color = BLACK; uncle->color = BLACK; newNode = grandParent; } else { if (newNode == parent->left) { rotateRight(root, parent); newNode = parent; parent = newNode->parent; } rotateLeft(root, grandParent); swapColors(parent, grandParent); newNode = parent; } } } (*root)->color = BLACK; } Node* insertNode(Node* root, int data) { Node* newNode = createNode(data); root = bstInsert(root, newNode); fixViolation(&root, newNode); return root; } void inOrderTraversal(Node* root) { if (root == NULL) return; inOrderTraversal(root->left); printf("%d ", root->data); inOrderTraversal(root->right); } int main() { Node* root = NULL; root = insertNode(root, 10); root = insertNode(root, 20); root = insertNode(root, 30); root = insertNode(root, 40); root = insertNode(root, 50); root = insertNode(root, 60); printf("In-order traversal of the constructed Red-Black tree is: "); inOrderTraversal(root); return 0; } ``` 上述代码实现了红黑树的插入操作,并进行了适当的旋转和颜色交换以保证红黑树的特性。在主函数中,将节点插入到红黑树中,并进行中序遍历输出。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值