对于二叉排序树的ASL算法
二叉排序树的特点是左孩子小于根节点,右孩子大于根节点
之前寻找博客上计算ASL的算法时,看到用的是设置一个max值来判断是否换层,遍历二叉排序树,若是大于max则是属于同一层,赋值给max,直到找到小于max的节点就是下一层,但是对于如果一层中只有最后一个节点(即这一层最大的节点)有右孩子,max值就一直是增加的,则不会换层
解决方法
使用一个父节点数组和队列,有孩子节点则加入父节点队列,存储每一层的父节点数,一层结束后输出前面的父节点,只留下该层最后一父节点,则可以判断一层结束;
若节点队列为空且当前节点无孩子,则整个二叉排序树结束。
代码片
typedef struct BTreeNode
{
int data;
struct BTreeNode *leftchild;
struct BTreeNode *rightchild;
}BinTreeNode;
代码片
void BSTS_ASL(BinTree bt)//平均查找长度ASL
{
queue<BinTree> a;
queue<BinTree> parent;
BinTree p;
int n = 0; //个数
int w[10] = { 0 };
int fu[10] = { 0 };
int i = 1, flag = 1;
double r;
if (bt == NULL)
return 0;//节点为空
p = bt;
a.push(bt);//头元素入队
while (!a.empty())
{
p = a.front(); a.pop(); //第一个元素出队
cout << p->data << ' '; //输出
w[i]++; //每层元素个数
n++; //个数
if (a.empty())
{
if (flag == 1) //第一次第一层结束
{
i++;
flag++;
cout << endl;
}
if (p->leftchild == NULL&&p->rightchild == NULL)//二叉树结束
break;
}
if (p->leftchild != NULL || p->rightchild != NULL)//有孩子则父节点入队
{
if (p->leftchild != NULL)
a.push(p->leftchild);//左孩子入队
if (p->rightchild != NULL)
a.push(p->rightchild);//右孩子入队
parent.push(p);
if (fu[1] == 0)
fu[1] = 1;//根节点
else
fu[i]++; //父节点数量
}
//一层结束,父节点队列出队
//左节点不为空,右节点为空, 且p等于左节点
if ((parent.front()->leftchild != NULL&&parent.front()->rightchild == NULL) && p == parent.front()->leftchild)
{
for (int j = 0; j < fu[i]; j++)
parent.pop();
p = a.front();
i++;//一层结束
cout << endl;
}
//右节点不为空,左节点为空, 且p等于右节点
else if ((parent.front()->rightchild != NULL&& parent.front()->leftchild == NULL) && p == parent.front()->rightchild)
{
for (int j = 0; j < fu[i]; j++)
parent.pop();
p = a.front();
i++;//一层结束
cout << endl;
}
//右节点不为空,左节点为空, 且p等于右节点
else if (p == parent.front()->rightchild)
{
for (int j = 0; j < fu[i]; j++)
parent.pop();
p = a.front();
i++;//一层结束
cout << endl;
}
}
cout << endl;
int s = 0;
for (int j = 0; j <= i; j++)
s += j*w[j];
printf("平均检索长度(ASL) = ");
cout << s << '/' << n << endl;
r = s* 1.0 / n;
}