1. 由搜索二叉树转换为排序的双向链表
分析
(1)搜索二叉树的左子树小于根节点,右子树大于根节点,奠定了排序的基础,而二叉树既有左子树,又有右子树,使双向成为可能的,也就是说,是有可能实现他们之间的转化的。
(2)为了构造链表的双向,我们可以将原先指向左子树的指针调整为链表结点中的pPre(指向前驱结点的指针),将原先指向右子树的指针调整为链表结点中的pNext(指向后继结点的指针)。
(3)为了保证链表有序,我们可以中序遍历树中的每个结点。当遍历到根节点时,将树看成三部分,根节点,左子树,右子树;根据链表的定义,根节点需要和左子树中的最大节点链接起来,需要和右子树中最小结点连接起来。
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};
class Solution {
public:
TreeNode* Convert(TreeNode* pRootOfTree)
{
TreeNode* pLastNode = NULL;
ConvertNode(pRootOfTree, pLastNode);
TreeNode*pcur = pLastNode;
while (pcur&&pcur->left != NULL) //找到头结点
{
pcur = pcur->left;
}
return pcur;
}
void ConvertNode(TreeNode* pNode, TreeNode*&pLastNode)
{
if (pNode == NULL)
return;
TreeNode* pcur = pNode;
if (pcur->left) //第一次走到最左边的结点停下来
ConvertNode(pcur->left, pLastNode);
pcur->left = pLastNode; //第一个结点的前驱结点第一次指向空
if (pLastNode)
pLastNode->right = pcur; //前驱结点的右指针指向当前结点
pLastNode = pcur;
if (pcur->right)
ConvertNode(pcur->right, pLastNode);
}
};
2. 由排序的双向链表转化为平衡二叉树
分析
(1)由于链表是排序的,我们可以先找到链表的中间结点,让中间结点做二叉树的根节点,比中间结点小的做左子树,比它大的做右子树。
(2)将二叉树的根节点返回去。
struct ListNode
{
int val;
ListNode* next;
ListNode(int x) { val = x; }
};
struct TreeNode
{
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x) { val = x; }
};
class Solution
{
public:
TreeNode* sortedListToBST(ListNode* head)
{
if (NULL == head) return NULL;
if (NULL == head->next)
{
return new TreeNode(head->val);
}
ListNode* slow = head;
ListNode* fast = head->next->next;
while (fast != NULL&& fast->next != NULL)
{
fast = fast->next->next;
slow = slow->next;
}
TreeNode* node = new TreeNode(slow->next->val);
node->right = sortedListToBST(slow->next->next);
slow->next = NULL;
node->left = sortedListToBST(head);
return node;
}
};