【数据结构实验】树(一)构建二叉查找树(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
相关推荐
唐叔在学习几秒前
【唐叔学算法】第21天:超越比较-计数排序、桶排序与基数排序的Java实践及性能剖析
数据结构·算法·排序算法
ALISHENGYA20 分钟前
全国青少年信息学奥林匹克竞赛(信奥赛)备考实战之分支结构(switch语句)
数据结构·算法
chengooooooo22 分钟前
代码随想录训练营第二十七天| 贪心理论基础 455.分发饼干 376. 摆动序列 53. 最大子序和
算法·leetcode·职场和发展
jackiendsc29 分钟前
Java的垃圾回收机制介绍、工作原理、算法及分析调优
java·开发语言·算法
FeboReigns41 分钟前
C++简明教程(文章要求学过一点C语言)(1)
c语言·开发语言·c++
FeboReigns44 分钟前
C++简明教程(文章要求学过一点C语言)(2)
c语言·开发语言·c++
游是水里的游2 小时前
【算法day20】回溯:子集与全排列问题
算法
_小柏_2 小时前
C/C++基础知识复习(43)
c语言·开发语言·c++
yoyobravery2 小时前
c语言大一期末复习
c语言·开发语言·算法
Jiude2 小时前
算法题题解记录——双变量问题的 “枚举右,维护左”
python·算法·面试