二叉排序樹平均檢索長度(ASL)的演算法
阿新 • • 發佈:2018-12-01
對於二叉排序樹的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;
}