用顺序表做二叉排序树的存储结构:读入一个整数序列(要求从磁盘文件读取),生成一棵二叉排序树,对二叉排序树作中序遍历,输出结果。计算二叉排序树T查找成功的平均查找长度。输出结果。输入元素x,查找二叉排序树,若存在,则删除该节点,并输出中序遍历结果。用C语言来书写
时间: 2023-08-27 17:29:17 浏览: 129
好的,以下是用顺序表实现二叉排序树的C语言代码:
```c
#include <stdio.h>
#include <stdlib.h>
#define MAX_SIZE 1000 // 顺序表的最大长度
typedef struct {
int data[MAX_SIZE]; // 数据
int length; // 顺序表的长度
} SeqList;
typedef struct {
int val; // 节点的值
int left_child; // 左子节点的下标
int right_child; // 右子节点的下标
} TreeNode;
int insert(SeqList *L, int val);
void inorder_traversal(SeqList *L, int i);
double calculate_avg_length(SeqList *L, int i, int depth);
int search(SeqList *L, int i, int val, int depth);
int delete(SeqList *L, int i, int val);
int find_min(SeqList *L, int i);
int main() {
SeqList L = {0}; // 初始化顺序表
int val, i, depth;
double avg_length;
FILE *fp; // 文件指针
fp = fopen("data.txt", "r"); // 以只读方式打开文件
if (fp == NULL) {
printf("文件打开失败!\n");
exit(1);
}
while (fscanf(fp, "%d", &val) != EOF) { // 从文件中读取整数序列
insert(&L, val); // 将整数插入到二叉排序树中
}
printf("中序遍历结果:");
inorder_traversal(&L, 0); // 对二叉排序树进行中序遍历
printf("\n");
depth = 0;
avg_length = calculate_avg_length(&L, 0, depth); // 计算平均查找长度
printf("查找成功的平均查找长度:%f\n", avg_length);
printf("请输入要删除的元素:");
scanf("%d", &val);
i = search(&L, 0, val, 1); // 查找要删除的节点
if (i != -1) { // 如果节点存在,则删除该节点
delete(&L, 0, val);
printf("中序遍历结果:");
inorder_traversal(&L, 0); // 输出删除后的中序遍历结果
printf("\n");
}
else {
printf("该元素不存在!\n");
}
fclose(fp); // 关闭文件
return 0;
}
// 在二叉排序树中插入一个元素
int insert(SeqList *L, int val) {
int i, j;
TreeNode node = {val, -1, -1}; // 初始化节点
if (L->length == MAX_SIZE) { // 顺序表已满
return -1;
}
if (L->length == 0) { // 二叉排序树为空
L->data[0] = node;
L->length++;
return 0;
}
i = 0;
while (i < L->length) { // 查找插入位置
if (val < L->data[i].val) { // 在左子树中查找
j = L->data[i].left_child;
if (j == -1) { // 左子节点为空,插入节点
L->data[L->length] = node;
L->data[i].left_child = L->length;
L->length++;
return 0;
}
}
else { // 在右子树中查找
j = L->data[i].right_child;
if (j == -1) { // 右子节点为空,插入节点
L->data[L->length] = node;
L->data[i].right_child = L->length;
L->length++;
return 0;
}
}
i = j;
}
return -1;
}
// 对二叉排序树进行中序遍历
void inorder_traversal(SeqList *L, int i) {
if (i == -1) {
return;
}
inorder_traversal(L, L->data[i].left_child);
printf("%d ", L->data[i].val);
inorder_traversal(L, L->data[i].right_child);
}
// 计算平均查找长度
double calculate_avg_length(SeqList *L, int i, int depth) {
if (i == -1) {
return 0;
}
double left_length = calculate_avg_length(L, L->data[i].left_child, depth + 1);
double right_length = calculate_avg_length(L, L->data[i].right_child, depth + 1);
double node_count = left_length + right_length + 1;
double prob = 1.0 / L->length;
return depth + node_count * prob;
}
// 在二叉排序树中查找一个元素
int search(SeqList *L, int i, int val, int depth) {
if (i == -1) {
return -1;
}
if (val == L->data[i].val) {
return i;
}
if (val < L->data[i].val) {
return search(L, L->data[i].left_child, val, depth + 1);
}
else {
return search(L, L->data[i].right_child, val, depth + 1);
}
}
// 删除二叉排序树中的一个元素
int delete(SeqList *L, int i, int val) {
if (i == -1) {
return -1;
}
if (val < L->data[i].val) { // 在左子树中查找要删除的节点
int j = L->data[i].left_child;
if (j == -1) {
return -1;
}
if (val == L->data[j].val) {
if (L->data[j].left_child == -1 && L->data[j].right_child == -1) { // 要删除的节点没有子节点
L->data[i].left_child = -1;
}
else if (L->data[j].left_child == -1 || L->data[j].right_child == -1) { // 要删除的节点只有一个子节点
if (L->data[j].left_child == -1) { // 左子节点为空
L->data[i].left_child = L->data[j].right_child;
}
else { // 右子节点为空
L->data[i].left_child = L->data[j].left_child;
}
}
else { // 要删除的节点有两个子节点
int k = find_min(L, L->data[j].right_child); // 在右子树中查找最小节点
L->data[j].val = L->data[k].val; // 将最小节点的值赋给要删除的节点
delete(L, L->data[j].right_child, L->data[j].val); // 删除最小节点
}
return 0;
}
else {
return delete(L, L->data[i].left_child, val);
}
}
else { // 在右子树中查找要删除的节点
int j = L->data[i].right_child;
if (j == -1) {
return -1;
}
if (val == L->data[j].val) {
if (L->data[j].left_child == -1 && L->data[j].right_child == -1) { // 要删除的节点没有子节点
L->data[i].right_child = -1;
}
else if (L->data[j].left_child == -1 || L->data[j].right_child == -1) { // 要删除的节点只有一个子节点
if (L->data[j].left_child == -1) { // 左子节点为空
L->data[i].right_child = L->data[j].right_child;
}
else { // 右子节点为空
L->data[i].right_child = L->data[j].left_child;
}
}
else { // 要删除的节点有两个子节点
int k = find_min(L, L->data[j].right_child); // 在右子树中查找最小节点
L->data[j].val = L->data[k].val; // 将最小节点的值赋给要删除的节点
delete(L, L->data[j].right_child, L->data[j].val); // 删除最小节点
}
return 0;
}
else {
return delete(L, L->data[i].right_child, val);
}
}
}
// 在二叉排序树的右子树中查找最小节点
int find_min(SeqList *L, int i) {
while (L->data[i].left_child != -1) {
i = L->data[i].left_child;
}
return i;
}
```
其中,`SeqList`是一个顺序表的结构体,用于存储二叉排序树。`TreeNode`是二叉排序树的节点结构体,包含节点的值、左子节点的下标和右子节点的下标。`insert`函数用于插入一个元素到二叉排序树中。`inorder_traversal`函数用于对二叉排序树进行中序遍历。`calculate_avg_length`函数用于计算平均查找长度。`search`函数用于在二叉排序树中查找一个元素。`delete`函数用于删除二叉排序树中的一个元素。`find_min`函数用于在二叉排序树的右子树中查找最小节点。
在`main`函数中,首先从文件中读取整数序列,并将整数插入到二叉排序树中。然后对二叉排序树进行中序遍历,并输出结果。接着计算平均查找长度,并输出结果。最后,从输入中读取要删除的元素,查找并删除该元素,并输出删除后的中序遍历结果。
阅读全文