No.1 把二元查找树转变为排序的双向链表

(本文是对http://blog.csdn.net/v_july_v 提供的微软100题的答案的理解,答案部分来自上述博客)

题目:

输入一颗二元查找树,将该二元查找树转换成一个排序的双向链表。

要求不可以创建任何新的结点,只调整指针的指向。

                    10

                   /      \

                6         14

               /   \         /   \

             4    8    12   16

转换成双向链表:4=6=8=10=12=14=16

首先我们定义的二元查找树节点的数据结构为:

struct BSTreeNode

{

      int  m_nValue;

     BSTreeNode *m_pLeft;

     BSTreeNode *m_pRight;

};


Answer:

先来分析一下需要哪些变量,我们需要得到这个转换后的双链表的头和尾:

BSTreeNode *head,*tail

所以声明函数为:

BSTreeNode * treeToLinkedList(BSTreeNode *root)

{

      BSTreeNode *head,*tail;
}

我们还需要一个功能函数,实现这个递归的转换的过程,设为:void helper(BSTreeNode *head,BSTreeNode *tail,BSTreeNode *root)

那么上面的函数就是:

BSTreeNode * treeToLinkedList(BSTreeNode *root)

{

      BSTreeNode *head,*tail;

      helper(head,tail,root);

      return head;

}


下面需要我们好好思考该怎么写这个递归函数helper():

对于算法小白来说,这道题需要我们花心思去好好思考一下递归结束的条件是什么。

1、首先应该想到的是边界问题,比如这个root本身就是NULL的话,那么他的左右孩子节点也就是NULL;

      则首先判断:

   

void helper(BSTreeNode *head,BSTreeNode *tail,BSTreeNode *root)
{
	if(root == NULL)
	{
		head = NULL;
		tail = NULL;
		return;
	}
     
	//如果root不是NULL,那么就要对它两个儿子结点为根的子树进行递归操作,该递归操作完成的任务是:
    //将head指向左子树中最小的结点,将tail指向右子树中最大的结点,
	//而且需要我们找到左子树中的尾部,即左子树中最大的结点,以及右子树中最小的结点,即右子树              
	//这就需要我们再设两个变量:BSTreeNode *left,*right;分别指向左子树转换成双向链表的尾和右子树转换成双向链表的头
     
	BSTreeNode *left,*right;

    //下一步需要我们完成寻找左子树的尾和右子树的头的工作
    helper(head,left,root->m_pLeft);
    helper(right,tail,root->m_pRight);
	// 处理返回的情况
	if(left == NULL)
	{
		head = root;  
	}
	else
	{
		left->m_pRight =  root;
		root->m_pLeft  = left;
	}

	if(right ==  NULL)
	{
		tail = root;
	}
	else
	{
		right->m_pLeft = root;
		root->m_pRight = left;
	}
}

当处理过程在递归函数的调用之后,那么该递归过程一定会首先递归到该二叉树的末尾,即叶子结点,实际上是先对叶子结点进行了处理,然后再一级一级的向父结点进行同样的处理,这类似于二叉树的后序遍历,最后处理父结点;


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值