二叉搜索树,顾名思义,就是用来方便搜索的二叉树。
其定义有以下要点 :
一、由于是二叉树,采用链式结构。
二、二叉搜索树中存储的信息key不能重复。
三、二叉搜索树中的左子树全都比根结点小,右子树全都比根结点大。
有了上述定义,我们引入相关的操作,主要有插入,查找,删除。
#pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
typedef struct STreeNode{
int key;
struct STreeNode * pLeft;
struct STreeNode * pRight;
}STreeNode;
// key 不允许重复
// key 不允许更改
//结点左边的值都小于结点,结点右边的值都大于结点
// 是否找到 ,1 找到0 没找到
int Find(STreeNode *Node, int key)
{
while (Node!=NULL)
{
if (Node->key == key){
return 1;
}
if (key<Node->key ){
Node = Node->pLeft;
}
if (key>Node->key){
Node = Node->pRight;
}
}
return 0;
}
STreeNode * CreadTree(int key){
STreeNode *pNode = (STreeNode*)malloc(sizeof(STreeNode));
pNode->key = key;
pNode->pLeft = pNode->pRight = NULL;
return pNode;
}
//插入,成功返回1,失败返回0
int Insert(STreeNode ** pNode, int key)
{
STreeNode * Node = *pNode;
STreeNode *parent = NULL;
while (Node!=NULL)
{
if (Node->key == key){
return 0;
}
else if (key>Node->key)
{
parent = Node;
Node = Node->pRight;
}
else
{
parent = Node;
Node = Node->pLeft;
}
}
//遍历后的parent,若仍为空则是根结点,否则是最后一个叶子结点
//表示pNode是一颗空树,直接插到根结点处
if (parent == NULL){
*pNode = CreadTree(key);
return 1;
}
if (key < parent->key){
parent->pLeft = CreadTree(key);
}
if (key>parent->key)
{
parent->pRight = CreadTree(key);
}
return 0;
}
//递归查找,成功返回1,失败返回-1
int FindR(STreeNode *Node, int key)
{
if (Node->key==key)
{
return 1;
}
else if (key>Node->key)
{
return FindR(Node->pRight, key);
}
else
{
return FindR(Node->pLeft, key);
}
return 0;
}
//递归插入,成功返回1,失败返回-1
int InsertR(STreeNode *Node, int key)
{
if (Node->key==key){
return -1;
}
if (Node==NULL)
{
Node = CreadTree(key);
}
if (key<Node->key)
{
return InsertR(Node->pLeft, key);
}
else
{
return InsertR(Node->pRight, key);
}
}
//递归删除,成功返回1.失败返回-1
int RemoveR(STreeNode **pRoot, int key)
{
if (*pRoot == NULL){
return -1;
}
if (key>(*pRoot)->key)
{
return RemoveR(&(*pRoot)->pRight, key);
}
if (key<(*pRoot)->key)
{
return RemoveR(&(*pRoot)->pLeft, key);
}
//没找到,则pRoot会为空,返回-1,表示失败
//找到的话,就开始删除
if ((*pRoot)->pLeft==NULL)
{
*pRoot = (*pRoot)->pRight;
return 0;
}
if ((*pRoot)->pRight==NULL)
{
*pRoot = (*pRoot)->pLeft;
return 0;
}
// 左右孩子都不为空, 替换删除法, 找左子树最大的
STreeNode *swap = *pRoot;
while (swap->pRight)//找到最后一个右子树,不能为空
{
swap = swap->pRight;
}
(*pRoot)->key = swap->key;
return RemoveR(&((*pRoot)->pLeft), swap->key);
return 0;
}
void Test()
{
STreeNode *Node = NULL;
Insert(&(Node), 3);
Insert(&(Node), 5);
Insert(&(Node), 9);
Insert(&(Node), 3);
Insert(&(Node), 4);
Insert(&(Node), 1);
RemoveR(&Node, 4);
}
关于二叉搜索树的主要操作如上所示,其中有递归的方式,但若二叉搜索树过大,则会调用大量栈帧,严重影响效率。
由于代码都为亲力亲为,所思所写。 若有问题,欢迎随时之处。