当前位置: 首页 > news >正文

BST平衡二叉树相关

对于一些结构的先行说明

才发现vscode选中变量名按下F2可以替换所有原来有误变量,方便)

#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>typedef struct BSTNode
{int data;struct BSTNode* left,*right;
}BSTNode;//这个队列结点的话,我们就存指向树节点的指针
//所以其实我们会发现,如果用typedef事先对data的元素类型定义为任意,其实也就跟c++,java里的泛型差不多了
typedef struct Node   
{BSTNode* data;struct Node* next;
}Node;typedef struct Queue
{Node* front;Node* rear;
}Queue;

此处是一些basic

BSTNode* createNode(int data)
{BSTNode* newNode=(BSTNode*)malloc(sizeof(BSTNode));newNode->data=data;newNode->left=NULL;newNode->right=NULL;return newNode;
}//这里用二重指针是因为,如果只使用单指针root的话,只是局部变量,若如此返回值应该是Node*
void insertNode(BSTNode** root,int data)
{if(*root==NULL) *root=createNode(data);else if(data<= (*root)->data) insertNode(&((*root)->left),data);else insertNode(&((*root)->right),data);
}bool search(BSTNode* root,int data)
{if(root==NULL) return false;else if(data<=root->data) return search(root->left,data);else return search(root->right,data);
}//BST就是平衡二叉树,左子树最大值一定不大于根节点,右子树最小值一定不小于根节点
//显然一直往左下方走就能找到最小的
//这里为什么用单指针,那当然是因为我们又不需要改变原有的树,所以当成局部变量就好了
BSTNode* findMin(BSTNode* root)
{if(root == NULL) return root;while(root->left!=NULL){root=root->left;}return root;
}BSTNode* findTarget(BSTNode* root,int data)
{if(root==NULL) return root;if(root->data==data) return root;else if(root->data >data) return findTarget(root->left,data);else return findTarget(root->right,data);
}int findHeight(BSTNode* root)
{if(root==NULL) return -1;    //这里是-1是把深度按照边数来定义,抵消最后的+1,按照结点数的话也可以是0return max(findHeight(root->left),findHeight(root->right))+1;   //显然,+1是因为要加上连接左右子树的那条边
}

需要烧烤画图的部分

