把二元查找树转变成排序的双向链表

来源:互联网 发布:js将字符串转换成json 编辑:程序博客网 时间:2024/06/06 00:24

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

   

转换成双向链表4=6=8=10=12=14=16

首先,我们定义的二元查找树结点的数据结构如下:

struct BSTreeNode

{

    int m_nValue;

    BSTreeNode * m_pLeft;

    BSTreeNode * m_pRIght;

};

解题思路:

1、构建一颗二叉查找树。

2、定义一个双向链表的全局变量pHead。

3、因为要保证链表的顺序,所以需要中序遍历。

4、因为不能创建任何新的结点,所以,需要重复利用树的结点。

5、因为,没有前驱和后继指针,所以,需要利用二叉树的左孩子指针和右孩子指针,将左孩子指针作为前驱指针,将右孩子指针作为后继指针。

6、每个结点的前驱由自己设置,每个结点的后继由下一个结点设置。

具体代码如下:

BSTree.h内容

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #ifndef _BSTREE_H_  
  2. #define _BSTREE_H_  
  3. typedef struct _tagBSTreeNode  
  4. {  
  5.     int m_nVal;  
  6.     _tagBSTreeNode * m_pLeft;  
  7.     _tagBSTreeNode * m_pRight;  
  8. }BSTreeNode;  
  9. extern BSTreeNode * pHead;  
  10. //追加树结点  
  11. int AppendNode(BSTreeNode **, int nNum);  
  12. //打印树结点  
  13. void PrintTree(BSTreeNode ** ppTree);  
  14. //释放树  
  15. void Clear(BSTreeNode ** ppTree);  
  16. //转换为有序双链表  
  17. void InOrderTree(BSTreeNode ** ppTree);  
  18. //销毁链表  
  19. void ClearList(BSTreeNode * pHead);  
  20. //打印链表  
  21. void PrintList(BSTreeNode * pHead);  
  22. //打印路径  
  23. void PrintPath(BSTreeNode * pHead, int nSum);  
  24. #endif  
BSTree.cpp内容

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include <stdlib.h>  
  2. #include <stdio.h>  
  3. #include "BSTree.h"  
