您的位置:首页 > 其它

【1】二元查找树转变成排序的双向链表

2014-02-24 23:13 302 查看

题目:



二元查找树【百度百科】


它首先要是一棵二元树,在这基础上它或者是一棵空树;或者是具有下列性质的二元树:

若左子树不空,则左子树上所有结点的值均小于它的根结点的值;

若右子树不空,则右子树上所有结点的值均大于它的根结点的值;

左、右子树也分别为二元查找树



分析


根据二元查找树的特点可知:节点A的左子树的值都小于A,A的右子树的值都大于A。

所以双向链表中,A的左边的值为左子树最右子树节点的值,而A的右边的值为右子树最左的子树节点的值,当然,这种分析不大适合直接写程序,效率不高。
对于只有三个节点的二元查找树,很容易获取其排序后的顺序值:左节点<父节点<右节点。找到了上述的规律后,用递归的思想,情况就变得比较简单了,比如对于一个节点A,其左子树构成的顺序表为LA,右子树构成的顺序表为RA,那么A以及其子节点构成的顺序表则是:LA<A<RA,如此,使用递归就很容易获取结果顺序表了,然后对顺序链表处理一下,即可获得所需的双向链表。
最后一种方法可根据树的遍历方法来排序的,还记得树的三种遍历方式(先序,中序,后续)?观察二元查找树的特殊性,发现:其左节点<中节点<右节点,这个顺序不是和树的中序遍历方式一样?那么可以直接套用二叉树的中序遍历来实现的啊!



中序遍历实现二元查找树转换为双向链表源码

class BSTreeNode
{
public:
int				_value;
BSTreeNode*		_pLeftTree;
BSTreeNode*		_pRightTree;
bool			_bSorted;
BSTreeNode(int value)
{
_value		= value;
_pLeftTree	= NULL;
_pRightTree	= NULL;
_bSorted	= false;
}
};
// 二叉树中序遍历
void BTreeMid(BSTreeNode* r)
{
stack<BSTreeNode*>	s;
BSTreeNode*			p = NULL;

s.push(r);
while(!s.empty())
{
p = s.top();
if(p && p->_bSorted == false)
{
s.push(p->_pLeftTree);
}
else
{
s.pop();
if(!s.empty())
{
p = s.top();
printf("%d ", p->_value);
p->_bSorted = true;
s.pop();
s.push(p->_pRightTree);
}
}
}
}
// 二叉树中序遍历转双向链表
void BSTreeToDQ(BSTreeNode* r)
{
stack<BSTreeNode*>	s;
BSTreeNode*			p = NULL;
BSTreeNode*			q = NULL;
BSTreeNode*			pHead = NULL;

s.push(r);
while(!s.empty())
{
p = s.top();
if(p && p->_bSorted == false)
{
s.push(p->_pLeftTree);
}
else
{
s.pop();
if(!s.empty())
{
p = s.top();
if(q)
{
p->_pLeftTree = q;
q->_pRightTree = p;
}
else
{
pHead = p;
}
q = p;
p->_bSorted = true;
s.pop();
s.push(p->_pRightTree);
}
}
}
q->_pRightTree = pHead;
pHead->_pLeftTree = q;

/*for (p=pHead; p!=pHead->_pLeftTree; p=p->_pRightTree)
{
printf("%d ", p->_value);
}*/
}


运行结果





内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: