【面试题】把二元查找树转变成排序的双向链表

          题目:输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。要求不能创建任何新的结点,只调整指针的指向。

  比如将二元查找树
                                            10
                                          /    \
                                        6      14
                                      /  \     /  \
                                   4     8  12 16
转换成双向链表
4=6=8=10=12=14=16。
定义二元查找树结点的数据结构如下:
    struct BSTreeNode // a node in the binary search tree
    {
        int        m_nValue; // value of node
        BSTreeNode *m_pLeft; // left child of node
        BSTreeNode *m_pRight; // right child of node
    };

分析与解答:可以中序遍历整棵树。按照这个方式遍历树,比较小的结点先访问。如果我们每访问一个结点,假设之前访问过的结点已经调整成一个排序双向链表,我们再把调整当前结点的指针将其链接到链表的末尾。当所有结点都访问过之后,整棵树也就转换成一个排序双向链表了。
  代码如下:
/* 建立二叉排序树 */
void addBSTreeNode(BSTreeNode *&pCurrent,int value)//在这个函数中会要改变指针值,一定要记得使用引用传递 
{ 
    if (pCurrent==NULL) 
    { 
        BSTreeNode* pBSTree=new BSTreeNode(); 
        pBSTree->m_nValue=value; 
        pBSTree->m_pLeft=NULL; 
        pBSTree->m_pRight=NULL; 
        pCurrent=pBSTree; 
    } 
    else if (pCurrent->m_nValue<value) 
    { 
        addBSTreeNode(pCurrent->m_pRight,value); 
    } 
    else if (pCurrent->m_nValue>value) 
    { 
        addBSTreeNode(pCurrent->m_pLeft,value); 
    } 
    else
    { 
        cout<<"重复节点"<<endl; 
    } 
 
}
/*将一颗二叉搜索树转换成一个双向链表*/
//pNode:当前节点,即子二叉树的根节点
//pLastNodeInList:双向链表中的最后一个节点
void convertToDoubleList(BSTreeNode* pNode, BSTreeNode*& pLastNodeInList)
{
         if(pNode == NULL)
            return;
		  BSTreeNode *pCurrent = pNode;
         /*转换左子树*/
		  if (pCurrent->m_pLeft != NULL)
            convertToDoubleList(pCurrent->m_pLeft, pLastNodeInList);
		   // 把当前节点放入双向链表中
		   pCurrent->m_pLeft = pLastNodeInList;//设置当前节点的左指针
		    
		   if(pLastNodeInList != NULL)
            pLastNodeInList->m_pRight = pCurrent;

            pLastNodeInList=pCurrent;
			// 转换右子树
         if (pCurrent->m_pRight != NULL)
            convertToDoubleList(pCurrent->m_pRight, pLastNodeInList);
}
//
BSTreeNode* Convert(BSTreeNode* pHeadOfTree)
{
      BSTreeNode *pLastNodeInList = NULL;//双链表最后一个节点
      convertToDoubleList(pHeadOfTree, pLastNodeInList);
           // 获取双向链表的头节点
      BSTreeNode *pHeadOfList = pLastNodeInList;
      while(pHeadOfList && pHeadOfList->m_pLeft)
            pHeadOfList = pHeadOfList->m_pLeft;

      return pHeadOfList; //返回双向链表的头节点

}


int main()
{
	/****创建二叉查找树****/
    BSTreeNode *pRoot=NULL; 
    addBSTreeNode(pRoot,10); 
    addBSTreeNode(pRoot,6); 
    addBSTreeNode(pRoot,14); 
    addBSTreeNode(pRoot,4); 
    addBSTreeNode(pRoot,8); 
    addBSTreeNode(pRoot,12); 
    addBSTreeNode(pRoot,16); 
	/***************转换为双向链表*******************/
 BSTreeNode *pHeadOfList=Convert(pRoot);
/**********************输出双向链表******************/
  while(pHeadOfList!=NULL)
	 {
	  cout<<pHeadOfList->m_nValue<<"->";
       pHeadOfList=pHeadOfList->m_pRight;
  }

  return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值