可以直接通过代码和代码注释的结合来学习并理解数据结构--队列的基本逻辑,比单纯的看文字理解代码更有乐趣,不过笔者建议在看代码之前可以先去本链接下的视频学习下数据结构---队列会事半功倍哦~
注:本视频来源于B站大佬:@动画讲编程的视频
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
/*********************************二叉搜索树************************************************/
//定义二叉搜索树节点结构体
typedef struct TreeNode
{
int node_val; //每个树节点上的值
TreeNode* left_node; //指向树左侧的节点地址的指针
TreeNode* right_node; //指向树右侧的节点地址的指针
}TreeNode_t;
//创建一个新节点
TreeNode_t* Creat_Node(int val)
{
TreeNode_t* node = (TreeNode_t*)malloc(sizeof(TreeNode_t));
node->node_val = val;
node->left_node = NULL; //因为二叉树的性质,刚创建的节点是属于"树梢"
node->right_node = NULL; //所以其左右指针不应该指向其他地方,那么置为NULL
return node;
}
//插入节点到二叉树中
TreeNode_t* Insert_Node(TreeNode_t* root, int val)
{
TreeNode_t* node = NULL;
if (root == NULL) //二叉树如果不存在
{
node=Creat_Node(val); //创建一个父节点(树根)
return node;
}
if (val < root->node_val) //如果插入的值小于父节点
{//那就让要想插入的节点的以目前的父节点的左指针域所指向的地址
root->left_node= Insert_Node(root->left_node,val);//为这个节点的位置插入,那此时又加入了插入函数以此来形成递归调用
}//直到让要插入的节点刚好找到一个父节点的指针域指向为NULL的节点,让这个父节点的指针指向该节点即可成功插入
else if (val > root->node_val)//插入右边与插入左边同理
{
root->right_node = Insert_Node(root->right_node, val);
}
else if (val == root->node_val)//如果要插入的值正好等于树中的某个值,那就说明插入的值不符合二叉树的数据结构,那就直接报错
{//并且不对该值做任何的处理而直接退出函数
printf("You insert's value equal to tree node value ,insert fail!!!\n");
}
return root;
}
//搜索在二叉树中的节点
TreeNode_t* Search_Node(TreeNode_t* root, int val)//与插入节点的方法类似
{
if (root == NULL || root->node_val == val)//当通过递归调用到节点的地址为NULL时,说明该二叉树没有这个值
{//或者说二叉树不存在
return root;//而当出现了要搜索的值正好等于树中的某个值的时候,就说明找到了要搜索的值,那就直接返回
}
if (val < root->node_val) //要搜索的值在当前节点左边
{
return Search_Node(root->left_node, val);
}
if (val > root->node_val) //要搜索的值在当前节点右边
{
return Search_Node(root->right_node, val);
}
}
//删除一个二叉树节点
TreeNode_t* Delete_Node(TreeNode_t* root,int val)
{
TreeNode_t* temp = NULL;
if (root == NULL) //树不存在
{
return root;//NULL
}
if (val < root->node_val) //要删除的节点在左子树
{
root->left_node = Delete_Node(root->left_node, val);
}
if (val > root->node_val) //要删除的节点在右子树
{
root->right_node = Delete_Node(root->right_node, val);
}
else if(val == root->node_val) //要删除的节点刚好被找到
{
if (root->left_node == NULL && root->right_node == NULL)//就只有一个节点或者在树的子叶节点处
{
free(root); //直接删除(释放内存空间)
return NULL; //该树就一个节点,所以删除后就应该返回NULL
}
else if (root->left_node != NULL && root->right_node == NULL)//该节点只有左子树
{
temp = root->left_node; //temp指向就会该节点的左子树
free(root);
return temp; //返回那个被删除后的节点遗留下的节点的地址,因为递归的调用,这个地址会被被删除的那个节点的父节点的指针所指向,于是这个temp就和整个树就连起来了!!!
}
else if (root->left_node == NULL && root->right_node != NULL)//该节点只有右子树
{
temp = root->right_node; //temp指向就会该节点的右子树
free(root); //返回那个被删除后的节点遗留下的节点的地址,因为递归的调用,这个地址会被被删除的那个节点的父节点的指针所指向,于是这个temp就和整个树就连起来了!!!
return temp;
}
/*这部分还需要多理解*/
else if (root->left_node != NULL && root->right_node != NULL)//该节点有既有左子树又有右子树
{
TreeNode_t* Minnode = root->right_node; //切换为右子树
while (Minnode->left_node != NULL) //找到右子树最小的节点
{
Minnode = Minnode->left_node; //这是因为二叉树的数据结构就是左子树永远要小于自己的父节点,而右子树永远要大于自己的父节点
} //所以这里一直让Minnode去指向该root的右子树的最左边的左子树
root->node_val = Minnode->node_val; //将找到的最小值赋给要想删除的节点
root->right_node = Delete_Node(root->right_node, Minnode->node_val);//通过递归来删除该树右子树的最小节点,因为该节点已经被用来代替了那个被删除的节点了
}
}
return root;
}
//遍历并打印二叉树中的各个节点的值
void Ergodic_Tree(TreeNode_t* root)
{
if (root != NULL)
{
printf("root value=%d\n", root->node_val);//打印节点的值
Ergodic_Tree(root->left_node); //递归打印左子树的值
Ergodic_Tree(root->right_node); //递归打印右子树的值
}
}
//示例
int main(void)
{
//创建一个"树根"
TreeNode_t* root=NULL;
//创建并插入二叉树节点
printf("Ceart and insert tree node:\n");
root = Insert_Node(root, 10);
root = Insert_Node(root, 20);
root = Insert_Node(root, 40);
root = Insert_Node(root, 30);
root = Insert_Node(root, 100);
root = Insert_Node(root, 30);
root = Insert_Node(root, 60);
//遍历二叉树
printf("Ergodic tree:\n");
Ergodic_Tree(root);
//删除一个节点
printf("Delect a tree node:\n");
root = Delete_Node(root,100);
//遍历二叉树
printf("Ergodic tree:\n");
Ergodic_Tree(root);
//搜索一个节点
printf("Search a tree node:\n");
root=Search_Node(root,60);
if (root != NULL)
{
printf("Search Success!!!,value=%d\n",root->node_val);//搜索到了
}
else
{
printf("Search Fail!!!,not exist value!!\n"); //没有搜索到
}
}