将二叉搜索树转换成一个排序的双向链表

【题目具体】

        将二叉搜索树转换成一个排序的双向链表,要求不能创建任何新的结点,只能调整树中结点指针的指向,也就是left当prev,right当next。

以如下的二叉树为例:

要将此二叉树转化称为如下的双向链表:

将pleft指针当作指向前一个结点的指针,将pright指针当作指向后一个结点的指针。

则步骤可以分以下:

1.先找到最左边的结点0作为头结点phead。

2.递归处理左子树,将它的上一个结点0用prev记录住,找到最左边的结点后。

3.处理当前结点0,将0的pleft指针指向prev,若prev为空,则不用对它进行操作,将prev指向当前结点,当前结点没有右子树,返回到上一层递归。

4.处理当前结点1,将结点1的pleft指针指向prev也就是结点0,此时prev结点不为空,则将prev的pright指针指向当前结点1,将prev指向当前结点。

5.当前结点1有右孩子,再对右子树进行左子树同等操作,1的右孩子2,2的pleft指向prev也就是结点1,此时prev不为空,则将prev的pright指向当前结点2,再更新prev指向当前结点2,然后返回到上一层。

此时结果如下:

6.按照以上的方法一直进行递归实现。

【代码实现】

	/将链表转化为一个双向链表
	Node* ToDb_List()
	{
		return _ToDb_List(_proot);
	}
	void PrintList(Node* phead)
	{
		_PrintList(phead);
	}
	//
private:
	///将链表转为一个双向链表
	Node* _ToDb_List(Node* proot)
	{
		assert(proot);
		Node *pCur = proot;
		///找链表的头结点
		while (pCur->_pLeft)
		{
			pCur = pCur->_pLeft;
		}
		Node * phead = pCur;
		Node* last_node = NULL; //指向上一个结点
		_ConvertNode(proot,last_node);  //调用递归函数
		return phead;
	}
	void _ConvertNode(Node* proot,Node * &last_node) ///递归实现函数
	{
		if (proot == NULL)
			return;
		///处理左子树
		if(proot->_pLeft != NULL)
			_ConvertNode(proot->_pLeft,last_node);
		/调整left指针指向上一个结点
		proot->_pLeft = last_node;
		将上一个结点的右指向当前结点
		if(last_node != NULL)
			last_node->_pRight = proot;
		/更新last的值
		last_node = proot;
		处理右子树
		if(proot->_pRight != NULL)
			_ConvertNode(proot->_pRight,last_node);
	}
	void _PrintList(Node* phead)   ///打印双向链表的函数
	{
		if (!phead)
			return;
		Node* pcur = phead;
		while(pcur)
		{
			cout<<pcur->_key<<"->";
			pcur = pcur ->_pRight;
		}
		cout<<"NULL"<<endl;
	}


测试代码

	BinarySearchTree<int,int> s1;
	s1.Insert(5,0);
	s1.Insert(3,0);
	s1.Insert(1,0);
	s1.Insert(7,0);
	s1.Insert(8,0);
	s1.Insert(2,0);
	s1.Insert(6,0);
	s1.Insert(0,0);
	s1.Insert(9,0);
	BSTNode<int,int>* phead = s1.ToDb_List();
	s1.PrintList(phead);

运行结果:


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值