您的位置:首页 > 其它

bst double Linked List

2015-05-31 12:49 134 查看
struct BSTreeNode //二分查找树中的一个节点

{

int m_nValue; //
节点的值

BSTreeNode *m_pLeft; //
左指针域

BSTreeNode *m_pRight; //
右指针域

};

然后,我们就可以根据以上递归的思想一步一步写出c++源码了

BSTreeNode* ConvertNode(BSTreeNode* pNode, bool asRight)

{ //如果是空数,那么返回空指针

if(!pNode)

return NULL;

//定义两个指针,存放当前节点的左双向链表的根河和右双向链表的根

BSTreeNode *pLeft = NULL;

BSTreeNode *pRight = NULL;

//先将左子数转换为双向链表,注意这里的第二个参数是false,表示左子数节点转换为左双向链表

if(pNode->m_pLeft)

pLeft = ConvertNode(pNode->m_pLeft, false);

//如果左双向链表不为空,那么就正确地链接到当前节点pNode上

if(pLeft)

{

pLeft->m_pRight
= pNode;

pNode->m_pLeft
= pLeft;

}

//再将右子数转换为双向链表,注意这里的第二个参数是true,表示右子数节点转换为右双向链表

if(pNode->m_pRight)

pRight = ConvertNode(pNode->m_pRight, true);

//如果右双向链表不为空,那么就正确地链接到当前节点pNode上

if(pRight)

{

pNode->m_pRight
= pRight;

pRight->m_pLeft
= pNode;

}

//到了这里,当前节点pNode以及它的子数已经被转换为双向链表了,最后一步,就是怎样将转换好的双向链表的头指针返回呢?显然,我们应该根据当前节点在原子数中的位置判断,如果当前节点pNode在原来的树种是以右节点的形式存在的,那么以当前节点为头指针的双向链表应该返回整个以pNode为根节点的子数中最小的节点,也即最左的节点,反之,则返回最右的节点,以下代码便是这段文字的代码描述

BSTreeNode *pTemp = pNode;

if(asRight)

{

while(pTemp->m_pLeft)

pTemp
= pTemp->m_pLeft;

}

else

{

while(pTemp->m_pRight)

pTemp
= pTemp->m_pRight;

}

return pTemp;

}

最后,我们就可以用一个主函数来对以上一段程序进行包装,以形成一个独立功能的函数

BSTreeNode* Convert(BSTreeNode* pHeadOfTree)

{

//这里,第二个参数为true,即把整个树当做是右子数看待,这样,最终就能返回整个树中的最小的节点了.

return ConvertNode(pHeadOfTree, true);

}

思路之二是中序遍历二元查找树,由于中序遍历是从小到大遍历的,所以可以假设在遍历某一个子树的根节点的时候其左子树已经是一个排序双向链表了,并且如果再得到该双向链表的为指针,可以很轻易地将其与根节点相连,然后同样可以使得右子数成为一个排序双向链表,然后将根节点轻而易举的链接到右子数组成的排序双向链表.

//此函数的功能是将以pNode为根的树转换为排序双向链表,并且将她链接到以pLastNodeInList为已经调整好的双向链表的尾节点上

void ConvertNode(BSTreeNode*
pNode, BSTreeNode*& pLastNodeInList)

{

if(pNode
== NULL)

return;

BSTreeNode *pCurrent = pNode;

//装换左子树

if (pCurrent->m_pLeft
!= NULL)

ConvertNode(pCurrent->m_pLeft,
pLastNodeInList);

//将当前节点链接到已调整好的双向链表的尾节点,pLastNodeInList为已经转换好的双向链表的尾指针

pCurrent->m_pLeft
= pLastNodeInList;

if(pLastNodeInList
!= NULL)

pLastNodeInList->m_pRight
= pCurrent;

//然后当前节点就成了双向链表中的最后一个节点

pLastNodeInList = pCurrent;

//所以转换右子数的时候,可以很顺利地将双向链表中的最后一个节点与右子数装换好的双向链表相连

if (pCurrent->m_pRight
!= NULL)

ConvertNode(pCurrent->m_pRight,
pLastNodeInList);

}

BSTreeNode* Convert_Solution1(BSTreeNode* pHeadOfTree)

{

//由于一开始已经调整好的双向链表为空,所以尾指针为空

BSTreeNode *pLastNodeInList = NULL;

//将整个树转换为双向链表的时候,pLastNodeInList就成了链表中的最后一个节点

ConvertNode(pHeadOfTree,
pLastNodeInList);

//然后链表指针不断向前移动,便得到了头节点的指针

BSTreeNode *pHeadOfList = pLastNodeInList;

while(pHeadOfList
&& pHeadOfList->m_pLeft)

pHeadOfList = pHeadOfList->m_pLeft;

return pHeadOfList;

}

将排序二叉树转化成双向链表,应该是一道很常见的面试题目,网上的实现比较多,有用递归也有用中序遍历法的。看到一位外国友人的实现,还是比较清晰的,思路如下:

1,如果左子树不为null,处理左子树

1.a)递归转化左子树为双向链表;

1.b)找出根结点的前驱节点(是左子树的最右的节点)

1.c)将上一步找出的节点和根结点连接起来

2,如果右子树不为null,处理右子树(和上面的很类似)
1.a)递归转化右子树为双向链表;
1.b)找出根结点的后继节点(是右子树的最左的节点)
1.c)将上一步找出的节点和根结点连接起来
3,找到最左边的节点并返回

附上国外友人的链接:http://www.geeksforgeeks.org/in-place-convert-a-given-binary-tree-to-doubly-linked-list/

下面是代码实现:

bintree2listUtil函数返回的node* 是root节点,bintree2list函数返回的是头节点
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: