首页 > 其他分享 >C语言基础(二十六)

C语言基础(二十六)

时间:2024-08-30 20:23:09浏览次数:6  
标签:二十六 right TreeNode int 基础 value C语言 root 节点

二叉树节点通常包含三个部分:存储数据的部分、指向左子节点的指针、以及指向右子节点的指针。

测试代码:

#include "date.h" 
#include <stdio.h>  
#include <stdlib.h>  
#include <time.h> 
// 定义二叉树节点的结构,包括节点的值、指向左子节点的指针和指向右子节点的指针。
typedef struct TreeNode {  
    int value;  
    struct TreeNode *left;  
    struct TreeNode *right;  
} TreeNode;  
// 创建一个新的树节点,并分配内存。如果内存分配失败,则打印错误信息并退出程序。 
TreeNode* createNode(int value) {  
    TreeNode* newNode = (TreeNode*)malloc(sizeof(TreeNode));  
    if (newNode == NULL) {  
        printf("Memory allocation failed\n");  
        exit(1);  
    }  
    newNode->value = value;  
    newNode->left = NULL;  
    newNode->right = NULL;  
    return newNode;  
}  
  
// 递归调用:将新值插入到二叉搜索树中的适当位置。
// 如果根节点为空,则新节点成为根节点;
// 如果新值小于根节点的值,则递归地在左子树中插入;
// 如果新值大于或等于根节点的值,则递归地在右子树中插入。
// 插入规则由程序员决定。、 
void insertNode(TreeNode** root, int value) {  
    if (*root == NULL) {  
        *root = createNode(value);  
    } else if (value < (*root)->value) {  
        insertNode(&((*root)->left), value);  
    } else {  
        insertNode(&((*root)->right), value);  
    }  
}  
// 递归调用:打印二叉树的内容,同时根据节点的层级打印相应数量的空格,可视化树的形状。  
void printTree(TreeNode* root, int level) {  
    if (root == NULL) return;  
  
    // 打印空格以显示树的层级  
    for (int i = 0; i < level; i++) {  
        printf("   ");  
    }  
    printf("%d\n", root->value);  
  
    // 递归打印左子树和右子树,层级+1  
    printTree(root->left, level + 1);  
    printTree(root->right, level + 1);  
}  
  
int generateRandomNumber(int min, int max) {   
    return min + rand() % (max - min + 1);  
} 
 
void freeTree(TreeNode* root) {  
    if (root != NULL) {  
        // 递归调用释放左子树  
        freeTree(root->left);  
        // 递归调用释放右子树  
        freeTree(root->right);  
        // 释放当前节点  
        free(root);  
    }  
}  
int main() {  

    int times = getTime();
    // 创建一个空的二叉搜索树,并随机插入一系列值。 
    TreeNode* root = NULL; // 初始化为空树  
    srand(time(NULL)); // 设置随机数生成的种子  
    // 插入随机生成的节点  
    for (int i = 0; i < 8; i++) {  
        int randomValue = generateRandomNumber(1, 100); // 生成1到100之间的随机数  
        insertNode(&root, randomValue);  
        printf("Inserted: %d\n", randomValue);  
    }  
  
    // 打印二叉树  
    printTree(root, 0);  
    // 动态释放内存   
    freeTree(root); 
    
    return 0;  
}

运行结果如下:

 

..........................................................................................................................................................

AVL树是一种自平衡的二叉搜索树,其中每个节点的两个子树的高度最大差别为1,其平衡因子(左子树高度减右子树高度)的绝对值不超过1。在AVL树中进行插入或删除节点后,会破坏树的平衡。为了恢复平衡,需要执行一种或多种旋转操作(单旋转或双旋转)。

测试代码:

