编写一个程序,建立由有序序列进行二分查找产生的判定树,使其具有如下功能: 1.输出n=11时的判定树并求成功情况下的平均查找长度ASL; 2.通过构造判定树可以求得成功情况下的平均查找长度ASL1; 3.当将含有n个节点的判定树看成一颗满二叉树时,其成功平均查找长度的理论值ASL2约为log2(n+1)-1; 4.对于n=10、100、1000和10000,求出其ASL1和ASL2的值;
时间: 2024-02-15 14:04:42 浏览: 181
好的,这里是一个实现二分查找判定树的程序,并满足你的要求。
首先,我们需要定义一个二叉树节点的结构体。每个节点包含3个字段:左子节点、右子节点和存储的值。
```
struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
```
然后,我们需要编写一个函数来构造二分查找判定树。该函数接受一个有序序列和序列的长度,返回构造好的二叉树根节点。
```
TreeNode* build_binary_tree(int arr[], int left, int right) {
if (left > right) {
return NULL;
}
int mid = left + (right - left) / 2;
TreeNode* root = new TreeNode(arr[mid]);
root->left = build_binary_tree(arr, left, mid - 1);
root->right = build_binary_tree(arr, mid + 1, right);
return root;
}
```
接下来,我们需要计算平均查找长度ASL。ASL是指在查找成功的情况下,查找过程中比较关键字的次数的平均值。ASL可以使用以下公式计算:
```
ASL = (1/N) * (∑(i=1 to N)Ci)
```
其中,N是元素个数,Ci是查找第i个元素时比较的次数。
下面是一个使用二分查找算法查找特定值并计算ASL的示例代码:
```
double binary_search_ASL(TreeNode* root, int target, int& count) {
count++;
if (root->val == target) {
return count;
} else if (root->val < target) {
return binary_search_ASL(root->right, target, count);
} else {
return binary_search_ASL(root->left, target, count);
}
}
double calculate_ASL(TreeNode* root, int arr[], int n) {
double sum = 0.0;
for (int i = 0; i < n; i++) {
int count = 0;
double res = binary_search_ASL(root, arr[i], count);
sum += res;
}
return sum / n;
}
```
其中,binary_search_ASL函数使用递归方式实现二分查找,并统计比较次数。calculate_ASL函数遍历序列中的每个元素,调用binary_search_ASL函数查找并统计比较次数,最后计算平均查找长度。
接下来,我们需要计算满二叉树的平均查找长度ASL2。根据题目要求,当将含有n个节点的判定树看成一颗满二叉树时,其成功平均查找长度的理论值ASL2约为log2(n+1)-1。因此,我们可以使用以下代码实现:
```
double calculate_ASL2(int n) {
return log2(n + 1) - 1;
}
```
最后,我们可以使用以下代码测试程序,并输出n=11时的判定树,以及n=10、100、1000和10000时的ASL1和ASL2的值:
```
int main() {
int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
int n = sizeof(arr) / sizeof(arr[0]);
// 构造二叉树
TreeNode* root = build_binary_tree(arr, 0, n - 1);
// 输出n=11时的判定树
// 由于二叉树可能非常大,这里只输出前10层
queue<TreeNode*> q;
q.push(root);
int cur_level = 0, max_level = 10;
while (!q.empty() && cur_level < max_level) {
int size = q.size();
cout << "level " << cur_level << ": ";
for (int i = 0; i < size; i++) {
TreeNode* node = q.front();
q.pop();
if (node == NULL) {
cout << "null ";
} else {
cout << node->val << " ";
q.push(node->left);
q.push(node->right);
}
}
cout << endl;
cur_level++;
}
// 计算ASL1和ASL2的值
int arr2[] = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19};
int n2 = sizeof(arr2) / sizeof(arr2[0]);
cout << "n=10时,ASL1=" << calculate_ASL(root, arr2, n2) << ", ASL2=" << calculate_ASL2(10) << endl;
int arr3[100];
for (int i = 0; i < 100; i++) {
arr3[i] = i + 1;
}
cout << "n=100时,ASL1=" << calculate_ASL(root, arr3, 100) << ", ASL2=" << calculate_ASL2(100) << endl;
int arr4[1000];
for (int i = 0; i < 1000; i++) {
arr4[i] = i + 1;
}
cout << "n=1000时,ASL1=" << calculate_ASL(root, arr4, 1000) << ", ASL2=" << calculate_ASL2(1000) << endl;
int arr5[10000];
for (int i = 0; i < 10000; i++) {
arr5[i] = i + 1;
}
cout << "n=10000时,ASL1=" << calculate_ASL(root, arr5, 10000) << ", ASL2=" << calculate_ASL2(10000) << endl;
return 0;
}
```
阅读全文