0.题目
输入一颗二叉搜索树,将这棵树装换为一个排序的双向链表。要求不能创建新的结点,只能调整二叉搜索树中结点的指向。例如:
1.解题思路
- 我们知道二叉搜索树的中序遍历是递增有序的,要想转换为有序的链表,我们可以利用中序遍历的路线装换
- 简化这个问题,如果这颗树只有一个结点,那么这棵树转换为链表就只有一个结点,直接返回就可以了;假设这棵树为下面的样子,左右子树分别只有一个结点。按照前序的路线装换,先去装换左子树,左子树只有一个结点,在把这个结点当做根节点,它的左子树为空,用一个last指针记录链表的最后一个结点,此时last为空,根结点1的left就等于last,然后1为双向链表的第一个结点,last指向1,然后在连接它的右子树,方法是一样的,这其实就是一个子问题。我们可以根据递归的方法去解决:
2.代码实现
void Covert(BSTreeNode* root, BSTreeNode** newlastnode)
{
assert(newlastnode);
//树为空,转换结束
if (root == NULL)
{
return;
}
BSTreeNode* cur = root;
//1.递归装换左子树
if (cur->_left != NULL)
{
Covert(cur->_left, newlastnode);
}
//2.连接根节点(newlastnode是指向左子树转换成双向链表的最后一个结点)
cur->_left = *newlastnode;
if ((*newlastnode) != NULL)
{
(*newlastnode)->_right = cur;
}
*newlastnode = cur;
//3.递归装换右子树
if (cur->_right != NULL)
{
Covert(cur->_right, newlastnode);
}
}
BSTreeNode* CovertTreeToList(BSTreeNode* root)
{
//newlastnode是指向左子树转换成双向链表的最后一个结点
BSTreeNode *NewLastNode = NULL;
Covert(root, &NewLastNode);
//NewLastNode指向链表的尾部,我们要返回链表的起始
BSTreeNode* newheadlist = NewLastNode;
while (newheadlist != NULL&&newheadlist->_left != NULL)
{
newheadlist = newheadlist->_left;
}
return newheadlist;
}
//打印转换成的双向链表(方便测试)
void PrintDoubleList(BSTreeNode* newheadlist)
{
BSTreeNode* cur = newheadlist;
printf("newlist->");
while (cur)
{
printf("%d<->", cur->_data);
cur = cur->_right;
}
printf("over\n");
}