• About
    • Resume
A Game Developer also plays some guitar

Tag Archives: Tree

二叉查找树(Binary Search Tree)

May 13, 2009 3:03 pm / Benny Chen

今天下午闲着无聊,复习了一下“二叉查找树”,并用代码温习了一下。
对于二叉查找树,一般支持的操作有:查找关键字,最大值,最小值,前驱和后继等等的查询,对于高度为h的树,它们都可以在O(h)时间内完成。

BinaryTree.h
[cpp collapse=”true”]
#ifndef __BINARY_TREE_H__
#define __BINARY_TREE_H__

template < typename Key, typename Data > class BinaryTree;

/*! 树的节点 */
template < typename Key, typename Data >
class TreeNode
{
public:
//! 默认构造函数
TreeNode()
: m_pParent( NULL ),
m_pLChild( NULL ),
m_pRChild( NULL )
{
}

//! 构造函数
TreeNode( Key k, const Data & d )
: m_pParent( NULL ),
m_pLChild( NULL ),
m_pRChild( NULL ),
m_key( k ),
m_data( d )
{
}

//! 拷贝构造函数
TreeNode( const TreeNode< Key, Data > & node )
: m_pParent( NULL ),
m_pLChild( NULL ),
m_pRChild( NULL ),
m_key( node.m_key ),
m_data( node.m_data )
{
}

//! 赋值函数
TreeNode< Key, Data > & operator=( const TreeNode< Key, Data > & rhs )
{
m_key = rhs.m_key;
m_data = rhs.m_data;
return *this;
}

//! 获取键值
Key GetKey() const { return m_key; }
//! 获取数据
Data GetData() const { return m_data; }
//! 设置数据
void SetData( const Data & d ) { m_data = d; }

private:
Key m_key; //!< 关键字
Data m_data; //!< 数据
TreeNode *m_pParent; //!< 父节点
TreeNode *m_pLChild; //!< 左子节点
TreeNode *m_pRChild; //!< 右子节点

friend class BinaryTree< Key, Data >;
};

/*! 二叉查找树 */
template < typename Key, typename Data >
class BinaryTree
{
public:
BinaryTree()
:m_pRoot( NULL )
{
}

~BinaryTree()
{
while ( m_pRoot != NULL )
{
DeleteNode( m_pRoot );
}
}

typedef TreeNode< Key, Data > _TreeNode;

//! 查找
_TreeNode * Search( const Key & destK ) const;

//! 最小值
_TreeNode * Minimum( _TreeNode * pNode ) const;

//! 最大值
_TreeNode * Maximum( _TreeNode * pNode ) const;

//! 后继
_TreeNode * Successor( _TreeNode * pNode ) const;

//! 前任
_TreeNode * Predecessor( _TreeNode * pNode ) const;

//! 添加节点
void AddNode( const _TreeNode * pNode );

//! 删除节点
void DeleteNode( _TreeNode * pNode );

//! 获取根节点
_TreeNode * GetRootNode() const { return m_pRoot; }

private:
_TreeNode *m_pRoot; //! 根节点
};

template < typename Key, typename Data >
void BinaryTree< Key, Data >::AddNode( const _TreeNode * pNode )
{
assert( NULL != pNode &&
"pNode cannot be NULL" );

_TreeNode *newNode = new _TreeNode( *pNode );
_TreeNode *n1 = m_pRoot;
_TreeNode *n2 = NULL;
while ( NULL != n1 )
{
n2 = n1;
if ( newNode->m_key < n2->m_key )
{
n1 = n2->m_pLChild;
}
else
{
n1 = n2->m_pRChild;
}
}
if ( NULL == m_pRoot )
{
m_pRoot = newNode;
}
else
{
if ( newNode->m_key < n2->m_key )
{
n2->m_pLChild = newNode;
}
else
{
n2->m_pRChild = newNode;
}
newNode->m_pParent = n2;
}
}

template < typename Key, typename Data >
void BinaryTree< Key, Data >::DeleteNode( _TreeNode * pNode )
{
assert( NULL != pNode &&
"pNode cannot be NULL" );

_TreeNode * n1 = NULL;
_TreeNode * n2 = NULL;

//! n1是要删除的节点
if ( NULL == pNode->m_pLChild || NULL == pNode->m_pRChild )
{
//! 没有或者只有1个子节点,删除的节点时pNode
n1 = pNode;
}
else
{
//! 左右子节点都有,先删除pNode的后继结点
n1 = Successor( pNode ); // 该后继一定没有左节点
}

//! n2是n1唯一的一个子节点
if ( NULL != n1->m_pLChild )
{
n2 = n1->m_pLChild;
}
else
{
n2 = n1->m_pRChild;
}

//! 为删除n1所作的指针修改
if ( NULL != n2 )
{
n2->m_pParent = n1->m_pParent;
}
if ( NULL == n1->m_pParent )
{
// Root是唯一的一个父节点为空的节点
m_pRoot = n2;
}
else
{
if ( n1 == n1->m_pParent->m_pLChild )
{
n1->m_pParent->m_pLChild = n2;
}
else
{
n1->m_pParent->m_pRChild = n2;
}
}

if ( n1 != pNode )
{
//! pNode左右子节点都有的情况,
//! 用pNode的后继结点的关键字和附加数据替换掉pNode的关键字和附加数据
pNode->m_key = n1->m_key;
pNode->m_data = n1->m_data;
}

delete n1;
}

