1. 程式人生 > >二叉排序樹平均檢索長度(ASL)的演算法

二叉排序樹平均檢索長度(ASL)的演算法

對於二叉排序樹的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; }