二叉排序树与平衡二叉树的实现-数据结构课设

题目:二叉排序树与平衡二叉树的实现

【问题描述】

设计并实现一个算法,分别用二叉链表和顺序表,实现对二叉排序树和平衡二叉树的的
操作。

【需求分析】

1 ) 从磁盘文件 L.txt 中读入一组整型数据。
2 ) 将读出的数据建成二叉排序树。
3 ) 输入该二叉排序树的根结点,输出中序遍历结果。
4 ) 输入二叉排序树的根结点,计算该二叉排序树的平均查找长度并输出。
5 ) 输入要删除的数据,定位到该结点,并删除。
6 ) 输入删除结点后的二叉排序树根结点,输出该二叉排序树的中序遍历结果。
7 ) 读入一组数生成一棵平衡的二叉排序树,若插入或删除一个元素后,该二叉排
序树不平衡,则将它转化为平衡的二叉排序树。
8 ) 输入平衡的二叉排序树的根结点,计算平衡的二叉树的平均查找长度并输出。
9 ) 读入一组数存入顺序表中,生成一颗二叉排序树。、
10 ) 输入该二叉排序树的根结点,输出中序遍历结果。
11 ) 输入该二叉排序树的根结点,计算该二叉排序树的平均查找长度并输出。
12 ) 输入要删除的数据,定位到该结点,并删除。
13 ) 输入删除结点后的二叉排序树根结点,输出该二叉排序树的中序遍历结果。

【算法设计和实现】

主要函数

{
BSTNode * createNode( int data ); //创建一新结点
BSTNode * insertBST( BSTNode * root , int data ); //插入一个结点到二叉排序树
void inorderTraversal( BSTNode * root ); //中序遍历二叉排序树
float averageSearchLenth( BSTNode * root , int level ); //计算二叉排序树的平均查找长度
BSTNode * deleteNode( BSTNode * root , int data ); //在二叉排序树中查找并删除指定元素
//平衡二叉树的操作
int getHeight( AVLNode * node ); //计算树的高度
int getmax( int a , int b ); //比较两者获取最大值
AVLNode * createAVLNode( int data ); //创建一个平衡二叉树结点
AVLNode * insertAVL( AVLNode * root , int data ); //插入一个结点到平衡二叉树
void inorderTraversalAVL( AVLNode * root ); //中序遍历平衡二叉树
float averageSearchLengthAVL( AVLNode * root , int level ); //计算平衡二叉树的平均查找长度
AVLNode * deleteNodeAVL( AVLNode * root , int data ); //删除平衡二叉树内指定的元素
AVLNode * rotateRight( AVLNode * tree ); //右旋转
AVLNode * rotateLeft( AVLNode * tree ); //左旋转
AVLNode * rotateRight_Left( AVLNode * tree ); //先右旋,再左旋
AVLNode * rotateLeft_Right( AVLNode * tree ); //先左旋,再右旋
int getBalanceFactor( AVLNode * node ); //获取平衡因子
//顺序表构建二叉排序树
void insertSeqList( SeqList * list , BSTNode * node ); //在顺序表中插入一个结点
BSTNode * buildBSTFromSeqList( SeqList * List ); //根据顺序表构建二叉排序树
}

存储结构

{
//二叉排序树的结点结构
typedef struct BSTNode {
int data; //结点存储的数据
struct BSTNode * left; //左孩子指针
struct BSTNode * right; //右孩子指针
} BSTNode ;
//平衡二叉树的结点结构
typedef struct AVLNode {
int data; //结点存储的数据
int height; //结点的高度
struct AVLNode * left; //左孩子指针
struct AVLNode * right; //右孩子指针
} AVLNode ;
//顺序表结构体
typedef struct {
BSTNode * data[ MAX_SIZE ]; //顺序表数组指针
int length; //顺序表长度
} SeqList ;
}

