• About
    • Resume
A Game Developer also plays some guitar

Monthly Archives: May 2009

You are browsing the site archives by month.

二叉查找树(Binary Search Tree)

May 13, 2009 3:03 pm / Leave a Comment / Benny Chen

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

BinaryTree.h

#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

测试BST

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

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

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

fit

May 11, 2009 11:31 pm / Leave a Comment / Benny Chen

fit,再熟悉不过的单词了,不过最常见的用法是作“合适的;适宜的”的意思,今儿学习一种我没怎么见过的用法——“健康的”。

Andres Iniesta will be fit in time to play in the Champions League final for Barcelona against Manchester United after tests revealed that his injury  is not as serious as first thought.
伊涅斯塔将会以健康的身体赶上巴萨跟曼联的欧冠决赛,经过检查后表明他的伤并不是有当初所想的那么严重。

这真是一条令人欣慰的新闻。Yes, he’ll be fit!

Posted in: Learn a Word / Tagged: fit, iniesta

Villarreal Deny Ten-Man Barcelona La Liga Title

May 11, 2009 9:59 pm / Leave a Comment / Benny Chen
barca-villarreal

barca-villarreal

Barcelona came within seconds of winning La Liga but a late, late Villarreal goal forced them to put the champagne on ice…
只需要再等待几十秒,巴萨就可以提前3轮夺得联赛冠军,但潜水艇在最后时刻的绝杀让我们的香槟还得再冰上一阵子了…

哎,这个夜晚只能用尴尬来形容,比利亚雷尔着实给迫不及待庆祝夺冠的加泰罗尼亚人浇了盆冷水,好大的一盆!

更糟糕的事情是,Iniesta又再次拉伤,不过稍微好点的消息是不会影响到在罗马的欧冠决赛,但愿如此吧,祈祷……

Posted in: Visca Barça / Tagged: barca, la liga

hypocrisy

May 8, 2009 9:43 pm / 1 Comment / Benny Chen

在欧冠半决赛巴萨绝杀切尔西之后的新闻发布会,希丁克用非直接的愤怒抨击欧足联所谓的“阴谋论”。“阴谋论”根本就纯属扯淡,因为欧足联如果真的要“阴谋”搞掉切尔西,根本不用等到斯坦福桥,那些质疑巴萨晋级资格的人,你们是不是已经忘了第一回合在诺坎普裁判对巴萨的待遇,或者你们就压根没看过比赛吧?!

况且“阴谋论”这样的词希丁克这个老狡猾也没资格喊出来,看看这篇goal.com的报道吧。

CL Special: There Is No Barcelona-Chelsea Conspiracy – Guus Hiddink’s Korea 2002 Hypocrisy
欧冠专题:”没有什么阴谋!”看看希丁克在02年韩国的伪善!

今天学习的单词是——hypocrisy,意思是,伪善,虚伪,the practice of claiming to have higher standards or beliefs than is the case.
扩展单词,hypocrite – 伪君子,伪善者,hypocritical – 虚伪的,伪善的。

正好这个单词打头也是单词H,跟希丁克的名字一样。
Hiddink is a hypocritical person. In other words, Hiddink is a hypocrite.
当然,这样说有些严重了,我个人并不是那么讨厌希丁克。

Posted in: Learn a Word / Tagged: Hiddink, hypocrisy, hypocrite, hypocritical

让历史铭记这一刻

May 3, 2009 1:23 pm / Leave a Comment / Benny Chen
barca-madrid

barca-madrid

 Barca humiliated Real Madrid!

Posted in: Visca Barça / Tagged: barca, derby, real madrid

Post Navigation

 
Newer Posts →

LinkedIn

Milan Petrovic

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