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

本文介绍如何将二叉搜索树转换成一个排序的双向链表,通过中序遍历调整指针指向,无需创建新节点。文章提供详细的转换逻辑及C++代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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

在二叉搜索树中,每个结点都有两个指向子节点的指针,在双向链表中,每个结点也有两个指针,分别指向前一个结点和后一个结点。在二叉搜索树中,左子节点的值总是小于右子结点的值,右子结点的值总是大于父节点的值。因此,我们在转换为双向链表时,原先指向左子节点的指针调整为链表中指向前一个节点的指针,原先指向右子结点的指针调整为链表中指向后一个结点的指针
例如:

要求将二叉搜索树转换成一个排序的双向链表,我们可以中序遍历每一个节点。当遍历到根节点时,将树看为3部分:值为4的节点,根节点为2的左子树,根节点为6的右子树,根据排序好的链表可以看出应当把结点4的left指针指向3,把结点3的right指针指向4,结点4的左子树已经转换为一个有序的双向链表,并且结点3是这个已经转化的双向链表的尾结点,我们可以用一个变量lastNode来保存最后一个结点的指针,方便与根节点连续时使用,然后将这个变量的值更新为指向根节点4,对于结点4的右子树采用相同的逻辑。
代码实现:
#include 
using namespace std;
template 
struct BinaryTreeNode
{
	BinaryTreeNode* _left;
	BinaryTreeNode* _right;
	T _data;

	BinaryTreeNode(const T& x)
		:_left(NULL)
		,_right(NULL)
		, _data(x)
	{}

};


template 
class BinaryTree
{
	typedef BinaryTreeNode Node;
public:
	BinaryTree()
		:_root(NULL)
	{}

	~BinaryTree()
	{
		Destroy(_root);
	}

	void Destroy(Node* root)
	{
		if (root == NULL)
			return;
		Destroy(root->_left);
		Destroy(root->_right);
		delete root;
	}

	bool Insert(const T& x)        //构成搜索二叉树
	{
		if (_root == NULL)
		{
			_root = new Node(x);
			return true;
		}
		Node* parent = NULL;
		Node* cur = _root;
		while (cur)
		{
			if (cur->_data > x)
			{
				parent = cur;
				cur = cur->_left;
			}
			else if (cur->_data < x)
			{
				parent = cur;
				cur = cur->_right;
			}
			else
			{
				return false;  //不能有相同的_data;
			}
		}
		if (parent->_data < x)
		{
			parent->_right = new Node(x);
			return true;
		}
		if (parent->_data > x)
		{
			parent->_left = new Node(x);
			return true;
		}
		return false;
	}

	void InOrder()        //中序遍历二叉树
	{
		_InOrder(_root);
		cout << endl;
	}



	Node* Convert()
	{
		return _Convert(_root);
	}

	void ConvertNode(Node* root, Node** lastNode)    
	{
		if (root == NULL)
			return ;

		if (root->_left)        //找到最左节点,即转换后链表的头结点
			ConvertNode(root->_left, lastNode);
		root->_left = *lastNode;  //调整root的左指针,指向左子树的最后一个结点
		if (*lastNode != NULL)
			(*lastNode)->_right = root;//调整左子树所构成链表的最后一个结点指向根节点,将其连接起来
		*lastNode = root;              //调整指向最后一个结点的指针
		if (root->_right != NULL)      //依次对右子树进行转换,lastNode是转换后链表的最后一个结点的指针
			ConvertNode(root->_right, lastNode);
	}

	void Printf1()
	{
		Node* cur = _root;
		while (cur->_left!=NULL)
		{
			cur = cur->_left;
		}
		while (cur)
		{
			cout << cur->_data << " ";
			cur = cur->_right;
		}
		cout << endl;
	}
	void Printf2()
	{
		Node* cur = _root;
		while (cur->_right!=NULL)
		{
			cur = cur->_right;
		}
		while (cur)
		{
			cout << cur->_data << " ";
			cur = cur->_left;
		}
		cout << endl;
	}

protected:
	void _InOrder(Node* root)
	{
		if (root == NULL)
			return;
		_InOrder(root->_left);
		cout << root->_data << " ";
		_InOrder(root->_right);
	}

	
	Node* _Convert(Node* rootOfTree)
	{
		Node* lastNode = NULL;
		ConvertNode(rootOfTree, &lastNode);

		Node* HeadOfList = lastNode;   //lastNode指向双向链表的尾结点,需要返回头结点
		while (HeadOfList != NULL && HeadOfList->_left != NULL)
			HeadOfList = HeadOfList->_left;
		return HeadOfList;
	}

protected:
	Node* _root;
};

void Test()
{

	int arr[] = { 11, 23, 1, 4, 5, 7, 8, 10, 9 };
	size_t size = sizeof(arr) / sizeof(arr[0]);
	BinaryTree s;
	for (size_t i = 0; i < size; ++i)
	{
		s.Insert(arr[i]);
	}
	cout << "搜索二叉树中序遍历:" << " ";
	s.InOrder();

	BinaryTreeNode* head = s.Convert();
	cout << "双向链表从左到右序列:" << "";
	s.Printf1();
	cout << "双向链表从右到序列:" << "";
	s.Printf2();

}empty
测试结果:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值