【数据结构实验】树(一)构建二叉查找树(BST)

文章目录

  • [1. 引言](#1. 引言)
  • [2. 二叉查找树](#2. 二叉查找树)
  • [3. 实验内容](#3. 实验内容)
    • [3.1 实验题目](#3.1 实验题目)
    • [3.2 算法实现](#3.2 算法实现)
      • [1. 数据结构](#1. 数据结构)
      • [2. 全局变量](#2. 全局变量)
      • [3. 中序遍历函数InOrder](#3. 中序遍历函数InOrder)
      • [4. 二叉查找树的构建函数T](#4. 二叉查找树的构建函数T)
      • [5. 主函数](#5. 主函数)
    • [3.3 代码整合](#3.3 代码整合)
  • [4. 实验结果](#4. 实验结果)

1. 引言

二叉查找树(Binary Search Tree,BST)是一种常用的数据结构,它在计算机科学和信息处理中有着广泛的应用。BST的特点是对于树中的每个节点,其左子树的所有节点值小于当前节点的值,而右子树的所有节点值大于当前节点的值。

本实验将通过C语言构建一个二叉查找树,分析其性能计算平均查找长度。

2. 二叉查找树

二叉查找树(Binary Search Tree,BST)是一种二叉树,其中每个节点都包含一个键值(key)和对应的数据(value)。而且对于任意节点,其左子树中的所有节点的键值都小于该节点的键值,而右子树中的所有节点的键值都大于该节点的键值。

二叉查找树的这种特性使得在查找、插入和删除节点时具有高效性。通过比较目标键值和当前节点的键值,可以在树中快速定位到目标节点或确定插入、删除的位置。在平均情况下,这些操作的时间复杂度为O(log n),其中n是二叉查找树中节点的数量。

除了高效的查找操作,二叉查找树还支持有序性操作。通过中序遍历二叉查找树,可以按照键值的顺序输出树中的所有节点,从而实现对节点的有序访问。

需要注意的是,如果二叉查找树的节点插入和删除不平衡,即树的高度不均衡地增长,可能会导致查找、插入和删除操作的最坏情况时间复杂度为O(n),其中n是树中节点的数量。为了解决这个问题,可以使用自平衡的二叉查找树,如红黑树(Red-Black Tree)或AVL树,来保持树的平衡性。

3. 实验内容

3.1 实验题目

实现教材 287 页底部的算法 T,从无到有创建一棵二叉查找树,输出中根遍历序列,并编程计算查找成功时的平均查找长度。

(一)输入要求

c 复制代码
    char *A[30]={
        "THE","OF","AND","TO","A",
        "IN","THAT","IS","WAS","HE",
        "FOR","IT","WITH","AS","HIS",
        "ON","BE","AT","BY","I",
        "THIS","HAD","NOT","ARE","BUT",
        "FROM","OR","HAVE","AN","THEY",
    };

(二)输出要求

  1. 输出该二叉查找树的中根遍历序列;
  2. 输出该二叉查找树查找成功时的平均查找长度。

3.2 算法实现

1. 数据结构

c 复制代码
typedef struct P {
	char *key;
	struct P* llink;
	struct P* rlink;
} P;

2. 全局变量

c 复制代码
P *root;
int Sum = 0;

3. 中序遍历函数InOrder

c 复制代码
void InOrder(P *t)
{
	if(t==NULL) return;
	else{
		InOrder(t->llink);
		printf("%s\n",t->key);
		InOrder(t->rlink);
	}
}
  • 递归地进行中序遍历,输出节点的关键词。

4. 二叉查找树的构建函数T

c 复制代码
P* T(char *ch) {
    if (root == NULL) {
        root = (P*)malloc(sizeof(P));
        root->key = strdup(ch);
        root->llink = NULL;
        root->rlink = NULL;
        return NULL;
    }

    P* p = root;
    while (p != NULL) {
        Sum++;
        if (strcmp(ch, p->key) == 0)
            return p;
        if (strcmp(ch, p->key) < 0) {
            if (p->llink == NULL)
                break;
            else
                p = p->llink;
        }
        else {
            if (p->rlink == NULL)
                break;
            else
                p = p->rlink;
        }
    }

    P* q = (P*)malloc(sizeof(P));
    q->key = strdup(ch);
    q->llink = NULL;
    q->rlink = NULL;
    if (strcmp(ch, p->key) < 0)
        p->llink = q;
    else
        p->rlink = q;
    return NULL;
}
  • 若树为空,直接创建根节点。
  • 若树不为空,根据二叉查找树的性质找到合适的位置插入新的节点。

5. 主函数

c 复制代码
int main() {
    char *A[30]={
        "THE","OF","AND","TO","A",
        "IN","THAT","IS","WAS","HE",
        "FOR","IT","WITH","AS","HIS",
        "ON","BE","AT","BY","I",
        "THIS","HAD","NOT","ARE","BUT",
        "FROM","OR","HAVE","AN","THEY",
    };

    int M = 30, i;
    for (i = 0; i < M; i++) {
        char *ch;
        ch = A[i];
        P* s = T(ch);
    }

    printf("中序遍历:\n");
    InOrder(root);

    Sum = 0;
    for (i = 0; i < M; i++) {
        char *ch;
        ch = A[i];
        P* s = T(ch);
    }

    printf("平均查找长度为%f", (float)Sum / M);

    // 释放节点的关键词内存
    for (i = 0; i < M; i++) {
        free(A[i]);
    }

    return 0;
}
  • 利用关键词数组 A 构建二叉查找树。
  • 输出中序遍历结果。
  • 再次构建二叉查找树,计算平均查找长度,并输出。

3.3 代码整合

c 复制代码
#include<stdio.h>
#include<string.h>
#include<malloc.h>

typedef struct P {
    char *key;
    struct P* llink;
    struct P* rlink;
} P;

P *root;
int Sum = 0;

void InOrder(P *t) {
    if (t == NULL)
        return;
    else {
        InOrder(t->llink);
        printf("%s\n", t->key);
        InOrder(t->rlink);
    }
}

P* T(char *ch) {
    if (root == NULL) {
        root = (P*)malloc(sizeof(P));
        root->key = strdup(ch);
        root->llink = NULL;
        root->rlink = NULL;
        return NULL;
    }

    P* p = root;
    while (p != NULL) {
        Sum++;
        if (strcmp(ch, p->key) == 0)
            return p;
        if (strcmp(ch, p->key) < 0) {
            if (p->llink == NULL)
                break;
            else
                p = p->llink;
        }
        else {
            if (p->rlink == NULL)
                break;
            else
                p = p->rlink;
        }
    }

    P* q = (P*)malloc(sizeof(P));
    q->key = strdup(ch);
    q->llink = NULL;
    q->rlink = NULL;
    if (strcmp(ch, p->key) < 0)
        p->llink = q;
    else
        p->rlink = q;
    return NULL;
}

int main() {
    char *A[30]={
        "THE","OF","AND","TO","A",
        "IN","THAT","IS","WAS","HE",
        "FOR","IT","WITH","AS","HIS",
        "ON","BE","AT","BY","I",
        "THIS","HAD","NOT","ARE","BUT",
        "FROM","OR","HAVE","AN","THEY",
    };

    int M = 30, i;
    for (i = 0; i < M; i++) {
        char *ch;
        ch = A[i];
        P* s = T(ch);
    }

    printf("中序遍历:\n");
    InOrder(root);

    Sum = 0;
    for (i = 0; i < M; i++) {
        char *ch;
        ch = A[i];
        P* s = T(ch);
    }

    printf("平均查找长度为%f", (float)Sum / M);

    // 释放节点的关键词内存
    for (i = 0; i < M; i++) {
        free(A[i]);
    }

    return 0;
}

4. 实验结果

c 复制代码
中序遍历:
A
AN
AND
ARE
AS
AT
BE
BUT
BY
FOR
FROM
HAD
HAVE
HE
HIS
I
IN
IS
IT
NOT
OF
ON
OR
THAT
THE
THEY
THIS
TO
WAS
WITH
平均查找长度为5.433333
相关推荐
贝塔西塔13 分钟前
一文读懂动态规划:多种经典问题和思路
算法·leetcode·动态规划
众链网络40 分钟前
AI进化论08:机器学习的崛起——数据和算法的“二人转”,AI“闷声发大财”
人工智能·算法·机器学习
1 小时前
Unity开发中常用的洗牌算法
java·算法·unity·游戏引擎·游戏开发
飒飒真编程2 小时前
C++类模板继承部分知识及测试代码
开发语言·c++·算法
GeminiGlory2 小时前
算法练习6-大数乘法(高精度乘法)
算法
熬了夜的程序员3 小时前
【华为机试】HJ61 放苹果
算法·华为·面试·golang
森焱森3 小时前
一文理解锂电池充电、过放修复与电量测量:从原理到实战
c语言·单片机·架构
马特说3 小时前
基于随机森林的金融时间序列预测系统:从数据处理到实时预测的完整流水线
算法·随机森林·金融
呆呆的小鳄鱼3 小时前
leetcode:HJ18 识别有效的IP地址和掩码并进行分类统计[华为机考][字符串]
算法·leetcode·华为
艾莉丝努力练剑4 小时前
【C语言】学习过程教训与经验杂谈:思想准备、知识回顾(五)
c语言·开发语言·数据结构·学习·算法