二叉查找树的解析与实现

二叉查找树是二叉树的一个特化,它具有的特殊性质是:对于树中的任何一个结点,它的左子树的所有结点的关键字都小于此结点的关键字,而右子树的所有结点的关键字都大于此结点的关键字.

二叉查找树的这种特殊性质使得它在查找元素的时候特别的方便,每一次查找都可以去掉一半的元素,因此查找的时间是O(logN).

二叉查找树的插入和查找算法也是很简单的,就是与当前结点的关键字作比较决定在右边还是左边继续操作.

二叉查找树最复杂的算法就是删除结点的算法了,根据所要删除的结点有两个子结点还是只有一个或者没有子结点会有不同的处理.有两个子结点的情况一般的处理是找到右子树中值最小的一个结点,将它的值替代当前的结点值,然后再把这个值最小的结点删除,也就是说有两个子结点的情况是用最小的一个大于当前结点关键字的结点替代了当前的结点(很拗口,但愿我说清楚了:)在只有一个或者没有子结点的情况就比较的简单了,如果还有子结点就把子结点的位置往上挪,然后把当前结点删除.

实现如下:

1)BSTree.h

/**//********************************************************************
    created:    2006/07/28
    filename:     BSTree.h
    author:        李创
                http://www.cppblog.com/converse/

    purpose:    二叉查找树的实现代码
*********************************************************************/

#ifndef BINARY_SEARCH_TREE_H
#define BINARY_SEARCH_TREE_H

#include <stdio.h>

template<typename T>
struct BTreeNode
{
    T    Data;
    BTreeNode* pLeft;
    BTreeNode* pRight;
    BTreeNode* pParent;

    BTreeNode(    T data = T(), BTreeNode<T>* Parent = NULL,
                BTreeNode<T>* Left = NULL, BTreeNode<T>* Right = NULL)
                : Data(data), pLeft(Left), pRight(Right), pParent(Parent)
    {
    }
};

template<typename T>
class BSTree
{
protected:
    BTreeNode<T>*    m_pRootNode;

public:
    BSTree(BTreeNode<T>* pRoot = NULL)
        : m_pRootNode(pRoot)
    {
    }
    ~BSTree();

    void            Display();
    BTreeNode<T>*    Insert(const T& data);
    BTreeNode<T>*    Find(const T& data);
    BTreeNode<T>*    FindMin();
    BTreeNode<T>*    FindMax();
    BTreeNode<T>*    Delete(const T& data);

private:
    void            Display(BTreeNode<T>* p);
    BTreeNode<T>*    Insert(const T& data, BTreeNode<T>* p);
    BTreeNode<T>*    Find(const T& data, BTreeNode<T>* p);
    BTreeNode<T>*    FindMin(BTreeNode<T>* p);
    BTreeNode<T>*    FindMax(BTreeNode<T>* p);
    BTreeNode<T>*    Delete(const T& data, BTreeNode<T>* p);

    void            DestructImpl(BTreeNode<T>* p);
};

#endif

时间: 2024-10-02 00:29:06

二叉查找树的解析与实现的相关文章

《程序设计解题策略》——1.4 利用改进型的二叉查找树优化动态集合的操作

1.4 利用改进型的二叉查找树优化动态集合的操作 我们知道,二叉查找树(binary search tree)能够支持多种动态集合操作,因此在程序设计竞赛中,二叉查找树起着非常重要的作用,它可以用来表示有序集合.建立索引或优先队列等.作用于二叉查找树上的基本操作时间是与树的高度成正比的:对于一棵含n个节点的二叉查找树,如果呈完全二叉树结构,则这些操作的最坏情况运行时间为O(log2n):但如果呈线性链结构,则这些操作的最坏情况运行时间退化为O(n).针对二叉查找树这种不平衡.不稳定的弊病,人们做

