程序员面试题精选100题(01)-把二元查找树转变成排序的双向链表

程序员面试题精选100题(01)-把二元查找树转变成排序的双向链表

参见博客:

http://zhedahht.blog.163.com/blog/static/254111742007127104759245/

http://www.cnblogs.com/caidaxia/archive/2011/10/14/2212369.html

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

 思路一:当我们到达某一结点准备调整以该结点为根结点的子树时,先调整其左子树将左子树转换成一个排好序的左子链表,再调整其右子树转换右子链表。最近链接左子链表的最右结点(左子树的最大结点)、当前结点和右子链表的最左结点(右子树的最小结点)。从树的根结点开始递归调整所有结点。

  思路二:我们可以中序遍历整棵树。按照这个方式遍历树,比较小的结点先访问。如果我们每访问一个结点,假设之前访问过的结点已经调整成一个排序双向链表,我们再把调整当前结点的指针将其链接到链表的末尾。当所有结点都访问过之后,整棵树也就转换成一个排序双向链表了。

首先我们定义的二元查找树节点的数据结构如下:
struct BSTreeNode
{
int m_nValue; // value of node
BSTreeNode *m_pLeft; // left child of node
BSTreeNode *m_pRight; // right child of node
};

思路一的代码为:

///////////////////////////////////////////////////////////////////////
// Covert a sub binary-search-tree into a sorted double-linked list
// Input: pNode - the head of the sub tree
//        asRight - whether pNode is the right child of its parent
// Output: if asRight is true, return the least node in the sub-tree
//         else return the greatest node in the sub-tree
///////////////////////////////////////////////////////////////////////
BSTreeNode* ConvertNode(BSTreeNode* pNode, bool asRight)
{
      if(!pNode)
            return NULL;

      BSTreeNode *pLeft = NULL;
      BSTreeNode *pRight = NULL;

      // Convert the left sub-tree
      if(pNode->m_pLeft)
            pLeft = ConvertNode(pNode->m_pLeft, false);

      // Connect the greatest node in the left sub-tree to the current node
      if(pLeft)
      {
            pLeft->m_pRight = pNode;
            pNode->m_pLeft = pLeft;
      }

      // Convert the right sub-tree
      if(pNode->m_pRight)
            pRight = ConvertNode(pNode->m_pRight, true);

      // Connect the least node in the right sub-tree to the current node
      if(pRight)
      {
            pNode->m_pRight = pRight;
            pRight->m_pLeft = pNode;
      }

      BSTreeNode *pTemp = pNode;

      // If the current node is the right child of its parent, 
      // return the least node in the tree whose root is the current node
      if(asRight)
      {
            while(pTemp->m_pLeft)
                  pTemp = pTemp->m_pLeft;
      }
      // If the current node is the left child of its parent, 
      // return the greatest node in the tree whose root is the current node
      else
      {
            while(pTemp->m_pRight)
                  pTemp = pTemp->m_pRight;
      }
 
      return pTemp;
}

///////////////////////////////////////////////////////////////////////
// Covert a binary search tree into a sorted double-linked list
// Input: the head of tree
// Output: the head of sorted double-linked list
///////////////////////////////////////////////////////////////////////
BSTreeNode* Convert(BSTreeNode* pHeadOfTree)
{
      // As we want to return the head of the sorted double-linked list,
      // we set the second parameter to be true
      return ConvertNode(pHeadOfTree, true);
}

下面给出思路二的代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
// 1:构造二叉查找树;
// 2:中序遍历二叉查找树,因此结点按从小到大顺序访问,假设之前访问过的结点已经调整为一个双向链表,那么
//       只需要将当前结点连接至双向链表的最后一个结点即可,访问完后,双向链表也就调整完了
#include <iostream>
using  namespace  std;
struct  BSTreeNode
{
     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);
void  inOrderBSTree(BSTreeNode* pBSTree);
void  convertToDoubleList(BSTreeNode* pCurrent);
 
BSTreeNode *pHead=NULL; //指向循环队列头结点
BSTreeNode *pIndex=NULL; //指向前一个结点
 
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);
     inOrderBSTree(pRoot);
     return  0;
}
/************************************************************************/
/* 建立二叉排序树                                                               */
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<< "node repeated" <<endl;
     }
 
}
/************************************************************************/
 
/************************************************************************/
/* 中序遍历二叉树,同时调整结点指针                                                                     */
void  inOrderBSTree(BSTreeNode* pBSTree)
{
 
     if  (NULL==pBSTree)
     {
         return ;
     }
     if  (NULL!=pBSTree->m_pLeft)
     {
         inOrderBSTree(pBSTree->m_pLeft);
     }
 
     //  if (NULL!=pBSTree)
     //  {
     //      cout<<pBSTree->m_nValue;
     //  }
     convertToDoubleList(pBSTree);
 
     if  (NULL!=pBSTree->m_pRight)
     {
         inOrderBSTree(pBSTree->m_pRight);
     }
 
}
/************************************************************************/
 
/************************************************************************/
/* 调整结点指针                                                                   */
void  convertToDoubleList(BSTreeNode* pCurrent)
{
     pCurrent->m_pLeft=pIndex; //使当前结点的左指针指向双向链表中最后一个结点
     if  (NULL==pIndex) //若最后一个元素不存在,此时双向链表尚未建立,因此将当前结点设为双向链表头结点
     {
         pHead=pCurrent;
     }
     else //使双向链表中最后一个结点的右指针指向当前结点
     {
         pIndex->m_pRight=pCurrent;
     }
 
     pIndex=pCurrent; //将当前结点设为双向链表中最后一个结点
 
     cout<<pCurrent->m_nValue<< " " ;
 
}
/******************************************************************

你可能感兴趣的:(程序员面试题精选100题(01)-把二元查找树转变成排序的双向链表)