问题如下:1.查找在二叉查找树中按大小排名为k的节点(如果元素x排名为k,则有k个元素排在x的前面,排名以0为起点),以升序排序
2.给出指定键值,返回其在二叉查找树中的排名,升序排序
第1个问题分析:1.任意节点的左子树中的所有节点一定排在自身前面
2.如果左子树中节点不足,比如查找排名为6的节点,但左子树中只有3个节点,则在右子树中查找排名为k-左子树节点数-1(根)的节点
3.如果左子树的大小=k,则返回当前节点
因为需要频繁计算左子树的大小,所以我们使用一个名为size的函数来单独计算,size使用递归实现,但如果树极不平衡或树极大时栈的数量将不可接受,那时可在树节点中加入一个元素来记录每一个节点下的子树大小:
代码如下:
typedef TreeNode * Tree;
typedef TreeNode * TreePosition;
size_t size(Tree T)
{
if (T == NULL)
return 0;
if (T->Left || T->Right)
{
if (T->Left == NULL)
return size(T->Right) + 1;
if (T->Right == NULL)
return size(T->Left) + 1;
else
return size(T->Left) + size(T->Right) + 1;
}
else
return 1;
}
TreePosition Select(size_t X,Tree T)
{
size_t iTemp = size(T->Left);
if (T == NULL)
return NULL;
else if (iTemp>X)
//当左子树的节点数大于排名时,在左子树里递归查找
return Select(X, T->Left);
else if (iTemp<X)
//当左子树节点树不够时,在右子树里递归查找,需要将排名减去左子树的节点数
//因为此时左子树所有节点都排在前面
return Select(X - iTemp -1, T->Right);
//当排名==左子树节点时,返回当前节点
else if (X == iTemp)
return T;
}
第2个问题与第一个问题思路基本相同:1.如果当前节点键值大于x,则返回 左子树大小+递归调用右子树的结果+1
2如果当前节点键值小于x,则返回递归调用左子树的结果
3 如果当前节点简直等于x,返回左子树大小
代码如下:.
size_t Rank(ElementType X, Tree T)
{
size_t iTemp = size(T->Left);
if (X == T->Element)
//当键值相等时,返回当前节点的左子树节点数
return iTemp;
else if (X > T->Element)
//当X大于当前键值时,排名=左子树节点数+在右子树里的排名+1(当前节点)
return iTemp + Rank(X, T->Right) +1;
else if (X < T->Element)
return Rank(X,T->Left);
}