void initQueue(Queue* q)
{q->front=q->rear=(Queue*)malloc(sizeof(Queue)); //嗯 这里已经隐含了初始队列空两指针指向一个地址了if(!q->front) exit(1);q->front->next=NULL;    //这里设置一个带头结点的链表,用于后面判断队列空
}//画图会非常好理解
void pushQueue(Queue* q,BSTNode* data)
{Node* newNode=(Node*)malloc(sizeof(Node));if(!newNode) exit(1);newNode->data=data;newNode->next=NULL;q->rear->next=newNode;  //让新结点和原链表接起来q->rear=newNode;    //移动尾指针
}BSTNode* getFront(Queue q)
{return q.front->next->data;
}void popQueue(Queue* q)
{if(q->front==q->rear) exit(1);Node* current=q->front->next;q->front->next=current->next;if(q->rear==current) q->rear=q->front;free(current);
}bool emptyQueue(Queue q)
{if(q.front==q.rear) return true;else return false;
}void leverOrder(BSTNode* root)
{if(root==NULL) return;Queue q;initQueue(&q);pushQueue(&q,root);while(!emptyQueue){BSTNode* current=getFront(q);printf("%d ",current->data);if(current->left!=NULL) pushQueue(&q,current->left);if(current->right!=NULL) pushQueue(&q,current->right);popQueue(&q);}
}//判断一棵树是不是BST,就是看符不符合定义,左子树严格小于根,右子树严格大于根
//所以其实应该对一些重复数据做额外处理的
//这里的话,其实就是靠定义来缩小向下每个结点的定义域,来减小成本
bool isBST(BSTNode* root,int minValue,int maxValue)   //这里一般就用无穷小和无穷大
{    if(root==NULL) return true;if(root->data <minValue&& root->data> maxValue&&isBST(root->left,root->data,maxValue)&&isBST(root->right,minValue,root->data))   //左子最大与右子最小return true;else return false;
}void deleteBST(BSTNode** root,int data)
{if(*root==NULL) return;else if(data< (*root)->data) deleteBST(&((*root)->left),data);else if(data> (*root)->data) deleteBST(&((*root)->right),data);//这里往上是还没有找到目标时的递归else{if((*root)->left==NULL&&(*root)->right) //叶子结点直接删就好了{free(*root);root=NULL;  //别忘了把指针的指针置空return;}else if((*root)->left!=NULL)   //只有一个孩子的享受全部家产{BSTNode* temp=*root;*root=(*root)->right;free(temp);}else if((*root)->right!=NULL){BSTNode* temp=*root;*root=(*root)->left;free(temp);}else    //有两个孩子的话,在一群高手中找个相对菜的把左子树的top1碾压一下{BSTNode* temp=findMin((*root)->right);(*root)->data=temp->data;deleteBST(&((*root)->right),temp->data);}}
}//在不改变树结点的结构的时候,按需找到想要的结点的后继
//这里和线索化的区别是,都有后继,同理其实也能找到前驱
BSTNode* getSuccessor(BSTNode* root,int data)
{BSTNode* current=findTarget(root,data);if(current==NULL) return NULL;//这里我们要看当前结点有没有右子//如果有右子的话,在右子中找最左下的,那个就是要的后继if(current->right != NULL) return findMin(root->right);//那如果没有右子的话,祖先结点和后继结点就要更新了else{BSTNode* successor=NULL;BSTNode* ancestor=root;while (ancestor!=current)   //如果祖先结点还没到达当前结点{//向下的时候,我们要分成向左走和向右走讨论//因为如果向左走,说明当前结点是第一次访问,反之则是第二次(中序 左根右)//画图容易知道,对于没有右子的,后继应该是上一个只访问过一次的祖先结点if(current->data <ancestor->data){successor =ancestor;ancestor =ancestor->left;}else ancestor=ancestor->right;}return successor;}
}

http://www.dtcms.com/a/573692.html

相关文章:

  • Spring Boot3零基础教程,事态感知API doOnXXX,笔记111
  • 个人性质网站唐尧文化 网站建设工作总结
  • JDBC - 数据库连接池
  • R 包中的生命周期触发函数全解析
  • 华为WATCH D2 WATCH GT6:秋季来临,尊爱老人的智能守护
  • LangChain RAG 完整流程实战解析
  • 镇江建设质量监督站网站移动app网站模板
  • 【论文精读】SV3D:基于视频扩散模型的单图多视角合成与3D生成
  • 视频融合平台EasyCVR级联失败问题排查:请求上级播放后,视频为何无法打开?
  • 哪个网站能下载gif品牌红酒的网站建设
  • 登录失败次数限制
  • wordpress文章图片目录网站改版的seo注意事项
  • 【git】git clone含有lfs大文件时卡在resolving deltas(100%)的解决方案
  • 外贸和网站制作个人网站有什么内容
  • 开发一个完整的Electron应用程序
  • 从测试小白到高手:JUnit 5 核心注解 @BeforeEach 与 @AfterEach 的实战指南
  • App 怎么上架 iOS?从准备资料到开心上架(Appuploader)免 Mac 上传的完整实战流程指南
  • 智能安全管理 基于视觉分析的玩手机检测系统 手机行为AI模型训练 边缘计算手机行为监测设备
  • 做网站的必备软件php安防企业网站源码
  • 旅游自媒体网站怎么做c2c网站建设系统
  • Apache HTTP Server 2.4.65 详细安装教程(基于 CentOS 7)
  • 建行个人网站河池网站建设
  • 河北网站备案多久关于网站建设的请示范文
  • 坑#Spring#NullPointerException
  • 做视频网站用什么格式教育+wordpress模板下载
  • 排序算法
  • 网站排名推广安卓下载软件
  • Nginx 安全网关
  • 手机网站 像素旅游网站建设方案之目标
  • 2025年具身智能安全前沿:守护机器人时代的防失控策略