本次的搜索二叉树基本操作包括搜索二叉树的初始化、搜索二叉树的插入(递归实现)、搜索二叉树的查找(递归实现)、搜索二叉树的结点删除(非递归实现)
1. 搜索二叉树的结构
typedef struct SearchTreeNode { SearchTreeType key; // 关键码 struct SearchTreeNode* lchild; struct SearchTreeNode* rchild; } SearchTreeNode;
2.搜索二叉树的初始化
搜索二叉树的初始化应该判断是否为空树,如果为空树直接返回,否则将根节点直接赋值为空,以达到初始化的目的。
//搜索二叉树的初始化 void SearchTreeInit(SearchTreeNode** root){ //判断是否为非法输入 if(root == NULL){ //非法输入 return; } //判断是否为空树 if(*root == NULL){ //空树 return; } *root = NULL; }
3.搜索二叉树的查找(递归实现)
a.判断搜索二叉树是否为空,为空直接返回
b.不为空,将查询值与根节点的关键字进行比较,等于直接返回根节点;小于,在根结点的左子树中继续查询;大于,在根节点的右子树中查找,进入递归。找到返回结点,找不到返回NULL。
//搜索二叉树的查找(递归实现) SearchTreeNode* SearchTreeFind(SearchTreeNode* root,SearchTreeType to_find){ //判断是否为空树 if(root == NULL){ //空树 return NULL; }else{() //非空 if(to_find > root->key){ SearchTreeFind(root->rchild,to_find); }else if(to_find < root->key){ SearchTreeFind(root->lchild,to_find); }else{ //找到了 return root; } } }
4. 搜索二叉树的结点删除(非递归实现)
a. 进行删除是应该保持删除结点的父结点
b. 对删除结点进行查找,找不到,则直接返回
c. 找到,则对其进行判断(此处的判断包含俩个方面:一:判断父结点是否为NULL,为NULL时,只对只有左孩子、只有右孩子、既没有左孩子,又没有右孩子的这三种情况有影响,需要改变根节点的指向;二:对子节点进行判断,分四种情况,只有左孩子、只有右孩子、既有左孩子,又有右孩子、既没有左孩子,又没有右孩子)。
//搜索二叉树的删除(非递归实现) void SearchTreeRemove(SearchTreeNode** root, SearchTreeType key){ if(root == NULL){ //非法输入 return; } if(*root == NULL){ //空树 return; } //查找 SearchTreeNode* parent = NULL; SearchTreeNode* cur = (*root); while(cur != NULL){ if(cur->key == key){ //要删除值等于根结点的关键字,判断根结点的孩子情况 if(cur->lchild!= NULL&& cur->rchild ==NULL){ //1.只有左子树 if(cur == (*root)){ (*root)= cur->lchild; free(cur); return; }else{ if(parent->rchild == cur){ parent->rchild =cur->lchild; free(cur); return; }else{ parent->lchild = cur->lchild; free(cur); return; } } // }else if(cur->lchild == NULL&&cur->rchild !=NULL) { //2.只有右子树 if(cur == (*root)){ (*root)= cur->lchild; free(cur); return; }else{ if(parent->rchild == cur){ parent->rchild =cur->rchild; free(cur); return; }else{ parent->lchild = cur->rchild; free(cur); return; } } }else if(cur->lchild != NULL&&cur->rchild != NULL){ //3.既有左子树、又有右子树 //这里右俩中方法:一、用该结点的右子树的最左下结点的值来替换该结点的值,最左下结点无左孩子,同2; // 二、用该结点的左子树的最右下结点的值来替换该结点的值,最右下结点无右孩子,同1. parent = cur; SearchTreeNode* min = cur->rchild; while(min->lchild != NULL){ parent = min; min = min->lchild; } cur->key = min->key; if(parent->rchild == min){ parent->rchild =min->rchild; free(min); return; }else{ parent->lchild = min->rchild; free(min); return; } }else{ //4.即没有左子树、又没有右子树 if(cur == (*root)){ (*root)= cur->lchild; free(cur); return; }else{ if(parent->rchild == cur){ parent->rchild =NULL; free(cur); return; }else{ parent->lchild = NULL; free(cur); return; } } } }else if(cur->key <key){ //要删除值大于根结点的关键字,在根结点的右子树中查找 parent = cur; cur = cur->rchild; }else{ //要删除值小于根结点的关键字,在根结点的左子树中查找 parent = cur; cur = cur->lchild; } } return; }
5.搜索二叉树的插入(递归实现)
插入相对而言还是较为简单的,简单的来说就是将插入值与结点的关键字进行比较,相等直接返回(此处规定不允许含有相同项),小于结点的关键字,则在结点的左子树中查找;大于结点的关键字,则在结点的关键字,则在结点的右子树中进行查找,直到遇到空结点,则将该结点置于空结点的位置,over。
//搜索二叉树的插入(递归实现) void SearchTreeInsert(SearchTreeNode** root, SearchTreeType key){ //判断是否为非法输入 if(root == NULL){ return; } //判断是否为空树 if(*root == NULL){ //空树 SearchTreeNode* ret = CreateSearchTreeNode(key); *root = ret; }else{ //非空 if(key < (*root)->key){ SearchTreeInsert(&(*root)->lchild,key); }else if(key > (*root)->key){ SearchTreeInsert(&(*root)->rchild,key); }else{ //规定搜索二叉树中无相同项,,出现相同情况,,直接返回 return; } } }