【数据结构实验】树(一)构建二叉查找树(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
相关推荐
EricWang135821 分钟前
[OS] 项目三-2-proc.c: exit(int status)
服务器·c语言·前端
我是谁??23 分钟前
C/C++使用AddressSanitizer检测内存错误
c语言·c++
小码农<^_^>25 分钟前
优选算法精品课--滑动窗口算法(一)
算法
羊小猪~~27 分钟前
神经网络基础--什么是正向传播??什么是方向传播??
人工智能·pytorch·python·深度学习·神经网络·算法·机器学习
软工菜鸡1 小时前
预训练语言模型BERT——PaddleNLP中的预训练模型
大数据·人工智能·深度学习·算法·语言模型·自然语言处理·bert
南宫生1 小时前
贪心算法习题其三【力扣】【算法学习day.20】
java·数据结构·学习·算法·leetcode·贪心算法
希言JY1 小时前
C字符串 | 字符串处理函数 | 使用 | 原理 | 实现
c语言·开发语言
午言若1 小时前
C语言比较两个字符串是否相同
c语言
AI视觉网奇1 小时前
sklearn 安装使用笔记
人工智能·算法·sklearn
JingHongB2 小时前
代码随想录算法训练营Day55 | 图论理论基础、深度优先搜索理论基础、卡玛网 98.所有可达路径、797. 所有可能的路径、广度优先搜索理论基础
算法·深度优先·图论