面试题27 二叉搜索树转换成双向链表

分析:

1. 二叉树中,每个结点都有两个指向子结点的指针。

2. 在双向链表中,每个结点也有两个指针,分别指向前一个结点后一个结点

3. 二叉搜索树中,左子结点的值总是小于父结点的值,右子结点的值总是大于父结点的值。

4. 将二叉搜索树转换为双向链表时,原先指向左子结点的指针调整为链表中指向前一个结点的指针,原先指向右子结点的指针调整为链表中指向后一个结点的指针。

5. 由于要求转换之后的链表是排好序的,所以我们采取中序遍历

6. 当遍历转换到根结点时,左子树已经转换成了一个排序的链表了,并且处在链表中的最后一个结点是当前值最大的结点,将其与根结点连接起来,接着去遍历转换右子树,并把根结点和右子树中的最小的结点连接起来。

代码:

[cpp]  view plain copy
  1. #include "stdafx.h"  
  2. #include <iostream>  
  3. using namespace std;  
  4.   
  5. struct BinaryTreeNode  
  6. {  
  7.     int m_nValue;  
  8.     BinaryTreeNode *m_pLeft;  
  9.     BinaryTreeNode *m_pRight;  
  10. };  
  11.   
  12. void Convert(BinaryTreeNode *pRoot, BinaryTreeNode *&pLastInList)  
  13. {  
  14.     if (pRoot == NULL)  
  15.     {  
  16.         return;  
  17.     }  
  18.   
  19.     BinaryTreeNode *pCurrentNode = pRoot;  
  20.   
  21.     if (pCurrentNode->m_pLeft != NULL)  
  22.     {  
  23.         Convert(pCurrentNode->m_pLeft, pLastInList);  
  24.     }  
  25.   
  26.     pCurrentNode->m_pLeft = pLastInList;  
  27.     if (pLastInList != NULL)  
  28.     {  
  29.         pLastInList->m_pRight = pCurrentNode;      
  30.     }     
  31.     pLastInList = pCurrentNode;  
  32.   
  33.     if (pCurrentNode->m_pRight != NULL)  
  34.     {  
  35.         Convert(pCurrentNode->m_pRight, pLastInList);  
  36.     }     
  37. }  
  38.   
  39. BinaryTreeNode *ConvertBSTToDoubleList(BinaryTreeNode *pRoot)  
  40. {  
  41.     if (pRoot == NULL)  
  42.     {  
  43.         return NULL;  
  44.     }  
  45.   
  46.     BinaryTreeNode *pLastInList = NULL;//指向排好序的双向链表的最后一个结点  
  47.     Convert(pRoot, pLastInList);  
  48.     while (pLastInList->m_pLeft != NULL)//返回到头结点  
  49.     {  
  50.         pLastInList = pLastInList->m_pLeft;  
  51.     }  
  52.     return pLastInList;  
  53. }  
  54.   
  55. //以先序的方式构建二叉树,输入-1表示结点为空  
  56. void CreateBinaryTree(BinaryTreeNode *&pRoot)  
  57. {  
  58.     int nNodeValue = 0;  
  59.     cin >> nNodeValue;      
  60.     if (-1 == nNodeValue)  
  61.     {  
  62.         pRoot = NULL;  
  63.         return;   
  64.     }  
  65.     else  
  66.     {  
  67.         pRoot = new BinaryTreeNode();  
  68.         pRoot->m_nValue = nNodeValue;  
  69.         CreateBinaryTree(pRoot->m_pLeft);  
  70.         CreateBinaryTree(pRoot->m_pRight);  
  71.     }  
  72. }  
  73.   
  74. void PrintInOrder(BinaryTreeNode *&pRoot)//中序遍历二叉树  
  75. {  
  76.     if (pRoot != NULL)  
  77.     {  
  78.         PrintInOrder(pRoot->m_pLeft);  
  79.         cout << pRoot->m_nValue << " ";  
  80.         PrintInOrder(pRoot->m_pRight);  
  81.     }  
  82. }  
  83.   
  84. void PrintDoubleListFromLeftToRight(BinaryTreeNode *pRoot)//从左到右打印双向链表  
  85. {  
  86.     if (pRoot == NULL)  
  87.     {  
  88.         return;  
  89.     }  
  90.   
  91.     BinaryTreeNode *pNode = pRoot;  
  92.     while (pNode != NULL)  
  93.     {  
  94.        cout << pNode->m_nValue << " ";  
  95.        pNode = pNode->m_pRight;  
  96.     }  
  97.     cout << endl;  
  98. }  
  99.   
  100. void PrintDoubleListFromRightToLeft(BinaryTreeNode *pRoot)//从右向左打印双向链表  
  101. {  
  102.     if (pRoot == NULL)  
  103.     {  
  104.         return;  
  105.     }  
  106.   
  107.     BinaryTreeNode *pNode = pRoot;  
  108.     while (pNode->m_pRight != NULL)  
  109.     {         
  110.         pNode = pNode->m_pRight;  
  111.     }  
  112.   
  113.     while (pNode != NULL)  
  114.     {  
  115.         cout << pNode->m_nValue << " ";  
  116.         pNode = pNode->m_pLeft;  
  117.     }  
  118.     cout << endl;  
  119. }  
  120.   
  121. int _tmain(int argc, _TCHAR* argv[])  
  122. {  
  123.     BinaryTreeNode *pRoot = NULL;  
  124.     CreateBinaryTree(pRoot);  
  125.     PrintInOrder(pRoot);//4 6 8 10 12 14 16  
  126.     cout << endl;  
  127.     BinaryTreeNode *pDoubleListHead = ConvertBSTToDoubleList(pRoot);  
  128.     PrintDoubleListFromLeftToRight(pDoubleListHead);//4 6 8 10 12 14 16  
  129.     PrintDoubleListFromRightToLeft(pDoubleListHead);//16 14 12 10 8 6 4  
  130.     system("pause");  
  131.     return 0;  
  132. }  
运行结果:


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值