题目:二叉搜索树与双向链表

描述:输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。

注意:

1.要求不能创建任何新的结点,只能调整树中结点指针的指向。当转化完成以后,树中节点的左指针需要指向前驱,树中节点的右指针需要指向后继
2.返回链表中的第一个节点的指针
3.函数返回的TreeNode,有左右指针,其实可以看成一个双向链表的数据结构

4.你不用输出或者处理,示例中输出里面的英文,比如"From left to right are:"这样的,程序会根据你的返回值自动打印输出

示例:

输入: {10,6,14,4,8,12,16}

输出:From left to right are:4,6,8,10,12,14,16;From right to left are:16,14,12,10,8,6,4;

题目解析: 系统自动输入一颗二叉树,输出的时候将双向链表从左往右输出和从右往左输出,在输出过程中要确保答案的正确性。

题目分析:在分析题目的同时首先得知道二叉搜索树的基本概念是什么,二叉搜索树:又称为二叉查找树、二叉排序树,它本身可以为一颗空树,或者是具有以下基本性质,当它的左子树不空,则左子树上的所有节点的值均小于它的根节点的值,若它的右子树不空,则右子树上的所有节点的值均大于它根节点的值,同时它根节点的左右子树也分别满足二叉搜索树的特性。经过分析,上述示例的二叉搜索树为下图:

解题思路:对于二叉搜索树来说,中序遍历输出的数值为升序排列。所以我们需要通过中序遍历去解决问题,因为输出的链表是从左往右输出,从左往右依次增大,我们按照正常思路来思考问题,就是将根节点的左(前)指向根节点左子树的最大值,将根节点的右(后)指向根节点右子树的最小值,若左子树或者右子树只有两层的话,直接将左子树或者右子树按照中序遍历输出即可。

采用递归操作解决问题,递归操作的条件为,当二叉树遍历遇到子节点为不存在的情况时就不会继续往下遍历,即终止本轮递归。总体思想是借用中序遍历,实现递归。

具体C++代码如下所示:


/*
struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};*/
class Solution {
    TreeNode* preNode = nullptr;
public:
    TreeNode* Convert(TreeNode* pRootOfTree) {
        if(pRootOfTree == nullptr)
            return nullptr;
        Convert(pRootOfTree->right);//找到最右边的节点
        if(preNode != nullptr){
            pRootOfTree->right = preNode;
            preNode->left = pRootOfTree;
        }
        preNode = pRootOfTree;
        Convert(pRootOfTree->left);
        return preNode;
    }
};

按照代码要求,首先执行的是最后一层的右结点,将右节点与右节点根结点之间构建连接,然后按照递归思想,一直循环执行即可完成目标输出。


另一种解法:在二叉树中,每个结点都有两个指向子结点的指针,双向链表中也存在,在搜索二叉树中左结点的值总是小于父结点的值,右结点的值总是大于父结点的值。在转换成排序双向链表时,原先指向左结点的指针调整为链表中指向前一个结点的指针,原先指向右结点的指针调整为链表中指向后一个结点的指针。

C++代码如下所示:


/*
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* pNode = NULL;
        List(pRootOfTree,&pNode);
        TreeNode* pHead = pNode;
        while (pHead != NULL && pHead->left != NULL)
            pHead = pHead->left;
        return pHead;
    }
    void List(TreeNode* Root,TreeNode**pr){
        if (Root == NULL)
            return ;
        TreeNode* pc = Root;
        if(pc->left != NULL)//递归左子树
            List(pc->left,pr);
        pc->left = *pr;
        if(*pr != NULL)
            (*pr)->right = pc;
        *pr = pc;
        if(pc->right != NULL)
            List(pc->right,pr);
        }
};