源程序代码:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#define MAX_SIZE 100
//二叉排序树的结点结构
typedef struct BSTNode {
int data;//结点存储的数据
struct BSTNode* left;//左孩子指针
struct BSTNode* right;//右孩子指针
}BSTNode;
//平衡二叉树的结点结构
typedef struct AVLNode {
int data;//结点存储的数据
int height;//结点的高度
struct AVLNode* left;//左孩子指针
struct AVLNode* right;//右孩子指针
}AVLNode;
//顺序表结构体
typedef struct {
BSTNode* data[MAX_SIZE];//顺序表数组指针
int length;//顺序表长度
}SeqList;
//二叉链表
//二叉排序树的操作
BSTNode* createNode(int data);//创建一新结点
BSTNode* insertBST(BSTNode* root, int data);//插入一个结点到二叉排序树
void inorderTraversal(BSTNode* root);//中序遍历二叉排序树
float averageSearchLenth(BSTNode* root, int level);//计算二叉排序树的平均查找长度
BSTNode* deleteNode(BSTNode* root, int data);//在二叉排序树中查找并删除指定元素
//平衡二叉树的操作
int getHeight(AVLNode* node);//计算树的高度
int getmax(int a, int b);//比较两者获取最大值
AVLNode* createAVLNode(int data);//创建一个平衡二叉树结点
AVLNode* insertAVL(AVLNode* root, int data);//插入一个结点到平衡二叉树
void inorderTraversalAVL(AVLNode* root);//中序遍历平衡二叉树
float averageSearchLengthAVL(AVLNode* root, int level);//计算平衡二叉树的平均查找长度
AVLNode* deleteNodeAVL(AVLNode* root, int data);//删除平衡二叉树内指定的元素
AVLNode* rotateRight(AVLNode* tree);//右旋转
AVLNode* rotateLeft(AVLNode* tree);//左旋转
AVLNode* rotateRight_Left(AVLNode* tree);//先右旋,再左旋
AVLNode* rotateLeft_Right(AVLNode* tree);//先左旋,再右旋
int getBalanceFactor(AVLNode* node);//获取平衡因子
//顺序表构建二叉排序树
void insertSeqList(SeqList* list, BSTNode* node);//在顺序表中插入一个结点
BSTNode* buildBSTFromSeqList(SeqList* List);//根据顺序表构建二叉排序树
BSTNode* createNode(int data) {
BSTNode* newnode = (BSTNode*)malloc(sizeof(BSTNode));
newnode->data = data;
newnode->left = NULL;
newnode->right = NULL;
return newnode;
}
BSTNode* insertBST(BSTNode* root, int data) {
if (!root) {//如果 root 不存在
root=createNode(data);//创建一个新结点为根结点
}
else if(data<root->data) {
root->left = insertBST(root->left, data);//如果插入值小于当前结点的值,则递归插入到左子树
}
else if (data > root->data) {
root->right = insertBST(root->right, data);//如果插入值大于当前结点的值,则递归插入到右子树
}
else {
return root;//重复的值不插入
}
return root;
}
void inorderTraversal(BSTNode* root) {
if (root) {//用递归实现中序遍历
inorderTraversal(root->left);//递归遍历左子树
printf("%d", root->data);//输出当前结点的值
inorderTraversal(root->right);//递归遍历右子树
}
}
float averageSearchLenth(BSTNode* root,int level) {
static int sum=0;
static int count=0;
if (root != NULL) {
sum += level;//累加每个结点的层级
count++;//统计结点个数
averageSearchLenth(root->left, level + 1);//递归遍历左子树
averageSearchLenth(root->right, level + 1);//递归遍历右子树
}
//返回平均查找长度
return (float)sum / count;
}
BSTNode* deleteNode(BSTNode* root, int data) {
if (root == NULL) {
//树为空,没有找到要删除的结点
printf("无%d\n",data);
return root;
}
if (data < root->data) {
//在左子树中递归删除结点
root->left = deleteNode(root->left, data);
}
else if (data > root->data) {
//在右子树中递归删除结点
root->right = deleteNode(root->right, data);
}
else {
//找到了要删除的结点
if (root->left == NULL) {
//如果该结点没有左孩子,直接将右孩子接入其父结点
BSTNode* temp = root->right;
free(root);
return temp;
}
else if (root->right == NULL) {
//如果该结点没有右孩子,直接将左孩子接入其父结点
BSTNode* temp = root->left;
free(root);
return temp;
}
//如果该结点有两个子树,找到右子树中的最小结点(或左子树中最大的结点)替换当前要删除
的结点
BSTNode* minNode = root->right;
while (minNode->left!= NULL) {
minNode = minNode->left;
}
root->data = minNode->data;//用右子树中最小的结点替换当前结点
root->right=deleteNode(root->right, minNode->data);//删除右子树中最小的结点
}
return root;
}
int getHeight(AVLNode* node) {
if (node == NULL)
return 0;
return node->height;
}
int getmax(int a, int b) {
return (a > b) ? a : b;
}
AVLNode* createAVLNode(int data) {
AVLNode* newnode = (AVLNode*)malloc(sizeof(AVLNode));
newnode->data = data;
newnode->left = NULL;
newnode->right = NULL;
newnode->height = 1;
return newnode;
}
AVLNode* rotateRight(AVLNode* tree) {
//传入 tree 是根结点,也是失衡结点
//k 是我最终要返回的结点
AVLNode* k = tree->left;
tree->left = k->right;//将 tree 的左孩子指针指向 k 的右孩子
k->right = tree;//将 k 的右孩子指针指向 tree,实现右转
//旋转完成以后,调整树的高度
//需要通过左右子树的深度来调整被旋转结点的深度
tree->height = getmax(getHeight(tree->left), getHeight(tree->right)) + 1;
k->height = getmax(getHeight(k->left), getHeight(k->right)) + 1;
return k;//此时 k 为根结点
}
AVLNode* rotateLeft(AVLNode* tree) {
//传入 tree 是根结点,也是失衡结点
//k 是我最终要返回的结点
AVLNode* k = tree->right;
tree->right = k->left;//将 tree 的右孩子指针指向 k 的左孩子
k->left = tree;//将 k 的左孩子指针指向 tree,实现左转
//旋转完成以后,调整树的高度
//需要通过左右子树的深度来调整被旋转结点的深度
tree->height = getmax(getHeight(tree->left), getHeight(tree->right)) + 1;
k->height = getmax(getHeight(k->left), getHeight(k->right)) + 1;
return k;//此时 k 为根结点
}
AVLNode* rotateRight_Left(AVLNode* tree) {
//在右孩子的左子树中插入一个结点导致失衡的情况
tree->right = rotateRight(tree->right);//以右孩子为根结点将右子树右旋
tree = rotateLeft(tree);//自身左旋
return tree;
}
AVLNode* rotateLeft_Right (AVLNode* tree) {
//在左孩子的右子树中插入一个结点导致失衡的情况
tree->left = rotateLeft(tree->left);//以左孩子为根结点将左子树左旋
tree = rotateRight(tree);//自身右旋
return tree;
}
int getBalanceFactor(AVLNode* node) {
if (node == NULL) {
return 0;
}
return getHeight(node->left) - getHeight(node->right);
}
AVLNode* insertAVL(AVLNode* root, int data) {
if (root == NULL) {// 如果根结点不存在,创建一个新结点为根结点
return createAVLNode(data);
}
else if (data < root->data) {//如果插入值小于当前结点的值,则递归插入到左子树
root->left = insertAVL(root->left, data);
}
else if (data > root->data) {//如果插入值大于当前结点的值,则递归插入到右子树
root->right = insertAVL(root->right, data);
}
else {
//重复的值不添加
return root;
}
//调整新结点的高度
root->height = 1 + getmax(getHeight(root->left), getHeight(root->right));
int balance = getBalanceFactor(root);//获取新结点的平衡因子,判断是否失衡
if (balance > 1 && data < root->left->data) {//在左孩子的左子树中插入新结点的情况
return rotateRight(root);
}
if (balance > 1 && data > root->left->data) {//在左孩子的右子树中插入新结点的情况
return rotateLeft_Right(root);
}
if (balance < -1 && data < root->right->data){//在右孩子的左子树中插入新结点的情况
return rotateRight_Left(root);
}
if (balance < -1 && data > root->right->data) {//在右孩子的右子树中插入新结点的情况
return rotateLeft(root);
}
return root;
}
void inorderTraversalAVL(AVLNode* root) {
if (root) {//递归实现平衡二叉树中序遍历
inorderTraversalAVL(root->left);//递归遍历左子树
printf("%d", root->data);//输出当前结点的值
inorderTraversalAVL(root->right);//递归遍历右子树
}
}
float averageSearchLengthAVL(AVLNode* root, int level) {
static int sum = 0;
static int count = 0;
if (root != NULL) {
sum += level;//累加每个结点的层级
count++;//统计结点个数
averageSearchLengthAVL(root->left, level + 1);//递归遍历左子树
averageSearchLengthAVL(root->right, level + 1);//递归遍历右子树
}
//返回平均查找长度
return (float)sum / count;
}
AVLNode* deleteNodeAVL(AVLNode* root, int data) {
if (root == NULL) {//根结点不存在的情况
printf("无%d", data);
return root;
}
if (data < root->data) {
//在左子树中递归删除结点
root->left = deleteNodeAVL(root->left, data);
}
else if (data > root->data) {
//在右子树中递归删除结点
root->right = deleteNodeAVL(root->right, data);
}
else {
//找到要删除的结点
if (root->left == NULL) {
//如果该结点没有左孩子,直接将右孩子接入其父结点
AVLNode* temp = root->right;
free(root);
return temp;
}
else if (root->right == NULL) {
//如果该结点没有右孩子,直接将左孩子接入其父结点
AVLNode* temp = root->left;
free(root);
return temp;
}
else {
//若左右孩子都存在,找到右子树中最小的结点替换该结点
AVLNode* minNode = root->left;
while (minNode->left) {
minNode = minNode->left;
}
root->data = minNode->data;
root->right = deleteNodeAVL(root->right, minNode->data);
}
}
root->height = 1+getmax(getHeight(root->left), getHeight(root->right));//调整根结点高度
int balance = getBalanceFactor(root);//获取平衡因子,判断是否失衡
if (balance > 1 && getBalanceFactor(root->left) >= 0 ) {//左左情况
return rotateRight(root);
}
if (balance > 1 && getBalanceFactor(root->left) < 0 ) {//左右情况
return rotateLeft_Right(root);
}
if (balance < 1 && getBalanceFactor(root->right) <= 0) {//右右情况
return rotateLeft(root);
}
if (balance < 1 && getBalanceFactor(root->right) > 0) {//右左情况
return rotateRight_Left(root);
}
return root;
void insertSeqList(SeqList* list, BSTNode* node) {
if (list->length == MAX_SIZE) {
printf("顺序表已满\n");
return;
}
list->data[list->length++] = node;
}
BSTNode* buildBSTFromSeqList(SeqList* list) {
BSTNode* root = NULL;//根结点
for (int i = 0; i < list->length; i++) {//遍历顺序表中所有的元素
BSTNode* node = list->data[i];//设置 node 作为临时变量保存当前需要插入的结点
if (root == NULL) {//若根结点不存在,则将 node 作为根结点
root = node;
}
else {
BSTNode* current = root;//从根结点开始向下比较
while (1) {
if (node->data < current->data) {//若 node 的值比 current 小,则与 current 的左子树中的
值作比较
if (current->left == NULL) {//左子树为空,直接插入
current->left = node;
break;
}
else {//左子树不为空,则将 current 指针指向他的左孩子
current = current->left;
}
}
else {//若 node 的值比 current 大,则与 current 的右子树中的值作比较
if (current->right == NULL) {//右子树为空,直接插入
current->right = node;
break;
}
else {//右子树不为空,则将 current 指针指向他的右孩子
current = current->right;
}
}
}
}
}
return root;
}
int main() {
//二叉排序树
BSTNode* T1 = NULL;
//从文本文件中读取整数序列并生成二叉排序树
FILE* file = fopen("./L.txt","r");//打开本文文件 L.txt
if (file == NULL) {//如果文件不存在
printf("无法打开文件\n");
return 0;
}
int num;
while (fscanf(file, "%d", &num) != EOF) {
T1 = insertBST(T1, num);//建立二叉排序树
}
fclose(file);
//中序遍历二叉排序树
printf("该二叉树的中序遍历结果为:");
inorderTraversal(T1);
printf("\n");
//计算二叉排序树的平均查找长度
float average_Search_Lenth = averageSearchLenth(T1,1);
printf("该二叉树的平均查找长度为:%f",average_Search_Lenth);
printf("\n");
//查找并删除指定元素结点
int x;
printf("输入要删除的元素:");
scanf("%d", &x);
T1 = deleteNode(T1, x);
//中序遍历删除结点后的二叉排序树
printf("删除元素后的二叉排序树的中序遍历结果为:");
inorderTraversal(T1);
printf("\n");
//平衡二叉树
AVLNode* BT = NULL;
file= fopen("./L.txt", "r");
if (file == NULL) {
printf("无法打开文件\n");
return 0;
}
while (fscanf(file, "%d", &num) != EOF) {
BT = insertAVL(BT, num);
}
fclose(file);
printf("平衡二叉树的中序遍历结果:");
inorderTraversalAVL(BT);
printf("\n");
float average_LenthAVL = averageSearchLengthAVL(BT, 1);
printf("平衡二叉树的平均查找长度为:%f", average_LenthAVL);
printf("\n");
printf("输入要查找并删除的元素:");
scanf("%d", &x);
BT = deleteNodeAVL(BT, x);
printf("删除元素后的平衡二叉树的中序遍历结果为:");
inorderTraversalAVL(BT);
printf("\n");
//顺序表
SeqList list;
list.length = 0;
file= fopen("L.txt", "r");
if (file == NULL) {
printf("无法打开文件\n");
return 0;
}
while (fscanf(file, "%d", &num) != EOF) {
BSTNode* newNode = createNode(num);
insertSeqList(&list, newNode);
}
fclose(file);
BSTNode*T2=NULL;
T2 = buildBSTFromSeqList(&list);
printf("该二叉树的中序遍历结果为:");
inorderTraversal(T2);
printf("\n");
average_Search_Lenth = averageSearchLenth(T2, 1);
printf("该二叉树的平均查找长度为:%f", average_Search_Lenth);
printf("\n");
printf("输入要删除的元素:");
scanf("%d", &x);
T2 = deleteNode(T2, x);
printf("删除元素后的二叉排序树的中序遍历结果为:");
inorderTraversal(T2);
printf("\n");
return 0;
}
  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

西唯兵欧泡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值