[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. //追加树结点  
  2. int AppendNode(BSTreeNode ** ppTree, int nNum)  
  3. {  
  4.  BSTreeNode * pNewNode = NULL;  
  5.  if (!ppTree)  
  6.   return 0;  
  7.  if (*ppTree == NULL)  
  8.  {  
  9.   pNewNode = (BSTreeNode *)malloc(sizeof(BSTreeNode));  
  10.   if (!pNewNode)  
  11.    return 0;  
  12.   pNewNode->m_nVal = nNum;  
  13.   pNewNode->m_pLeft = NULL;  
  14.   pNewNode->m_pRight = NULL;  
  15.   *ppTree = pNewNode;  
  16.   return 1;  
  17.  }  
  18.  if ((*ppTree)->m_nVal > nNum)  
  19.  {  
  20.   AppendNode(&((*ppTree)->m_pLeft), nNum);  
  21.  }  
  22.  else if ((*ppTree)->m_nVal < nNum)  
  23.  {  
  24.   AppendNode(&((*ppTree)->m_pRight), nNum);  
  25.  }  
  26.  else  
  27.  {  
  28.   printf("树结点已经存在.\n");  
  29.   return 0;  
  30.  }  
  31.  return 1;  
  32. }  
  33. //打印树结点  
  34. void PrintTree(BSTreeNode ** ppTree)  
  35. {  
  36.  if (!ppTree)  
  37.   return;  
  38.  if (*ppTree == NULL)  
  39.  {  
  40.   return;  
  41.  }  
  42.  if ((*ppTree)->m_pLeft)  
  43.   PrintTree(&((*ppTree)->m_pLeft));  
  44.  if (*ppTree)  
  45.   printf("%d", (*ppTree)->m_nVal);  
  46.  if ((*ppTree)->m_pRight)  
  47.   PrintTree(&((*ppTree)->m_pRight));  
  48. }  
[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. //释放树  
  2. void Clear(BSTreeNode ** ppTree)  
  3. {  
  4.  BSTreeNode * pLeftTree = NULL;  
  5.  BSTreeNode * pRightTree = NULL;  
  6.  if (!ppTree)  
  7.   return;  
  8.  if (*ppTree == NULL)  
  9.   return;  
  10.  if ((*ppTree)->m_pLeft)  
  11.  {  
  12.   pLeftTree = (*ppTree)->m_pLeft;  
  13.   Clear(&pLeftTree);  
  14.  }  
  15.  if ((*ppTree)->m_pRight)  
  16.  {  
  17.   pRightTree = (*ppTree)->m_pRight;  
  18.   Clear(&pRightTree);  
  19.  }  
  20.  if (*ppTree)  
  21.  {  
  22.   free(*ppTree);  
  23.   *ppTree = NULL;  
  24.  }  
  25.  return;  
  26. }  
[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. //以左孩子为前驱  
  2. //以右孩子为后继  
  3. BSTreeNode * pHead = NULL;  
  4. int nListLen = 0;  
[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. void AppendNode2List(BSTreeNode * pInput)  
  2. {  
  3.  int nTemp = 0;  
  4.  BSTreeNode * pCurNode = NULL;  
  5.  if (pInput == NULL)  
  6.   return;  
  7.  if (!pHead)  
  8.  {  
  9.   pHead = pInput;  
  10.   pInput->m_pLeft = NULL;  
  11.   nListLen++;  
  12.   return;  
  13.  }  
  14.  pCurNode = pHead;  
  15.  while (nTemp < nListLen-1)  
  16.  {  
  17.   pCurNode = pCurNode->m_pRight;  
  18.   nTemp++;  
  19.  }  
  20.  pCurNode->m_pRight = pInput;  
  21.  pInput->m_pLeft = pCurNode;  
  22.  nListLen++;  
  23.  return ;  
  24. }  
[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. //打印树结点  
  2. void InOrderTree(BSTreeNode ** ppTree)  
  3. {  
  4.  if (!ppTree)  
  5.   return;  
  6.  if (*ppTree == NULL)  
  7.  {  
  8.   return;  
  9.  }  
  10.  if ((*ppTree)->m_pLeft)  
  11.   InOrderTree(&((*ppTree)->m_pLeft));  
  12.  if (*ppTree)  
  13.   AppendNode2List(*ppTree);  
  14.  if ((*ppTree)->m_pRight)  
  15.   InOrderTree(&((*ppTree)->m_pRight));  
  16. }  
[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. void PrintList(BSTreeNode * pHead)  
  2. {  
  3.  BSTreeNode * pCurNode = NULL;  
  4.  if (!pHead)  
  5.   return;  
  6.  pCurNode = pHead;  
  7.  printf("\n链表数据:\n");  
  8.  while (pCurNode)  
  9.  {  
  10.   printf("%d ", pCurNode->m_nVal);  
  11.   pCurNode = pCurNode->m_pRight;  
  12.  }  
  13.  return;  
  14. }  
[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. void ClearList(BSTreeNode * pHead)  
  2. {  
  3.  BSTreeNode * pCurNode = NULL;  
  4.  if (!pHead)  
  5.   return;  
  6.  while (pHead)  
  7.  {  
  8.   pCurNode = pHead->m_pRight;  
  9.   free(pHead);  
  10.   pHead = pCurNode;  
  11.  }  
  12.  return;  
  13. }  
main.cpp内容:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. //把二叉查找树转换为有序的双链表  
  2. //要求不可以创建新结点,只可以改变指针  
  3. //提示:  
  4. //可以将左孩子用于指向前驱结点  
  5. //可以将右孩子用于指向后继结点  
  6. #define _CRTDBG_MAP_ALLOC  
  7. #include <stdlib.h>  
  8. #include <stdio.h>  
  9. #include <crtdbg.h>  
  10. #include "BSTree.h"  
  11.   
  12. void main()  
  13. {  
  14.     BSTreeNode * pTree = NULL;  
  15.     if (AppendNode(&pTree, 5) == NULL)  
  16.     {  
  17.         printf("追加失败.\n");  
  18.         return;  
  19.     }  
  20.     if (AppendNode(&pTree, 4) == NULL)  
  21.     {  
  22.         printf("追加失败.\n");  
  23.         return;  
  24.     }  
  25.     if (AppendNode(&pTree, 3) == NULL)  
  26.     {  
  27.         printf("追加失败.\n");  
  28.         return;  
  29.     }  
  30.     if (AppendNode(&pTree, 2) == NULL)  
  31.     {  
  32.         printf("追加失败.\n");  
  33.         return;  
  34.     }  
  35.     if (AppendNode(&pTree, 1) == NULL)  
  36.     {  
  37.         printf("追加失败.\n");  
  38.         return;  
  39.     }  
  40.     printf("二叉搜索树:\n");  
  41.     PrintTree(&pTree);  
  42.     InOrderTree(&pTree);  
  43.     PrintList(pHead);  
  44.     printf("\n");  
  45.     ClearList(pHead);  
  46.     _CrtDumpMemoryLeaks();  
  47.     system("pause");  
  48.     return;  
  49. }  
运行效果如图1所示:

图1 运行效果

0 0