面试题27:二叉搜索树与双向链表转换

本文探讨如何将二叉搜索树转换为有序的双向链表,利用二叉搜索树中序遍历的特性,使得链表节点顺序保持从小到大排序。在转换过程中,节点的左指针指向其前一个节点,右指针指向下一个节点。通过中序遍历,当遍历到根节点时,连接左右子树最大节点,形成有序链表。
1.输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表,不能创建任何新的结点。只能调整树中结点指针的指向。

例如: 下面的二叉搜索树和对应的双向链表。



分析:在二叉搜索树中,每个节点都有两个指针,在双向链表中,也有两个指针,在二叉搜索树种,做节点的值总是小于父节点的值,右节点的值总是大于父节点的值。为了使得构造的双向链表有序,原先指向左节点的指针调整为指向前一个节点,原先指向右节点的指针指向链表中的下一个结点。而二叉搜索树的中序遍历出来的序列是从小打到排序的。所以采用中序遍历二叉树。当遍历到根节点的时候,如下图:


当遍历到根节点10 的时候,可以将树看成三个部分,根节点为6的左子树的部分和根节点为14 的右子树,按要求,值为10 的节点将和左子树的最大的一个节点8连接起来,同时还要和右子树值为12 的节点连接起来。


源码:

/**
		* 功能说明:Description
		* 作者:K0713
		* 日期:2016-7-20
**/
#include<iostream>
#include<vector>
using namespace std;
//二叉树结构
struct BinaryTreeNode
{
	int                    m_nValue;
	BinaryTreeNode*        m_pLeft;
	BinaryTreeNode*        m_pRight;
};
//创建结点
BinaryTreeNode* CreateBinaryTreeNode(int value);
//连接结点
void ConnectTreeNodes(BinaryTreeNode* pParent, BinaryTreeNode* pLeft, BinaryTreeNode* pRight);
//打印树结点
void PrintTreeNode(BinaryTreeNode* pNode);
//打印二叉树
void PrintTree(BinaryTreeNode* pRoot);
//销毁二叉树
void DestroyTree(BinaryTreeNode* pRoot);
//树的深度
int TreeDepth(BinaryTreeNode* pRoot);
//-----------------//
//递归转换
void ConvertNode(BinaryTreeNode* pNode, BinaryTreeNode** pLastNodeInList);
//二叉树与双向链表转换,并返回链表头节点
BinaryTreeNode* Convert(BinaryTreeNode* pRootOfTree);
//打印双向链表
void PrintDoubleLinkedList(BinaryTreeNode* pHeadOfList);
//销毁链表
void DestroyList(BinaryTreeNode* pHeadOfList);
int main()
{
	BinaryTreeNode* pNode10 = CreateBinaryTreeNode(10);
	BinaryTreeNode* pNode6 = CreateBinaryTreeNode(6);
	BinaryTreeNode* pNode14 = CreateBinaryTreeNode(14);
	BinaryTreeNode* pNode4 = CreateBinaryTreeNode(4);
	BinaryTreeNode* pNode8 = CreateBinaryTreeNode(8);
	BinaryTreeNode* pNode12 = CreateBinaryTreeNode(12);
	BinaryTreeNode* pNode16 = CreateBinaryTreeNode(16);
	ConnectTreeNodes(pNode10, pNode6, pNode14);
	ConnectTreeNodes(pNode6, pNode4, pNode8);
	ConnectTreeNodes(pNode14, pNode12, pNode16);
	PrintTree(pNode10);
	BinaryTreeNode* pHeadOfList = Convert(pNode10);
	PrintDoubleLinkedList(pHeadOfList);
	DestroyList(pNode4);
	system("PAUSE");
	return 0;
}
//创建树结点
BinaryTreeNode* CreateBinaryTreeNode(int value)
{
	BinaryTreeNode* pNode = new BinaryTreeNode();
	pNode->m_nValue = value;
	pNode->m_pLeft = NULL;
	pNode->m_pRight = NULL;
	return pNode;
}
//连接树结点
void ConnectTreeNodes(BinaryTreeNode* pParent, BinaryTreeNode* pLeft, BinaryTreeNode* pRight)
{
	if (pParent != NULL)
	{
		pParent->m_pLeft = pLeft;
		pParent->m_pRight = pRight;
	}
}
//打印
void PrintTreeNode(BinaryTreeNode* pNode)
{
	if (pNode != NULL)
	{
		cout << "value of this node is: " << pNode->m_nValue << endl;
		if (pNode->m_pLeft != NULL)
			cout << "value of its left child is: " << pNode->m_pLeft->m_nValue << endl;
		else
			cout << "left child is null.\n";
		if (pNode->m_pRight != NULL)
			cout << "value of its right child is:" << pNode->m_pRight->m_nValue << endl;
		else
			cout << "right child is null.\n";
	}
	else
	{
		cout << "this node is null.\n";
	}
	cout << endl;
}
void PrintTree(BinaryTreeNode* pRoot)
{
	PrintTreeNode(pRoot);
	if (pRoot != NULL)
	{
		if (pRoot->m_pLeft != NULL)
			PrintTree(pRoot->m_pLeft);
		if (pRoot->m_pRight != NULL)
			PrintTree(pRoot->m_pRight);
	}
}
//销毁
void DestroyTree(BinaryTreeNode* pRoot)
{
	if (pRoot != NULL)
	{
		BinaryTreeNode* pLeft = pRoot->m_pLeft;
		BinaryTreeNode* pRight = pRoot->m_pRight;
		delete pRoot;
		pRoot = NULL;
		DestroyTree(pLeft);
		DestroyTree(pRight);
	}
}
//树的深度
int TreeDepth(BinaryTreeNode* pRoot)
{
	if (pRoot == NULL)
		return 0;
	int nLeft = TreeDepth(pRoot->m_pLeft);
	int nRight = TreeDepth(pRoot->m_pRight);
	return (nLeft > nRight) ? (nLeft + 1) : (nRight + 1);
}
//二叉树与双向链表的转换
BinaryTreeNode* Convert(BinaryTreeNode* pRootOfTree)
{
	BinaryTreeNode *pLastNodeInList = NULL;
	ConvertNode(pRootOfTree, &pLastNodeInList);
	// pLastNodeInList指向双向链表的尾结点,
	// 我们需要返回头结点
	BinaryTreeNode *pHeadOfList = pLastNodeInList;
	while (pHeadOfList != NULL && pHeadOfList->m_pLeft != NULL)
		pHeadOfList = pHeadOfList->m_pLeft;
	return pHeadOfList;
}
//递归转换
void ConvertNode(BinaryTreeNode* pNode, BinaryTreeNode** pLastNodeInList)
{
	if (pNode == NULL)
		return;
	BinaryTreeNode *pCurrent = pNode;
	if (pCurrent->m_pLeft != NULL)
		ConvertNode(pCurrent->m_pLeft, pLastNodeInList);
	pCurrent->m_pLeft = *pLastNodeInList;
	if (*pLastNodeInList != NULL)
		(*pLastNodeInList)->m_pRight = pCurrent;
	*pLastNodeInList = pCurrent;
	if (pCurrent->m_pRight != NULL)
		ConvertNode(pCurrent->m_pRight, pLastNodeInList);
}
//打印双向链表
void PrintDoubleLinkedList(BinaryTreeNode* pHeadOfList)
{
	BinaryTreeNode* pNode = pHeadOfList;
	printf("The nodes from left to right are:\n");
	while (pNode != NULL)
	{
		printf("%d\t", pNode->m_nValue);
		if (pNode->m_pRight == NULL)
			break;
		pNode = pNode->m_pRight;
	}
	printf("\nThe nodes from right to left are:\n");
	while (pNode != NULL)
	{
		printf("%d\t", pNode->m_nValue);
		if (pNode->m_pLeft == NULL)
			break;
		pNode = pNode->m_pLeft;
	}
	printf("\n");
}
void DestroyList(BinaryTreeNode* pHeadOfList)
{
	BinaryTreeNode* pNode = pHeadOfList;
	while (pNode != NULL)
	{
		BinaryTreeNode* pNext = pNode->m_pRight;
		delete pNode;
		pNode = pNext;
	}
}

结果:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值