二叉搜索树是这样来的
节点是这样删的
//BST.h
#ifndef _BST_H_
#define _BST_H_
/*
*在二叉排序树中,当根的左右子树存在时,其左子树上所有节点的值均小于根节点的值,右子树上所有节点的值均大于根节点的值
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
typedef int Elemenet;
typedef struct _BST_Node
{
Elemenet data;
struct _BST_Node *LChild;
struct _BST_Node *RChild;
}BST_Node;
typedef BST_Node *BST;
//初始化搜索树
void InitBST(BST *bst);
//插入
bool InsertBST(BST *bst, Elemenet v);
//最小节点值
Elemenet MinBST(const BST *bst);
//最大节点值
Elemenet MaxBST(const BST *bst);
//中序遍历(值由小到大)
void TraversalBST(const BST *bst);
//查找
BST_Node *SearchBST(const BST *bst, Elemenet key);
//删除
bool DeleteBST(BST *bst, Elemenet key);
//摧毁
void DestroyBST(BST *bst);
#endif //_BST_H_
//BST.c
#include "BST.h"
void InitBST(BST *bst)
{
*bst = NULL;
}
//多个if( x ) return; return;的效率和if( x ){} else if( x )...else是一样的,判断次数一致,汇编代码也一样,貌似此处用后者逻辑更清楚些???
bool InsertBST(BST *bst, Elemenet v)
{
if( NULL == *bst )
{
*bst = (BST_Node *)malloc(sizeof(BST_Node));
if( NULL == *bst )
return false;
(*bst)->data = v;
(*bst)->LChild = NULL;
(*bst)->RChild = NULL;
return true;
}
else if( v < (*bst)->data )
return InsertBST(&(*bst)->LChild, v);
else if( v > (*bst)->data )
return InsertBST(&(*bst)->RChild, v);
else
return false; //此种情况下,二叉搜索树中某个节点的值与待插值相等,为保证二叉树节点值的唯一性返回false
}
//如果左子树存在,那么最小节点应该在左子树上
Elemenet MinBST(const BST *bst)
{
BST_Node *p = *bst;
while (NULL != p->LChild)
p = p->LChild;
return p->data;
}
//如果右子树存在,最大节点应该在右子树上
Elemenet MaxBST(const BST *bst)
{
BST_Node *p = *bst;
while (NULL != p->RChild)
p = p->RChild;
return p->data;
}
//中序遍历(值由小到大)
void TraversalBST(const BST *bst)
{
if( NULL == *bst )
return ;
TraversalBST(&(*bst)->LChild);
printf("%d ", (*bst)->data);
TraversalBST(&(*bst)->RChild);
}
BST_Node *SearchBST(const BST *bst, Elemenet key)
{
if( NULL == *bst )
return NULL;
if( key < (*bst)->data )
return SearchBST(&(*bst)->LChild, key);
if( key > (*bst)->data )
return SearchBST(&(*bst)->RChild, key);
return *bst;
}
//多个if( x ) return; return;的效率和if( x ){} else if( x )...else是一样的,判断次数一致,汇编代码也一样
bool DeleteBST(BST *bst, Elemenet key)
{
if( NULL == *bst )
return false;
if( key < (*bst)->data )
return DeleteBST(&(*bst)->LChild, key);
if( key > (*bst)->data )
return DeleteBST(&(*bst)->RChild, key);
//下面为找到目标删除节点的情况
BST_Node *p = NULL;
//目标删除节点的左右子树都存在(如节点59、32、68),可用左子树中的最大者或右子树中最小者的值替换目标删除节点,接着转化为删除左子树中的最大者或右子树中最小者
if( NULL != (*bst)->LChild && NULL != (*bst)->RChild )
{
p = (*bst)->RChild;
while (NULL != p->LChild) //寻找右子树中最小者
p = p->LChild;
(*bst)->data = p->data; //替换待目标删除节点
return DeleteBST(&(*bst)->RChild, key); //转化为删除右子树中最小者
}
else //目标删除节点最多只有一个子树(如2、52、60、69以及全部叶子节点)
{
p = *bst;
if( NULL == (*bst)->LChild ) //左子树为空(包含左子树为空,右子树不为空与左右子树均为空的情况)
{
*bst = (*bst)->RChild; //使指向目标删除节点的指针指向其可能存在的子树或空
}
else //左子树不为空,右子树为空
{
*bst = (*bst)->LChild; //指向存在的右子树
}
free(p);
return true;
}
}
void DestroyBST(BST *bst)
{
if( NULL == *bst )
return;
DestroyBST(&(*bst)->LChild);
DestroyBST(&(*bst)->RChild);
free(*bst);
*bst = NULL;
}
//main.c
#include <stdio.h>
#include "BST.h"
#include <stdbool.h>
int main(int argc, char *argv[])
{
BST bst;
int array[10] = {59, 32, 68, 52, 60, 2, 69, 258, 17, 47};
int i = 0;
bool ret = true;
InitBST(&bst);
for(i = 0; i < 10 && ret; i++)
{
ret = InsertBST(&bst, array[i]);
}
printf("最小值为%d\n", MinBST(&bst));
printf("最大值为%d\n", MaxBST(&bst));
printf("遍历\n");
TraversalBST(&bst);
printf("\n");
BST_Node *p = SearchBST(&bst, 258);
if( NULL != p )
printf("查找的节点的值为%d\n", p->data);
else
printf("查找的节点不存在\n");
printf("删除59\n");
DeleteBST(&bst, 59);
printf("遍历\n");
TraversalBST(&bst);
printf("\n删除69\n");
DeleteBST(&bst, 69);
printf("遍历\n");
TraversalBST(&bst);
DestroyBST(&bst);
return 0;
}