3、如何判断一棵树是否是红黑树?

一、红黑树的定义

红黑树是每个节点都带有颜色属性的二叉查找树,颜色或红色或黑色。除了二叉查找树强制的一般要求以外,对于任何有效的红黑树有如下的额外要求:

  • 性质1. 节点是红色或黑色。
  • 性质2. 根节点是黑色。
  • 性质3 每个叶节点(NIL节点,空节点)是黑色的。
  • 性质4 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)
  • 性质5. 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。

二、如何判断是否是红黑树(假设正数代表黑色,负数代表红色)

1、中序遍历树,如何序列是递增的,则是二叉查找树,继续下一步。否则不是,结束。

2、如果根是黑色,继续下一步,否则结束。

3、对树的层序遍历的逆序列(队列+栈)一一遍历。判断以当前结点为根结点的树是否是红黑树(从边界开始,递推判断)。

map<Node*, int> mp;//以当前结点的指针为Key,值为当前结点到每个叶子的黑色结点的数目
  • 若当前结点的孩子结点为空时,则当前结点是红黑树。
  • 若左孩子和右孩子到叶子节点的黑色结点数不同,结束。
  • 若存在左孩子且当前结点和左孩子的颜色都为红色,结束。
  • 若存在右孩子且当前结点和右孩子的颜色都为红色,结束。
  • 经以上判断后,以当前结点为根的树是红黑树。则,若当前结点为红色,当前结点到每个叶子的黑色结点的数目等于任一孩子到叶子节点的黑色结点数。

若当前结点为黑色,当前结点到每个叶子的黑色结点的数目等于任一孩子到叶子节点的黑色结点数+1。

代码:

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <vector>
#include <stack>
#include <queue>
#include <map>
using namespace std;

struct Node {

    int data;
    Node *lchild, *rchild;
};

bool isRedBlock;
vector<int> pre, in;
queue<Node*> Q;
stack<Node*> st;
map<Node*, int> mp;

//前序和中序建树
Node* create(int preL, int preR, int inL, int inR) {
    if (preL > preR) return NULL;
    Node* root = new Node;
    root->data = pre[preL];
    int k;
    for (k = inL; k <= inR; k++) {
        if (in[k] == pre[preL]) break;
    }
    int numleft = k - inL;
    root->lchild = create(preL + 1, preL + numleft, inL, k - 1);
    root->rchild = create(preL + numleft + 1, preR, k + 1, inR);
    return root;
}

bool cmp(int a, int b) {
    return abs(a) < abs(b);
}
void layertraverse(Node* root) {
    Q.push(root);
    while (!Q.empty()) {
        Node* front = Q.front();
        Q.pop();
        st.push(front);
        if (front->lchild != NULL) Q.push(front->lchild);
        if (front->rchild != NULL) Q.push(front->rchild);
    }
}

bool isRedSeq(Node* root) {
    bool flag = false;
    if (root->lchild != NULL&& root->data < 0 && root->lchild->data < 0) flag = true;
    if (root->rchild != NULL && root->data < 0 && root->rchild->data < 0) flag = true;
    return flag;
}
void judge() {
    while (!st.empty()) {
        Node* top = st.top();
        st.pop();
        if (top->lchild == NULL && top->rchild == NULL) {
            if (top->data > 0) mp[top] = 1;
            else mp[top] = 0;
        }
        else{
            if (mp[top->lchild] == mp[top->rchild]) {

                if (isRedSeq(top)) {
                    isRedBlock = false;
                    break;
                }
                if (top->data > 0) mp[top] = mp[top->lchild] + 1;
                else mp[top] = mp[top->lchild];
            }
            else {
                isRedBlock = false;
                break;
            }
        }
    }
}
int main(){
    int k, n;
    scanf("%d", &k);
    for (int i = 0; i < k; i++) {
        pre.clear();
        in.clear();
        while (!st.empty()) st.pop();
        while (!Q.empty()) Q.pop();
        mp.clear();
        isRedBlock = true;

        scanf("%d", &n);
        pre.resize(n);
        for (int j = 0; j < n; j++) scanf("%d", &pre[j]);
        in = pre;
        sort(in.begin(), in.end(), cmp);
        Node* root = create(0, n - 1, 0, n - 1);
        if (root->data > 0) {
            layertraverse(root);
            judge();
        }
        else isRedBlock = false;
        printf("%s\n", isRedBlock == true ? "Yes" : "No");
    }
    return 0;
}

原文地址:https://www.cnblogs.com/fuqia/p/9514341.html

时间: 2024-07-30 06:20:28

3、如何判断一棵树是否是红黑树?的相关文章

【LeetCode】Symmetric Tree 判断一棵树是否是镜像的