#include "date.h"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// AVL树 
// 定义结构体 
typedef struct TreeNode {
    int value;
    struct TreeNode *left;
    struct TreeNode *right;
} TreeNode;
// 定义函数createNode,创建新节点并返回指向该节点的指针。
// 如果内存分配失败,则打印错误信息并退出程序。 
TreeNode* createNode(int value) {
    TreeNode* newNode = (TreeNode*)malloc(sizeof(TreeNode));
    if (newNode == NULL) {
        printf("Memory allocation failed:\n");
        exit(1);
    }
    newNode->value = value;
    newNode->left = NULL;
    newNode->right = NULL;
    return newNode;
}
// 定义函数rotateRight,用于向右旋转二叉树节点。
// 将当前节点的左孩子作为新的根节点,调整左右孩子的指向。 
void rotateRight(TreeNode** root) {
    TreeNode* newRoot = (*root)->left;
    (*root)->left = newRoot->right;
    newRoot->right = *root;
    *root = newRoot;
}
// 定义函数rotateLeft,用于向左旋转二叉树节点。
// 将当前节点的右孩子作为新的根节点,调整左右孩子的指向。 
void rotateLeft(TreeNode** root) {
    TreeNode* newRoot = (*root)->right;
    (*root)->right = newRoot->left;
    newRoot->left = *root;
    *root = newRoot;
}
// 定义函数getHeight,用于计算树的高度。
// 递归调用比较左右子树的高度并返回较大值加1: 
int getHeight(TreeNode* root) {  
    if (root == NULL) return 0;  
    return 1 + (getHeight(root->left) > getHeight(root->right) ? getHeight(root->left) : getHeight(root->right));  
} 
// 定义函数rebalance,用于平衡二叉树。
// 通过比较左右子树的高度差来判断是否需要旋转,然后执行相应的旋转操作。 
void rebalance(TreeNode** root) {
    if (*root == NULL) {
        return;
    }
    int leftHeight = getHeight((*root)->left);
    int rightHeight = getHeight((*root)->right);

    if (leftHeight - rightHeight > 1) {
        if (getHeight((*root)->left->left) < getHeight((*root)->left->right)) {
            rotateLeft(&((*root)->left));
        }
        rotateRight(root);
    } else if (rightHeight - leftHeight > 1) {
        if (getHeight((*root)->right->right) < getHeight((*root)->right->left)) {
            rotateRight(&((*root)->right));
        }
        rotateLeft(root);
    }
}
// 定义函数insertNode,用于向树中插入新节点。
// 根据值的大小递归调用,在左右子树中插入节点,并在插入后执行平衡操作。 
void insertNode(TreeNode** root, int value) {
    if (*root == NULL) {
        *root = createNode(value);
    } else if (value < (*root)->value) {
        insertNode(&((*root)->left), value);
    } else {
        insertNode(&((*root)->right), value);
    }
    rebalance(root);
}
// 定义函数printTree,用于按层次打印树。
// 递归调用打印节点值,并通过增加缩进表示树的层次结构。 
void printTree(TreeNode* root, int level) {
    if (root == NULL) return;

    for (int i = 0; i < level; i++) {
        printf("   ");
    }
    printf("%d\n", root->value);

    printTree(root->left, level + 1);
    printTree(root->right, level + 1);
}
// 定义函数generateRandomNumber,用于生成介于[min, max]范围内的随机数。 
int generateRandomNumber(int min, int max) { 
    return min + rand() % (max - min + 1);
}
// 定义函数freeTree,用于释放树的内存。
// 递归调用释放左右子树的内存,并释放根节点的内存。 
void freeTree(TreeNode* root) {
    if (root != NULL) {
        freeTree(root->left);
        freeTree(root->right);
        free(root);
    }
}
// 初始化根节点为NULL,然后随机数生成15个介于1和100之间的值,并插入到树中。
// 插入后打印树结构,并最后释放树的内存。 
int main() {
    int times = getTime();

    TreeNode* root = NULL;
    srand(time(NULL));

    for (int i = 0; i < 15; i++) {
        int randomValue = generateRandomNumber(1, 100);
        insertNode(&root, randomValue);
        printf("Inserted: %d\n", randomValue);
    }
    printTree(root, 0);
    freeTree(root);
   }

运行结果如下:

 

标签:二十六,right,TreeNode,int,基础,value,C语言,root,节点
From: https://blog.csdn.net/wehpd/article/details/141726294