Photoshop详细解析古风人像的摄影和后期过程

  本教程主要使用Photoshop详细解析古风人像的摄影和后期过程,拍摄古风作品前,我们首先要了解什么是古风.我理解的古风为"具有古代韵味气息的文化及作品",所以在拍摄前后均围绕"古代韵味"做文章.既然构思的是清妆古韵,那在后期处理上自然就选择了偏冷的色调. 一.拍摄部分 1.场景 原计划是去青城山,因为当天拍摄时间有限,最后选择在市区内的望江公园,这个场地很多摄影师都去拍过,为了避免重复,我们没有去标志性的建筑拍摄,或者说有意避开了"热门"拍

JavaScript 预解析的原理及实现

事实上或某种现象证明并不是这样的,通过<JavaScript权威指南>及网上相关资料了解到,JavaScript有"预解析"行为.理解这一特性是很重要的,不然在实际开发中你可能会遇到很多无从解析的问题,甚至导致程序bug的存在.为了解析这一现象,也作为自己的一次学习总结,本文逐步引导你来认识JavaScript"预解析",如果我的见解有误,还望指正. (1) 如果JavaScript仅是运行时自上往下逐句解析的,下面的代码能正确运行是可以理解的,因为我们

PHP抓取网页、解析HTML常用的方法总结

  这篇文章主要介绍了PHP抓取网页.解析HTML常用的方法总结,本文只是对可以实现这两个需求的方法作了总结,只介绍方法,不介绍如何实现,需要的朋友可以参考下 概述 爬虫是我们在做程序时经常会遇到的一种功能.PHP有许多开源的爬虫工具,如snoopy,这些开源的爬虫工具,通常能帮我们完成大部分功能,但是在某种情况下,我们需要自己实现一个爬虫,本篇文章对PHP实现爬虫的方式做个总结. PHP实现爬虫主要方法 1.file()函数 2.file_get_contents()函数 3.fopen()-

控件-mscomm串口波形绘制范例,求大神解析这三个函数,急急急,绘制波形图的原理是什么,拜托了

问题描述 mscomm串口波形绘制范例,求大神解析这三个函数,急急急,绘制波形图的原理是什么,拜托了 //串口void CPort_testDlg::OnComm() { //if(stop)return; VARIANT m_input1; COleSafeArray m_input2; long lengthi; BYTE data[600]; CString str; int ai=0bi=0ci=0di=0; int sum=0; if(m_Comm.GetCommEvent()==2)

【原创】memcached 中的命令行参数解析

     本文主要是以 memcached 源码为例,讲解如何在 linux 下解析命令行参数.  安装 memcached 后,查看其可用选项:  ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 [root@Be

设计模式的解析和实现(C++)之四-Prototype模式

作用: 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. UML结构图: 抽象基类: 1)Prototype:虚拟基类,所有原型的基类,提供Clone接口函数 接口函数: 1)Prototype::Clone函数:纯虚函数,根据不同的派生类来实例化创建对象. 解析: Prototype模式其实就是常说的"虚拟构造函数"一个实现,C++的实现机制中并没有支持这个特性,但是通过不同派生类实现的Clone接口函数可以完成与"虚拟构造函数"同样的效果.举一个

CLR全面透彻解析: .NET应用程序可扩展性

借助 Microsoft .NET Framework,编程人员便可轻松获取由不同开发人员和公司构建的组件,并将这 些组件集成到自己的应用程序中.但仅当已知哪些组件是构建基础时才能轻松实现上述过程.如果在构建 时对所需组件一无所知(对于加载项,通常会遇到这种情况),那么事情就会变得更加困难.开发人员在 扩展其应用程序时经常会遇到问题.例如,应将加载项存储在数据库中还是磁盘上?开发人员应考虑已知 接口的加载项以获得激活类型吗?使用 AppDomain.AppDomainManager 和 AppD

设计模式的解析和实现(C++)之十四-Command模式

作用: 将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤消的操作. UML结构图: 解析: Comnand模式的思想是把命令封装在一个类中,就是这里的Command基类,同时把接收对象也封装在一个类中就是这里的Receiver类中,由调用这个命令的类也就是这里的Invoker类来调用.其实,如果弄清楚了Command模式的原理,就会发现其实它和注册回调函数的原理是很相似的,而在面向过程的设计中的回调函数其实和这里的Command类的作用是一