数据结构实验十:树表查找+哈希查找

本节课实验课总体安排:

1、讲解4道选择题;

2、讲解平衡二叉树的构造,输出二叉树的中序遍历序列,判断该二叉树是否为平衡二叉树;

3、完成两道力扣题:二叉树的中序遍历+平衡二叉树的判断

一、选择题

1、【历年期末试题】设散列表表长 m =14,散列函数 H(K)= k mod 11,表中已经有15、38、61、84四个元素,如果用线形探测法处理冲突,则元素49的存储地址是()

✅ 计算 49 的初始散列地址

散列函数:
[H(k) = k mod 11]

[49 mod 11 = 49 - 44 = 5]

初始地址 = 5

✅ 查看表中已有元素的地址

元素(k \mod 11)地址
1515 mod 11 = 44
3838 mod 11 = 55
6161 mod 11 = 66
8484 mod 11 = 77

占用地址:4, 5, 6, 7

✅ 用线性探测法查找下一个空位置

49 初始地址:5

  • 地址 5:被 38 占用 → 冲突

  • 地址 6:被 61 占用 → 冲突

  • 地址 7:被 84 占用 → 冲突

  • 地址 8:空位

🎯最终结果:49 的存储地址 = 8

2、 折半查找有序表(4,6,10,12,20,30,50,70,88,100)。若查找表中元素58,则它将依次与表中()比较大小,查找结果是失败。

✅ 有序表

索引(0~9)对应表中元素:

下标0123456789
元素4610122030507088100

🔍 开始折半查找 58

① 第一次比较

low = 0, high = 9
mid = (0 + 9) / 2 = 4

比较元素:20

58 > 20 → 去右半段(5~9)

② 第二次比较

low = 5, high = 9
mid = (5 + 9) / 2 = 7

比较元素:70

58 < 70 → 去左半段(5~6)

③ 第三次比较

low = 5, high = 6
mid = (5 + 6) / 2 = 5

比较元素:30

58 > 30 → 去右半段(6~6)

④ 第四次比较

low = 6, high = 6
mid = 6

比较元素:50

58 > 50 → 去右半段(7~6),查找失败。

🎯 最终比较序列

依次比较了:20 → 70 → 30 → 50

二、程序题

#include <stdio.h>
#include <stdlib.h>

typedef int ElemType;

// --------- 二叉链表结构 ---------
typedef struct BTNode {
    ElemType data;
    struct BTNode *lchild, *rchild;
} BTNode, *BTree;

// --------- 构建二叉树:先序输入,0 表示空 ---------
int CreateBTree(BTree *T) {
    int x;
    if (scanf("%d", &x) != 1) return 0; // 输入失败
    if (x == 0) {
        *T = NULL;
        return 1;
    } else {
        *T = (BTree)malloc(sizeof(BTNode));
        if (*T == NULL) {
            fprintf(stderr, "内存分配失败\n");
            exit(1);
        }
        (*T)->data = x;
        if (!CreateBTree(&((*T)->lchild))) return 0;
        if (!CreateBTree(&((*T)->rchild))) return 0;
        return 1;
    }
}

// --------- 中序遍历(无全局变量,参数 first 控制空格) ---------
void InOrder(BTree T, int *first) {
    if (T == NULL) return;

    InOrder(T->lchild, first);

    if (*first) {
        printf("%d", T->data);
        *first = 0;
    } else {
        printf(" %d", T->data);
    }

    InOrder(T->rchild, first);
}

// --------- 判断是否平衡二叉树(AVL) ---------
int IsBalanced(BTree T, int *height) {
    if (T == NULL) {
        *height = 0;
        return 1;
    }

    int lh = 0, rh = 0;

    int left_balanced = IsBalanced(T->lchild, &lh);
    int right_balanced = IsBalanced(T->rchild, &rh);

    *height = (lh > rh ? lh : rh) + 1;

    if (!left_balanced || !right_balanced) return 0;
    if (abs(lh - rh) > 1) return 0;

    return 1;
}

// --------- 释放二叉树内存 ---------
void DestroyTree(BTree T) {
    if (T == NULL) return;
    DestroyTree(T->lchild);
    DestroyTree(T->rchild);
    free(T);
}

int main() {
    BTree T = NULL;
    if (!CreateBTree(&T)) {
        fprintf(stderr, "二叉树构造失败\n");
        return 1;
    }

    // 输出中序遍历
    int first = 1;
    InOrder(T, &first);
    printf("\n");

    // 判断是否平衡
    int height;
    int ok = IsBalanced(T, &height);
    printf("%d\n", ok);

    // 释放内存
    DestroyTree(T);

    return 0;
}

三、代码讲解

1️⃣ 头文件与类型定义

#include <stdio.h>    
#include <stdlib.h>
  • stdio.h:提供 scanfprintf 等输入输出函数。

  • stdlib.h:提供 mallocfreeexit 等动态内存和程序控制函数。

typedef int ElemType;
  • ElemType:节点存储的数据类型。

    • 类型int

    • 用途:二叉树节点保存的数据。

    • 设计意义:可灵活修改为其他类型,如 floatchar