template < typename Key, typename Data >
TreeNode< Key, Data > * BinaryTree< Key, Data >::Search( const Key & destK ) const
{
_TreeNode *n = m_pRoot;
while ( NULL != n && destK != n->m_key )
{
if ( destK < n->m_key )
{
n = n->m_pLChild;
}
else
{
n = n->m_pRChild;
}
}

return n;
}

template < typename Key, typename Data >
TreeNode< Key, Data > * BinaryTree< Key, Data >::Minimum( _TreeNode * pNode ) const
{
assert( NULL != pNode &&
"pNode cannot be NULL" );

while ( NULL != pNode->m_pLChild )
{
pNode = pNode->m_pLChild;
}

return pNode;
}

template < typename Key, typename Data >
TreeNode< Key, Data > * BinaryTree< Key, Data >::Maximum( _TreeNode * pNode ) const
{
assert( NULL != pNode &&
"pNode cannot be NULL" );

while ( NULL != pNode->m_pRChild )
{
pNode = pNode->m_pRChild;
}

return pNode;
}

template < typename Key, typename Data >
TreeNode< Key, Data > * BinaryTree< Key, Data >::Successor( _TreeNode * pNode ) const
{
assert( NULL != pNode &&
"pNode cannot be NULL" );

//! 2 cases
if ( NULL == pNode->m_pRChild )
{
//! 1: 右子树为空
//! 向上查找直到遇到某个是其父节点的左儿子的节点时为止
while ( NULL != pNode->m_pParent && pNode->m_pParent->m_pLChild != pNode )
{
pNode = pNode->m_pParent;
}
return pNode->m_pParent;
}
else
{
//! 2: 右子树不为空,后继即为右子树中的最左节点
return Minimum( pNode->m_pRChild );
}
}

template < typename Key, typename Data >
TreeNode< Key, Data > * BinaryTree< Key, Data >::Predecessor( _TreeNode * pNode ) const
{
assert( NULL != pNode &&
"pNode cannot be NULL" );

//! 2 cases
if ( NULL == pNode->m_pRChild )
{
//! 1: 左子树为空
//! 向上查找直到遇到某个是其父节点的右儿子的节点时为止
while ( NULL != pNode->m_pParent && pNode->m_pParent->m_pRChild != pNode )
{
pNode = pNode->m_pParent;
}
return pNode->m_pParent;
}
else
{
//! 2: 左子树不为空,前任即为左子树中的最右节点
return Maximum( pNode->m_pLChild );
}
}

#endif
[/cpp]

测试BST
[cpp]
#include "BinaryTree.h"

int num[11] = { 15, 6, 18, 3, 2, 4, 7, 13, 9, 17, 20 };

int _tmain(int argc, _TCHAR* argv[])
{
BinaryTree< int, int > myTree;
typedef TreeNode< int, int > Node;

for ( int i = 0; i < 11; i ++ )
{
int x = num[i];
Node n( x, 0 );

myTree.AddNode( n );
}

Node *pRoot = myTree.GetRootNode();
Node *min = myTree.Minimum( pRoot );
Node *max = myTree.Maximum( pRoot );

Node *someNode = myTree.Search( 17 );
Node *pre = myTree.Predecessor( someNode );
Node *suc = myTree.Successor( someNode );

myTree.DeleteNode( suc );

return 0;
}
[/cpp]

参考资料:算法导论P151-P158

Posted in: Talking in Code / Tagged: binary search, tree

Categories

  • In My Life (25)
    • A Day in the Life (8)
    • English Learning (2)
    • Learn a Word (7)
    • Something In The Way (8)
  • Music Heaven (8)
    • Guitar (1)
    • In Concert (1)
    • Lyrics (3)
  • OK Computer (54)
    • 3D (3)
    • C++ (10)
    • Computer Graphics (15)
    • Game Programming (23)
    • iOS (6)
    • Linux (1)
    • Lua (9)
    • My Projects (3)
    • Some Experiences (9)
    • Talking in Code (2)
    • Unity (2)
  • Quotations (2)
  • Uncategorized (1)
  • Visca Barça (24)
    • FCB BJ (5)

Recent Posts

  • [译]优化你的手机游戏(没有延迟的,才是健康的)- 一篇给游戏美术设计师读的文章
  • 新浪微博API for MOAI
  • 稍后继续
  • Unity Developer ++
  • Another Thread @ Moai Forum
  • 1st Day of Golden Week
  • 为SyntaxHighlighter添加新语言
  • 基于Lua的State Pattern
  • Class Diagram of Pacman
  • 基于Moai的Pacman

Recent Comments

  • 约修亚_RK on 为SyntaxHighlighter添加新语言
  • 爱装的小男孩 on 小心DLL链接静态库时的内存错误
  • happyfire on Game Loop的几种实现方式
  • William on 新浪微博API for MOAI
  • Benny Chen on 新浪微博API for MOAI
  • your man on 新浪微博API for MOAI
  • 你家男人 on 稍后继续
  • 逍遥 on 关于对std::vector的遍历
  • papa on Unity Developer ++
  • T客网 ︱ Techpot » Blog Archive » iOS开发与OpenGL ES相关问题整理(1) on iOS开发与OpenGL ES相关问题整理(1)

Tags

2d 3D 3dsmax 3ds max air Apply architecture Asia tour barca Beijing bilbao binary search blocked bob boost bruce springsteen C++ capo CGContextDrawImage Champions League Change DLL DX10 eval exporter flash framework frustum culling game game engine iniesta ios linux lua Moai opengles pacman plug-in plugin 北京 导出插件 崩溃 巴萨 游戏引擎 踢球
© Copyright 2026 - A Game Developer
Infinity Theme by DesignCoral / WordPress