1. 程式人生 > >3、如何判斷一棵樹是否是紅黑樹?

3、如何判斷一棵樹是否是紅黑樹?

假設 隊列 als 前序 紅黑樹 truct lse -s ron

一、紅黑樹的定義

紅黑樹是每個節點都帶有顏色屬性的二叉查找樹,顏色或紅色或黑色。除了二叉查找樹強制的一般要求以外,對於任何有效的紅黑樹有如下的額外要求:

  • 性質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; }

3、如何判斷一棵樹是否是紅黑樹?