typedef struct BTNode {
    ElemType data;            // 节点存储的值
    struct BTNode *lchild;    // 左子树指针
    struct BTNode *rchild;    // 右子树指针
} BTNode, *BTree;
  • BTNode:二叉树节点结构体。

    • data:存储节点值

    • lchild:指向左子树

    • rchild:指向右子树

  • BTreeBTNode* 类型,表示二叉树指针,便于函数传递。


2️⃣ 构建二叉树函数 CreateBTree

int CreateBTree(BTree *T) {
  • TBTree* 类型,指向二叉树节点指针。

    • 用途:函数内部修改节点地址可以回传到上一层递归。

    int x;
  • x:存储当前节点的输入值。

    • 用途:暂存用户输入的数据,决定当前节点值或空节点。

    if (scanf("%d", &x) != 1) return 0;
  • 功能:从标准输入读取一个整数存入 x

  • 变量解释x 保存输入值

  • 设计意义:防止输入非法导致程序崩溃,返回 0 表示失败。

    if (x == 0) {
        *T = NULL;
        return 1;
    } else {
  • *T:当前节点指针

  • 功能:输入为 0 表示空节点,直接置空并返回构造成功。

  • 设计意义:递归终止条件。

        *T = (BTree)malloc(sizeof(BTNode));
  • *T:分配节点的指针

  • 功能:为当前节点动态申请内存。

        if (*T == NULL) {
            fprintf(stderr, "内存分配失败\n");
            exit(1);
        }
  • 功能:检查 malloc 是否成功,失败退出程序。

  • 变量*T 是分配的节点。

        (*T)->data = x;
  • (*T)->data:节点存储的值

  • 功能:将输入值赋给节点。

        if (!CreateBTree(&((*T)->lchild))) return 0;
        if (!CreateBTree(&((*T)->rchild))) return 0;
  • (*T)->lchild:左子树指针

  • (*T)->rchild:右子树指针

  • 功能:递归创建左、右子树。

  • 设计意义:二叉树递归构造,根→左→右。

        return 1;
    }
}
  • 返回值:1 表示当前节点及子树构造成功。


3️⃣ 中序遍历函数 InOrder

void InOrder(BTree T, int *first) {
  • T:当前节点

  • first:整型指针,控制输出格式,首元素不加空格,后续加空格。

    if (T == NULL) return;
  • 功能:空节点直接返回,递归终止条件。

    InOrder(T->lchild, first);
  • T->lchild:左子树指针

  • 功能:递归遍历左子树(中序遍历顺序)。

    if (*first) {
        printf("%d", T->data);
        *first = 0;
    } else {
        printf(" %d", T->data);
    }
  • T->data:当前节点值

  • *first:控制输出空格

  • 功能:格式化输出节点值。

  • 设计意义:保证输出严格按照题目要求。

    InOrder(T->rchild, first);
}
  • T->rchild:右子树指针

  • 功能:递归遍历右子树,完成中序遍历。


4️⃣ 判断平衡二叉树:IsBalanced

int IsBalanced(BTree T, int *height) {
  • T:当前节点

  • height:返回当前节点的子树高度

    if (T == NULL) {
        *height = 0;
        return 1;
    }
  • 变量说明

    • 空树高度为 0,视为平衡

  • 用途:递归基准条件。

    int lh = 0, rh = 0;
  • lh:左子树高度

  • rh:右子树高度

    int left_balanced = IsBalanced(T->lchild, &lh);
    int right_balanced = IsBalanced(T->rchild, &rh);
  • left_balanced:左子树是否平衡

  • right_balanced:右子树是否平衡

  • lhrh:子树高度返回值

  • 功能:递归判断子树平衡,同时获取高度。

    *height = (lh > rh ? lh : rh) + 1;
  • *height:当前节点高度

  • 用途:左、右子树高度最大值 + 1,供上一层使用。

    if (!left_balanced || !right_balanced) return 0;
    if (abs(lh - rh) > 1) return 0;
  • 判断条件

    • 子树不平衡或高度差 > 1,则当前节点不平衡

  • 返回值:0 表示不平衡,1 表示平衡

    return 1;
}
  • 当前节点平衡,返回 1


5️⃣ 释放二叉树:DestroyTree

void DestroyTree(BTree T) {
    if (T == NULL) return;
  • T:当前节点指针

  • 空节点直接返回,递归终止。

    DestroyTree(T->lchild);
    DestroyTree(T->rchild);
  • 左、右子树递归释放内存。

    free(T);
}
  • 释放当前节点内存。


6️⃣ 主函数 main

int main() {
    BTree T = NULL;
  • T:二叉树根节点指针,初始为空。

    if (!CreateBTree(&T)) {
        fprintf(stderr, "二叉树构造失败\n");
        return 1;
    }
  • 构建二叉树,并检查成功

  • 错误处理,防止程序异常。

    int first = 1;
    InOrder(T, &first);
    printf("\n");
  • first:控制中序遍历输出格式

  • 调用中序遍历并打印节点值

    int height;
    int ok = IsBalanced(T, &height);
    printf("%d\n", ok);
  • height:二叉树高度

  • ok:是否平衡,1=平衡,0=不平衡

    DestroyTree(T);
    return 0;
}
  • 释放二叉树内存,正常退出程序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值