二叉排序树的删除
(一)、二叉排序树定义:详见《数据结构》(C语言版)严蔚敏,吴伟民 P.227 (9.2.1)
(二)、二叉排序树删除指定的target节点
- a.若target为叶子节点,则直接删除target即可;
- b.若target只有左子树(或者右子树),则将target的父节点和左子树(或者右子树)拼接,同时删除target即可;
- c.若target同时拥有左子树和右子树,则将target的值和target的右子树中序遍历的第一个节点InorderFirstNodeOfTargetRight(即其右子树中的最小值)的值交换后,删除InorderFirstNodeOfTargetRight即可。
- d(与c等价)若target同时拥有左子树和右子树,则将target的值和target的左子树中序遍历的最后一个节点InorderLastNodeOfTargetLeft(即其左边子树中的最大值)的值交换后,删除InorderLastNodeOfTargetLeft即可。
(三)、二叉排序树以(二)a,b,c,为准则进行二叉排序树指定节点的删除示例代码如下:
#include <stdio.h>
#include <stdlib.h>
#define DATATYPE int
#define STATUS int
#define FALSE 0
#define TRUE 1
/**
* 二叉排序树结构体定义
*/
typedef struct BSTNode{
DATATYPE data;
struct BSTNode * lchild;
struct BSTNode * rchild;
}BSTNode, *BSTree;
/**
* 申请新的树节点内存空间
* @return BSTree
*/
BSTree NewBSTNode(){
BSTree node= (BSTree)malloc(sizeof(BSTNode));
if (node == NULL){
printf("OOM\n");
exit(1);
}
return node;
}
/**
* 将data数据渲染到新增节点,并且初始化新节点数据
* @param data
* @return
*/
BSTree GetAloneNode(DATATYPE data){
BSTree newnode = NewBSTNode();
newnode->lchild=NULL;
newnode->rchild=NULL;
newnode->data=data;
return newnode;
}
/**
* 二叉排序树的插入
* @param bstroot
* @param data
* @return
*/
BSTree InsertData(BSTree bstroot, DATATYPE data){
BSTree newnode = GetAloneNode(data);
if (bstroot==NULL){
bstroot=newnode;
} else if (data < bstroot->data){
bstroot->lchild = InsertData(bstroot->lchild,data);
}else if(data > bstroot->data){
bstroot->rchild = InsertData(bstroot->rchild,data);
}
return bstroot;
}
/**
* 递归查找
* @return
*/
BSTree Search1(BSTree bstroot, DATATYPE data){
if (bstroot==NULL){
return NULL;
}else if(data == bstroot->data){
return bstroot;
}else if(data < bstroot->data){
return Search1(bstroot->lchild,data);
}else if(data > bstroot ->data){
return Search1(bstroot->rchild,data);
}else{
return NULL;
}
}
/**
* 非递归查找
*/
BSTree Search2(BSTree bstroot, DATATYPE data){
BSTree tmp = bstroot;
while (tmp){
if (tmp->data == data){
return tmp;
}else if(tmp->data < data){
tmp = tmp->rchild;
}else if(tmp->data > data){
tmp = tmp->lchild;
}
}
return NULL;
}
/**
*二叉排序树的前序遍历
*/
void Preorder(BSTree bsTree)
{
if(bsTree == NULL)
return;
else
{
printf("%d ",bsTree->data);
Preorder(bsTree->lchild);
Preorder(bsTree->rchild);
}
}
/**
* 删除指定节点
*/
void DeleteNodeByData(BSTree bsTree, DATATYPE data){
BSTree targetNode = Search2(bsTree,data);
if (targetNode != NULL){
BSTree q,s;
if (targetNode->rchild == NULL){
q = targetNode;
targetNode = targetNode->lchild;
free(q);
}else if(targetNode->lchild == NULL){
q = targetNode;
targetNode = targetNode->rchild;
free(q);
}else{//左右子树均不为空,
// 将其右子树中序遍历的第一个子女交换并且删除此子女
// 或者将其左子树中序遍历的最后一个子女交换,并且删此子女
q = targetNode;
s = targetNode->rchild;
//找到右子树中序遍历的第一个子女s,q为s的父节点
while (s->lchild){
q = s;
s = s->lchild;
}
targetNode ->data = s->data;//交换数据
if (q != targetNode){
q->lchild = s->rchild;
}else{
q->rchild = s->rchild;
}
free(s);
}
}
}
int main() {
DATATYPE a[10] ={17,7,21,4,11,18,25,3,6,19};
BSTree bsTree = NULL;
for (int i = 0; i < 10; ++i) {
bsTree = InsertData(bsTree,a[i]);
}
Preorder(bsTree);
printf("\n");
DeleteNodeByData(bsTree,17);
Preorder(bsTree);
return 0;
}
(四)、欢迎讨论交流优化。