二叉搜索树与双向链表:最直观的想法是,中序遍历二叉搜索树,并使用一个数组保存中序遍历的结点指针结果,再遍历中序数组将其左右相连,最后返回中序遍历数组的第一个元素即可。

vector<TreeNode*> TreeList; //中序遍历数组
//中序遍历 得到中序遍历数组
void dfs(TreeNode* cur)
{
	if(!cur)
	  return;
	dfs(cur->left);
	TreeList.push_back(cur);
	dfs(cur->right);
}
TreeNode* Convert(TreeNode* pRootOfTree) 
{
    if(!pRootOfTree) //空树
	  return nullptr;
	dfs(pRootOfTree);
	for(int i=0;i<TreeList.size()-1;i++) //遍历中序数组 左右相连
	{
	   TreeList[i]->right=TreeList[i+1];
	   TreeList[i+1]->left=TreeList[i];
	}
	return TreeList[0];
}

优化:上述方法开辟了额外的数组存储空间,那么有没有什么原地操作的方法呢?当然有!使用二叉树双指针即可!其中使用一个指针pre表示前驱结点,使用一个指针cur表示当前结点,仍然使用中序遍历方法,当左子树遍历完成后,即肯定cur->left为空才返回,此时将cur->left设置为前驱节点,同时,如果pre不为空的话,当前节点必定为前驱节点的后继节点,即pre->right=cur,当然,也要更新前驱节点为当前结点,再继续右子树的遍历,最后返回二叉树的最左下即中序遍历的开头结点即可。(其实就是中序遍历,然后在处理中间结点时,其左边指向前驱,如果前驱不为空,那么前驱的后继就指向当前,这样就避免了再遍历一次来完成后继的填充,其与数组类似,只不过是将数组转化为了指针)

TreeNode *pre=nullptr;
//中序遍历 得到中序遍历数组
void dfs(TreeNode* cur)
{
	if(!cur) //叶子结点
	  return;
	dfs(cur->left); //左子树遍历
	cur->left=pre;  //更新前驱
	if(pre) //更新后继
	  pre->right=cur;
	pre=cur; //更新下一次的前驱
	dfs(cur->right);  //右子树遍历
}
TreeNode* Convert(TreeNode* pRootOfTree) 
{
    if(!pRootOfTree) //空树
	  return nullptr;
	dfs(pRootOfTree); //中序遍历
	while(pRootOfTree->left) //找到最左下
	  pRootOfTree=pRootOfTree->left;
	return pRootOfTree; //双向链表头结点
}