相关文章

  • C语言基础(二十七)
    1、位字段(Bit-fields)也是一种数据结构,允许在结构体(struct)或联合体(union)中定义其成员占用特定的位数。对于需要精确控制内存布局或处理硬件寄存器映射等场景非常有用。位字段使得开发者能够定义小于一个字节的变量,从而更有效地利用内存空间。位字段的声明方式是在结构体或联合体......
  • 11.2 C语言文件的读写操作
    11.2C语言文件的读写操作11.2文件的读写操作11.2文件的读写操作文件的读写是文件处理中的核心操作,C语言提供了多种函数来实现从文件读取数据和向文件写入数据。文件的写操作写字符:fputc(c,fp);//将字符c写入文件写字符串:fputs(str,fp);//将字符......
  • js基础学习
    1.js是动态语言,变量类型是可变的。varx=10;varx='pink';2.八进制(0开头)、十六进制(0x开头)3.字符串多个嵌套时,外双内单/外单内双。模版字符串:为了简化字符串拼接。`我今年${age}了`转义字符:4.typeof变量 可以检测类型---控制台颜色也可以检测类型5.转成字符串......
  • 【C语言】内存函数
    文章目录前言一、memcpy的使用和模拟实现1.memcpy的使用2.模拟实现memcpy函数二、memmove的使用和模拟实现1.memmove的使用2.模拟实现memmove函数三、memset函数的使用四、memcmp函数的使用前言`内存函数的头文件都是<string.h>介绍了memcpy、memmove、memset......
  • C语言深度复习【数组和指针】
    目录一.数组和指针1.1数组指针1.2指针数组1.3函数指针1.4const和指针1.5sizeof和指针和数组1.6strlen和字符数组一.数组和指针1.1数组指针一个数组指针实际上是指指向数组的指针。当你有一个数组类型作为函数参数时,它在函数内部被当作一个指针来处理。例......
  • 信息安全数学基础(3)整数的表示
    前言    在信息安全数学基础中,整数的表示是一个核心且基础的概念。整数的表示不仅涉及到其数值的存储方式,还关系到整数在计算机中的运算和处理。以下是对整数表示的详细阐述:一、整数的定义与分类    整数包括正整数、零和负整数,通常表示为…,-3,-2,-1,0,......
  • 什么是激活函数?零基础扫盲~
    我刚开始学习深度学习的时候,看到了这么一段话:作者把非线性激活函数(ReLU)用在了模型里,发现训练速度显著提高,原因在于传统用的是饱和非线性激活函数,例如tanh,训练时如果进入到饱和区域,那么会因为梯度变化过小而难以训练;而ReLU是一种非饱和非线性激活函数,接受阈是0~∞∞,不存在tan......
  • Linux操作文件和文件夹的常用基础命令
    文件和文件夹的查看ls:列出当前目录中的文件和文件夹。ls-l:以长格式列出文件信息,包括权限、所有者、大小、修改时间等。ls-a:显示隐藏文件(以.开头的文件)。ls-h:以人类可读的格式显示文件大小。文件和文件夹的创建touchfilename:创建一个新的空文件。mkdirdirname:......
  • VS Code 代码片段指南: 从基础到高级技巧
    前言“系列首发于公众号『非同质前端札记』,若不想错过更多精彩内容,请“星标”一下,敬请关注公众号最新消息。今天咱们来聊聊VSCode里的自定义代码片段。这玩意儿简直是提升编码效率的神器,用好了能让你敲代码更方便!不管你是刚入行的菜鸟还是身经百战的老兵,这篇攻略都......
  • VS Code 代码片段指南: 从基础到高级技巧
    前言“系列首发于公众号『非同质前端札记』,若不想错过更多精彩内容,请“星标”一下,敬请关注公众号最新消息。今天咱们来聊聊VSCode里的自定义代码片段。这玩意儿简直是提升编码效率的神器,用好了能让你敲代码更方便!不管你是刚入行的菜鸟还是身经百战的老兵,这篇攻略都......