题目:
输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。要求不能创建任何新的节点,只调整指针的指向。
解题原理:
节点10的左指针应该指向其左子树值最大的节点8,节点8的右指针应该指向节点10,节点10的右指针应该指向其右子树的最小节点12,节点12的左指针应该指向节点10。
因此采用需找pCurrent节点左子树的最大节点leftMaxNode,其右子树的最小节点rightMinNode,它们链接起来,依次递归,即可得到该树的双向链表。双向链表的头节点即为该树最左节点。
代码如下:
struct BSTreeNode{
int m_nValue;
BSTreeNode *m_pLeft;
BSTreeNode *m_pRight;
};
//将节点加入树中的恰当位置
void addBSTreeNode(BSTreeNode *&pCurrent, int nValue)
{
if(NULL == pCurrent)
{
// cout << "test" <<endl;
BSTreeNode *pBSTree = new BSTreeNode();
pBSTree->m_nValue = nValue;
pBSTree->m_pLeft = NULL;
pBSTree->m_pRight = NULL;
pCurrent = pBSTree;
}
// cout << "aa" << endl;
else
{
if(pCurrent->m_nValue > nValue)
{
addBSTreeNode(pCurrent->m_pLeft,nValue);
}
else if(pCurrent->m_nValue < nValue)
{
addBSTreeNode(pCurrent->m_pRight,nValue);
}
}
}
//双向链表的头结点,一定是一棵有序树的最小孩子节点
BSTreeNode * findHead(BSTreeNode *root)
{
if(NULL == root)
return NULL;
if(!root->m_pLeft)
{
return root;
}
return findHead(root->m_pLeft);
}
//查找左子树值最大的结点
BSTreeNode * findLeftMaxNode(BSTreeNode *pCurrent)
{
if(NULL == pCurrent)
return NULL;
if(NULL == pCurrent->m_pRight)
return pCurrent;
return findLeftMaxNode(pCurrent->m_pRight);
}
//查找右子树值最小结点
BSTreeNode * findRightMinNode(BSTreeNode *pCurrent)
{
if(NULL == pCurrent)
return NULL;
if(NULL == pCurrent->m_pLeft)
return pCurrent;
return findRightMinNode(pCurrent->m_pLeft);
}
/*将树转换成双向链表
其原理为:节点pCurrent的pre指针一定指向其左子树值最大的节点,
左子树值最大的节点的next指针一定指向pCurrent节点;
同理,pCurrent的next指针一定指向其右子树值最小的节点,
右子树值最小的节点的pre指针一定指向pCurrent
*/
void converToDoubleLink(BSTreeNode *pCurrent)
{
if(NULL == pCurrent || (!pCurrent->m_pLeft && !pCurrent->m_pRight))
return;
BSTreeNode *leftMaxNode = findLeftMaxNode(pCurrent->m_pLeft);
if(pCurrent->m_pLeft)
{
converToDoubleLink(pCurrent->m_pLeft);
}
pCurrent->m_pLeft = leftMaxNode;
if(leftMaxNode)
leftMaxNode->m_pRight = pCurrent;
BSTreeNode *rightMinNode = findRightMinNode(pCurrent->m_pRight);
if(pCurrent->m_pRight)
{
converToDoubleLink(pCurrent->m_pRight);
}
pCurrent->m_pRight = rightMinNode;
if(rightMinNode)
rightMinNode->m_pLeft = pCurrent;
}
//中序遍历二叉树
void traceMidTree(BSTreeNode *root)
{
if(NULL == root)
return;
if(root->m_pLeft)
{
traceMidTree(root->m_pLeft);
}
cout << root->m_nValue<<",";
traceMidTree(root->m_pRight);
}
//测试用
void addNodes()
{
BSTreeNode *root=NULL, *pHead,*pCurrent;
addBSTreeNode(root, 10);
addBSTreeNode(root, 6);
addBSTreeNode(root, 14);
addBSTreeNode(root, 4);
addBSTreeNode(root, 8);
addBSTreeNode(root, 12);
addBSTreeNode(root, 16);
traceMidTree(root);
cout<<endl;
pHead = findHead(root);
pCurrent = pHead;
converToDoubleLink(root);
while(pCurrent)
{
cout<< pCurrent->m_nValue<<",";
pCurrent = pCurrent->m_pRight;
}
}