写完整C代码,建立由有序序列进行二分查找产生的判定树,使其具有如下功能: 1.输出n=11时的判定树并求成功情况下的平均查找长度ASL; 2.通过构造判定树可以求得成功情况下的平均查找长度ASL1; 3.当将含有n个节点的判定树看成一颗满二叉树时,其成功平均查找长度的理论值ASL2约为log2(n+1)-1; 4.对于n=10、100、1000和10000,求出其ASL1和ASL2的值;
时间: 2024-03-20 21:40:19 浏览: 16
好的,下面是完整的C代码实现:
```
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
typedef struct TreeNode {
int val;
struct TreeNode* left;
struct TreeNode* right;
} TreeNode;
// 递归构造判定树
TreeNode* buildTree(int* nums, int start, int end) {
if (start > end) return NULL; // 叶子节点
int mid = (start + end) / 2;
TreeNode* root = (TreeNode*)malloc(sizeof(TreeNode));
root->val = nums[mid];
root->left = buildTree(nums, start, mid - 1);
root->right = buildTree(nums, mid + 1, end);
return root;
}
// 递归遍历判定树查找指定值的节点
TreeNode* find(TreeNode* root, int val) {
if (root == NULL || root->val == val) return root;
if (val < root->val) return find(root->left, val);
else return find(root->right, val);
}
// 计算判定树的深度
int depth(TreeNode* root) {
if (root == NULL) return 0;
int leftDepth = depth(root->left);
int rightDepth = depth(root->right);
return 1 + (leftDepth > rightDepth ? leftDepth : rightDepth);
}
// 计算成功情况下的平均查找长度ASL1
double ASL1(TreeNode* root, int* nums, int n) {
double sum = 0;
for (int i = 0; i < n; i++) {
sum += depth(find(root, nums[i]));
}
return sum / n;
}
int main() {
int nums[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
int n = sizeof(nums) / sizeof(nums[0]);
// 构造判定树
TreeNode* root = buildTree(nums, 0, n - 1);
// 输出判定树
printf("判定树:\n");
printf(" %d\n", root->val);
printf(" %d %d\n", root->left->val, root->right->val);
printf("%d %d %d %d\n", root->left->left->val, root->left->right->val, root->right->left->val, root->right->right->val);
printf(" %d %d\n", root->right->left->right->val, root->right->right->right->val);
// 计算ASL1和ASL2
double asl1 = ASL1(root, nums, n);
double asl2 = log2(n + 1) - 1;
// 输出结果
printf("\n成功情况下的平均查找长度ASL1:%f\n", asl1);
printf("成功情况下的平均查找长度ASL2:%f\n", asl2);
// 对于n=10、100、1000和10000,求出其ASL1和ASL2的值
for (int i = 1; i <= 4; i++) {
int nn = pow(10, i);
int* nums1 = (int*)malloc(nn * sizeof(int));
for (int j = 0; j < nn; j++) {
nums1[j] = j + 1;
}
// 随机打乱序列
for (int j = nn - 1; j > 0; j--) {
int k = rand() % (j + 1);
int temp = nums1[j];
nums1[j] = nums1[k];
nums1[k] = temp;
}
// 排序
qsort(nums1, nn, sizeof(int), cmp);
// 构造判定树
TreeNode* root1 = buildTree(nums1, 0, nn - 1);
// 计算ASL1和ASL2
double asl11 = ASL1(root1, nums1, nn);
double asl22 = log2(nn + 1) - 1;
// 输出结果
printf("\n对于n=%d,ASL1=%f,ASL2=%f\n", nn, asl11, asl22);
free(nums1);
}
return 0;
}
// 比较函数用于qsort排序
int cmp(const void* a, const void* b) {
return *(int*)a - *(int*)b;
}
```
注意:本代码中的判定树是基于有序序列构造的,因此输入的序列必须是有序的。如果输入的序列无序,需要先进行排序。