数据结构_二叉搜索树

目录:

  1. 搜索二叉树的主要操作:
    (1)插入数据
    (2).递归/非递归查找
    (3).递归/非递归删除
  2. 搜索二叉树的应用
    模拟实现一个简单字典, 判断一个单词是否在其中/拼写正确

搜索

在数据结构中,搜索一共分为以下几类:
在这里插入图片描述
这里主要说的是搜索二叉树的相关操作。。。

搜索二叉树

在这里插入图片描述

搜索二叉树的定义:

在这里插入图片描述

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;
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值