目录:
- 搜索二叉树的主要操作:
(1)插入数据
(2).递归/非递归查找
(3).递归/非递归删除 - 搜索二叉树的应用
模拟实现一个简单字典, 判断一个单词是否在其中/拼写正确
搜索
在数据结构中,搜索一共分为以下几类:
这里主要说的是搜索二叉树的相关操作。。。
搜索二叉树
搜索二叉树的定义:
typedef struct BStree
{
BSDataType data;
struct BStree* _pLeft;
struct BStree* _pRight;
}BStree;
搜索二叉树递归和非递归查找:
- 和根对比,如果相等 返回
- 大于跟,向右子树查找
- 小于根,向左子树查找
非递归:
int BStreeFind (BStree* root, BSDataType data)//查找,成功返回1;失败返回0
{
BStree* cur = root;
if (root == NULL)
{
return 0;
}
while (cur)//cur不为空时
{
if (data == cur->data) //如果两个数相等,就找到了
{
return 1;
}
else if (data > cur->data) //数据大于当前结点的数据,朝右找
{
cur = cur->_pRight;
}
else //数据小于当前结点的数据,朝左找
{
cur = cur->_pLeft;
}
}
return 0;
}
运行结果:
递归:
int BStreeFind_RE (BStree* root, BSDataType data)//递归查找,成功返回1;失败返回0
{
if (root == NULL)
{
return 0;
}
if (root->data > data)
{
return BStreeFind_RE (root->_pLeft, data);
}
else if (root->data < data)
{
return BStreeFind_RE (root->_pRight, data);
}
else
{
return 1;
}
}
搜索二叉树插入数据(数据不能重复,如果重复,插入失败):
- 先给要插入的元素找到合适的位置
- 在该位置插入元素
int BStreeInsert (BStree** root, BSDataType data)//插入数据,成功返回1,失败返回0
{
BStree* cur = NULL;
BStree* parent = NULL;
BStree* newNode = NULL;
assert (root != NULL);
cur = (*root);
while (cur != NULL)
{
if (cur->data == data)
{
return 0;//数据重复,插入失败
}
else if (cur->data > data)
{
parent = cur;
cur = cur->_pLeft;
}
else
{
parent = cur;
cur = cur->_pRight;
}
}
newNode = (BStree*)malloc (sizeof (BStree));
if (newNode == NULL)
{
//开辟空间失败
perror ("BStreeInsert::malloc>>");
return 0;
}
newNode->data = data;
newNode->_pLeft = NULL;
newNode->_pRight = NULL;
if (parent == NULL)//如果树为空
{
(*root) = newNode;
return 1;
}
if (data > parent->data)
{
//往右边插
parent->_pRight = newNode;
}
else
{
//往左边插
parent->_pLeft = newNode;
}
return 1;
}
通过中序遍历打印结果为:
递归和非递归的删除:
1、左为空
- 要删除的是根, 还是parent的左, 还是parent的右
2、右为空
- 要删除的是根,还是parent的左,还是parent的右
3、左右都不为空
(1)找左子树中最大的
- 最大的就是它的左孩子
- 最大的不是它的左孩子(是它左孩子最右边的孩子)
非递归:
int BStreeRemove (BStree** root, BSDataType data)//删除(非递归)
{
BStree* cur = *root;
BStree* parent = NULL;
//先找到要删除的节点
while (cur)
{
if (cur->data == data)
{
//找到了,这个节点就是要删除的节点
if (cur->_pLeft == NULL) //只有右孩子
{
if (parent == NULL) //要删除的就是根节点
{
(*root) = cur->_pRight;
}
else
{
if (data > parent->data)//cur 是 parent 的右孩子
{
parent->_pRight = cur->_pRight;
}
else //cur 是 parent 的左孩子
{
parent->_pLeft = cur->_pRight;
}
}
free (cur);
cur = NULL;
return 1;
}
else if (cur->_pRight == NULL) //只有左孩子
{
if (parent == NULL)//要删除的就是根节点
{
(*root) = cur->_pLeft;
}
else
{
if (data > parent->data)//cur 是 parent 的右孩子
{
parent->_pRight = cur->_pLeft;
}
else //cur 是 parent 的左孩子
{
parent->_pLeft = cur->_pLeft;
}
}
free (cur);
cur = NULL;
return 1;
}
else//左右孩子都有
{
//找cur左子树中最大的节点
BStree* del = cur->_pLeft;
BStree* delParent = NULL;
while (del->_pRight != NULL)
{
delParent = del;
del = del->_pRight;
}//del就是cur左子树中最大的节点
cur->data = del->data;
if (delParent == NULL) //cur 的左孩子没有右子树
{
cur->_pLeft = del->_pLeft;
}
else
{
delParent->_pRight = del->_pLeft;
}
free (del);
del = NULL;
return 1;
}
}
else if (cur->data > data)//data 小于当前节点---> 朝左找
{
parent = cur;
cur= cur->_pLeft;
}
else //data 大于当前节点---> 朝右找
{
parent = cur;
cur= cur->_pRight;
}
}
return 0;
}
运行结果:
递归:
void BStreeRemove_RE (BStree** root, BSDataType data)//删除(递归)
{
assert (root != NULL);
if (*root == NULL)
{
return ;
}
if ((*root)->data > data)//当前节点大于data --> 朝左找
{
return BStreeRemove_RE(&((*root)->_pLeft), data);
}
else if ((*root)->data < data)//当前节点小于data --> 朝右找
{
return BStreeRemove_RE(&((*root)->_pRight), data);
}
else//当前节点等于data --> 找到了,这就是要删除的节点
{
BStree* del = *root;
if (del ->_pLeft == NULL)//只有右孩子
{
(*root) = (*root)->_pRight;
}
else if ((*root)->_pRight == NULL)//只有左孩子
{
(*root) = (*root)->_pLeft;
}
else //左右孩子都有
{
BStree* cur = del->_pLeft;
BStree* curParent = NULL;
if (cur->_pRight != NULL)
{
curParent = cur;
cur = cur->_pRight;
}//cur 是del左孩子(左子树)中最大的节点
del->data = cur->data;//让del中的值等于cur中的值,再删除cur
if (curParent == NULL)//del的左孩子没有右子树
{
del->_pLeft = cur->_pLeft;
}
else//del的左孩子有右子树
{
curParent->_pRight = cur->_pRight;
}
free (cur);
cur = NULL;
}
}
}
运行结果:
///
二叉排序树的应用:模拟实现一个简单字典, 判断一个单词是否在其中/拼写正确
头文件dictionary.h :
#ifndef __DICT_H__
#define __DICT_H__
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
typedef struct EnAndHan
{
char key[20];
char trans[20];
}BSDataType;
typedef struct DICT
{
BSDataType data;
struct DICT* _pLeft;
struct DICT* _pRight;
}Dict;
void BStreeInorder (Dict* root);//中序遍历二叉树
int BStreeInsert (Dict** root, BSDataType data);//插入
char* BStreeFind (Dict* root, char* data);//查找
#endif
主要函数main.c
#include "dictionary.h"
int BStreeInsert (Dict** root, BSDataType data)//插入数据,成功返回1,失败返回0
{
Dict* cur = NULL;
Dict* parent = NULL;
Dict* newNode = NULL;
assert (root != NULL);
cur = (*root);
while (cur != NULL)
{
if (strcmp(cur->data.key, data.key) == 0)
{
return 0;//数据重复,插入失败
}
else if (strcmp(cur->data.key, data.key) > 0)
{
parent = cur;
cur = cur->_pLeft;
}
else
{
parent = cur;
cur = cur->_pRight;
}
}
newNode = (Dict*)malloc (sizeof (Dict));
if (newNode == NULL)
{
//开辟空间失败
perror ("DictInsert::malloc>>");
return 0;
}
strcpy(newNode->data.key, data.key);
strcpy(newNode->data.trans, data.trans);
newNode->_pLeft = NULL;
newNode->_pRight = NULL;
if (parent == NULL)//如果树为空
{
(*root) = newNode;
return 1;
}
if (strcmp (data.key, parent->data.key) > 0)
{
//往右边插
parent->_pRight = newNode;
}
else
{
//往左边插
parent->_pLeft = newNode;
}
return 1;
}
void BStreeInorder (Dict* root)//中序遍历二叉树
{
if (root == NULL)
{
return;
}
BStreeInorder (root->_pLeft);
printf ("%s :: %s\n", root->data.key, root->data.trans);
BStreeInorder (root->_pRight);
}
char* BStreeFind (Dict* root, char* data)//查找,成功返回单词意思;失败返回NULL
{
Dict* cur = root;
if (root == NULL)
{
return 0;
}
while (cur)
{
if (strcmp(data, cur->data.key) == 0)
{
return cur->data.trans;
}
else if (strcmp(data, cur->data.key) > 0)
{
cur = cur->_pRight;
}
else
{
cur = cur->_pLeft;
}
}
return 0;
}
功能测试test.c:
#include "dictionary.h"
int main()
{
int i = 0;
int num = 0;
char* ret = NULL;
int tmp = 0;
BSDataType data;
Dict *root = NULL;
printf ("请输入你要存的单词个数:");
scanf ("%d", &num);
printf("输入你要存入的单词和对应的汉语翻译:\n");
for (i=0; i<num; ++i)
{
scanf ("%s", data.key);
scanf ("%s", data.trans);
tmp = BStreeInsert(&root, data);
printf ("%s\n", tmp?"插入成功!!!":"插入失败!!!");
}
printf ("\n*****************************************************\n");
BStreeInorder (root);
printf ("\n*****************************************************\n");
ret = BStreeFind(root, "apple");
printf("查找apple:\n");
printf ("%s\n\n", (ret != NULL)?ret:"没有该单词或拼写错误");
ret = BStreeFind(root, "appple");
printf("查找appple:\n");
printf ("%s\n\n", (ret != NULL)?ret:"没有该单词或拼写错误");
system ("pause");
return 0;
}