题目:Symmetric Tree <span style="font-size:18px;">/**LeetCode Symmetric Tree 对称的树 * 思路:判断一棵树是否对称,1.有左子树就要有右子树 * 2.除根节点外对称节点值要相同 * 注意:对称后就是左子树的左节点和右子树的右节点比较 * Definition for binary tree * public class TreeNode { * int val; * TreeNode left; *

判断一棵树是否是另一棵树的子树

问题 判断一棵树是否是另一棵树的子树,如图 思路 问题分两步: 找值相同的根结点(遍历解决) 判断两结点是否包含(递归:值.左孩子.右孩子分别相同) 代码 bool IsPart(TreeNode *root1, TreeNode *root2) { if (root2 == NULL) return true; if (root1 == NULL) return false; if (root1->val != root2->val) return false; return IsPart(

判断一棵树是否为完全二叉树

完全二叉树:若一棵二叉树具有具有n个节点,它的每个节点都与高度为k的满二叉树编号为0~n-1结点一一对应,则称这可二叉树为完全二叉树. 方法一:一维数组存储 根据完全二叉树的定义和性质,利用一位数组作为完全二叉树的存储,如下图 由图,节点的编号与数组元素的下标是一一对应的,可根据二叉树的性质,可方便找出下标 为i的的双亲结点a[i/2]及左右孩子结点a[i*2],a[i*2+1].这样判断一棵树是否为二叉树,应该对此二叉树从上到下,从左到右依次编号, 然后把编好的号依次存入一位数组中,在与相应深

判断一棵树是否是二叉搜索树

前两天写过一篇博文<二叉搜索树基本操作实现>,为了更深入了解二叉搜索树的性质,本文实现判断一棵树是否为二叉搜索树算法. 二叉搜索树的性质: 任意节点的键值一定大于其左子树中的每一个节点的键值,并小于其右子树中的每一个节点的键值. 构造二叉树的节点定义为: struct TreeNode{ int data; TreeNode *left; TreeNode *right; }; 方法1 (错误) 对每一个节点,检测其值是否大于左子树节点,是否小于右子树节点.思路很简单,代码实现如下: bool

判断一棵树是否为二叉搜索树(二叉排序树) python

输入一棵树,判断这棵树是否为二叉搜索树.首先要知道什么是排序二叉树,二叉排序树是这样定义的,二叉排序树或者是一棵空树,或者是具有下列性质的二叉树: (1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值: (2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值: (3)左.右子树也分别为二叉排序树: (4)没有键值相等的节点 #方法1,直接判断 直接判断的关键在于不能只是单纯地判断根.左.右三个节点的大小关系,左子树的右节点不仅要大于父节点,还要小于父节点的父节点,右子树的左节点

从2-3-4树模型到红黑树实现

目录 从2-3-4树模型到红黑树实现 前言 2-3-4树 查找 插入 树的生长 删除 左倾红黑树 查找 插入 删除 总结 参考文献 从2-3-4树模型到红黑树实现 前言 红黑树,是一个高效的二叉查找树.其定义特性保证了树的路径长度在黑色节点上完美平衡,使得其查找效率接近于完美平衡的二叉树. 但是红黑树的实现逻辑很复杂,各种旋转,颜色变化,直接针对其分析,大多数都是死记硬背各种例子,不太容易有个直观的理解.实际上,红黑树是实现手段,是其他概念模型为了方便在二叉树上实现进而定义的节点颜色这个信息.如

LeetCode&mdash;&mdash;Same Tree(判断两棵树是否相同)

问题: Given two binary trees, write a function to check if they are equal or not. Two binary trees are considered equal if they are structurally identical and the nodes have the same value.   分析: 考虑使用深度优先遍历的方法,同时遍历两棵树,遇到不等的就返回. 代码如下: /** * Definition f

判断一棵树是否是二叉平衡树

主要就是判断二叉树深度进行改造.判断条件为左树为平衡树,右树为平衡树,并且左树的高度和右树的高度插不超过-1:public class IsAVL { public static class Node{ private Node left; private Node right; private int value; public Node(int value){ this.value = value; } } public static int isAVL(Node head){ if(hea

树-二叉查找树、红黑树

二叉查找树的性质: 如果节点的左子树不空,则左子树上所有结点的值均小于等于它的根结点的值: 如果节点的右子树不空,则右子树上所有结点的值均大于等于它的根结点的值: 任意节点的左.右子树也分别为二叉查找树: 二叉查找树查找某个结点时,是二分查找的思想,查找所需的最大次数等同于二叉树的高度. 缺陷:二叉查找树多次插入新节点时,有可能导致二叉查找树的不平衡,变成线性结构. 二叉查找树的优化=> 红黑树 1.节点是红色或黑色. 2.根节点是黑色. 3.所有叶子都是黑色(叶子是NIL节点). 4.每个红色