二叉树之二叉查找树



    二叉树的一个重要应用是二叉查找树。假设树中每个节点被指定一个关键字值。使二叉树成为二叉查找树的性质是,对于树中的每个节点X,它的左子树中所有元素值小于X的值,而右子树中所有元素值大于X的值。这意味着,该树所有的元素可以用某种统一方式排序。如下图,左边是二叉查找树,但右边则不是(值为7的节点不符合要求)。

   下面我们对二叉查找树的操作简要描述。由于树的递归定义,通常是递归地编写这些操作的例程。因为二叉查找树的平均深度是O(log N),所以一般不必担心栈空间被用尽。

   首先,声明二叉查找树的数据结构和一些常见的操作函数。

#include <Tree.h>

//创建一个二叉查找树
#ifndef _Tree_H_
#define _Tree_H_

struct TreeNode{
	int element;  //节点存储信息可以根据需要修改!
	TreeNode* Left;
	TreeNode* Right;
};

void MakeEmpty(TreeNode* T);
TreeNode* Find(int X, TreeNode* T);
TreeNode* FindMin(TreeNode* T);
TreeNode* FindMax(TreeNode* T);
TreeNode* Insert(int X, TreeNode* T);
TreeNode* Delete(int X, TreeNode* T);

#endif

  下面,我们用高度递归的方法(大大减少代码量)分别实现这些操作。

#include <Tree.cpp>

#include "tree.h"
#include <stdlib.h>
#include <iostream>

void MakeEmpty(TreeNode* T)
{
	if(T)
	{
		MakeEmpty(T->Left);
		MakeEmpty(T->Right);
		delete T;
	}
}

TreeNode* Find(int X, TreeNode* T)
{
	if(!T)
		return NULL;
	else if(X < T->element)
		return Find(X,T->Left);
	else if(X > T->element)
		return Find(X,T->Right);
	else
		return T;
}

TreeNode* FindMin(TreeNode* T)  //这个用递归法
{
	if(!T)
		return NULL;
	else if(T->Left)
		return FindMin(T->Left);
	else
		return T;
}

TreeNode* FindMax(TreeNode* T)  //这个不用递归
{
	if(T)
		while(T->Right)
			T = T->Right;
	
	return T;
}

TreeNode* Insert(int X, TreeNode* T)
{
	if(!T)  //这个条件的判定一定要放在第一位!
	{
		T = new TreeNode;
		T->element = X;
		T->Left = T->Right = NULL;
	}
	else if(X < T->element)
	{
		T->Left = Insert(X, T->Left);
	}
	else if(X > T->element)
	{
		T->Right = Insert(X, T->Right);
	}
	else
		;  //如果X==T->element,表示X本来就在Tree中,什么也不需要做!

	return T;
}

TreeNode* Delete(int X, TreeNode* T)
{
	TreeNode* temp;
	if(!T)
		std::cout<<"没找到要删除的节点!";
	else if(X < T->element)
		T->Left = Delete(X, T->Left);
	else if(X > T->element)
		T->Right = Delete(X, T->Right);
	else if(T->Left && T->Right) //被删除节点有两个儿子
	{
		//用右子树中最小的节点来顶替被删除的节点
		//这种方法会造成二叉树整体向左倾斜
		temp = FindMin(T->Right);
		T->element = temp->element;
		T->Right = Delete(temp->element,T->Right); //继续递归
	}
	else //被删除节点有0或1个儿子
	{
		temp = T;
		if(!T->Left)
			T = T->Right;
		else
			T = T->Left;
		delete temp;
	}

	return T;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值