3-29 红黑树的红色内结点问题
问题描述
红黑树是一类特殊的二叉搜索树,其中每个结点被“染成”红色或黑色。若将二叉搜索树结点中的空指针看作是指向一个空结点,则称这类空结点为二叉搜索树的前端结点。并规定所有前端结点的高度为-1。
一棵红黑树是满足下面“红黑性质”染色二叉搜索树:
(1)每个结点被染成红色或黑色;
(2)每个前端结点为黑色结点;
(3)任一红结点的儿子结点均为黑结点;
(4)在从任一结点到其子孙前端结点的所有路径上具有相同的黑结点数。从红黑树中任一结点 x 出发(不包括结点 x),到达一个前端结点的任意一条路径上的黑结点个数称为结点 x 的黑高度,记作 bh(x)。红黑树的黑高度定义为其根结点的黑高度。
图示的二叉搜索树是一棵红黑树。标在结点旁边的数字是相应结点的黑高度。

给定正整数 n,试设计一个算法,计算出在所有含有 n 个结点的红黑树中,红色内结点 个数的最小值和最大值。
数据输入:
第一行是正整数 n,1< n< 5000。
Java
import java.util.Scanner;
public class HongHeiShuDeHongSeNeiJieDian {
private static int n,m;
private static int[][][] red;
public static void main(String[] args){
Scanner input = new Scanner(System.in);
while (true){
n = input.nextInt();
m = 2 * ilog(n+3);
red = new int[n+1][m+1][2];
output();
}
}
private static void init(){
for(int i=0; i<=n; i++)
for(int j=0; j<=m; j++)
for(int k=0; k<2; k++)
red[i][j][k] = -1;
red[0][0][0] = 0;
red[0][0][1] = 0;
red[1][1][0] = 1;
red[1][1][1] = 0;
red[2][1][1] = 1;
red[3][1][1] = 2;
red[3][2][0] = 1;
red[3][2][1] = 0;
}
//max
private static void dyna(){
int i,j,jj,k;
init();
for(i=4; i<=n; i++)
for(j=ilog(i+1)/2,jj=4*j; j<=jj; j++){
int imax = -1;
for(k=0; k<=i/2; k++){
int temp = isum(red[k][j-1][1], red[i-k-1][j-1][1]);
if(imax < temp)
imax = temp;
}
if(imax >= 0)
red[i][j][0] = imax+1;
imax = -1;
for(k=0; k<=i/2; k++){
int temp = isum(red[k][j][0], red[i-k-1][j][0]);
if(imax < temp)
imax = temp;
temp = isum(red[k][j][0], red[i-k-1][j-1][1]);
if(imax < temp)
imax = temp;
temp = isum(red[k][j-1][1], red[i-k-1][j][0]);
if(imax < temp)
imax = temp;
temp = isum(red[k][j-1][1], red[i-k-1][j-1][1]);
if(imax < temp)
imax = temp;
}
if(imax >= 0)
red[i][j][1] = imax;
}
}
//min
private static void dynamin(){
int i,j,jj,k;
init();
for(i=4; i<=n; i++)
for(j=ilog(i+1)/2,jj=4*j; j<=jj; j++){
int imin = i+1;
for(k=0; k<=i/2; k++){
int temp = isum(red[k][j-1][1], red[i-k-1][j-1][1]);
if(temp >=0 && imin > temp)
imin = temp;
}
if(imin < i+1)
red[i][j][0] = imin+1;
imin = i+1;
for(k=0; k<=i/2; k++){
int temp = isum(red[k][j][0], red[i-k-1][j][0]);
if(temp >=0 && imin > temp)
imin = temp;
temp = isum(red[k][j][0], red[i-k-1][j-1][1]);
if(temp >=0 && imin > temp)
imin = temp;
temp = isum(red[k][j-1][1], red[i-k-1][j][0]);
if(temp >=0 && imin > temp)
imin = temp;
temp = isum(red[k][j-1][1], red[i-k-1][j-1][1]);
if(temp >=0 && imin > temp)
imin = temp;
}
if(imin < i+1)
red[i][j][1] = imin;
}
}
private static void output(){
double ratio1=0,ratio2=0,temp=0;
int[] minr = new int[n+1];
int[] maxr = new int[n+1];
dynamin();
for(int i=1; i<=n; i++)
minr[i] = rmin(i);
dyna();
for(int i=1; i<=n; i++)
maxr[i] = rmax(i);
System.out.println(minr[n]);
System.out.println(maxr[n]);
}
private static int rmin(int i){
int j,jj,imin=i+1;
for(j=ilog(i+3)/2,jj=4*j; j<=jj; j++){
if(red[i][j][0] >= 0 && imin > red[i][j][0])
imin = red[i][j][0];
if(red[i][j][1] >= 0 && imin > red[i][j][1])
imin = red[i][j][1];
}
return imin;
}
private static int rmax(int i){
int j,jj,imax=-1;
for(j=ilog(i+3)/2,jj=4*j; j<=jj; j++){
if(imax < red[i][j][0])
imax = red[i][j][0];
if(imax < red[i][j][1])
imax = red[i][j][1];
}
return imax;
}
private static int ilog(int x){
int i = (int)(Math.log(x)/Math.log(2));
return i;
}
private static int isum(int x, int y){
if(x<0 || y<0)
return -1;
return x+y;
}
}
Input & Output
8
1
4
338
4
223
Reference
王晓东《计算机算法设计与分析》

本文探讨了红黑树中红色内结点的问题,指出红黑树是一种特殊的二叉搜索树,满足特定的红黑性质。给定结点数n,目标是计算含有n个结点的红黑树中红色内结点数量的最小值和最大值。适用于算法设计和分析的学习者。
177万+

被折叠的 条评论
为什么被折叠?



