二叉搜索树转换为双向链表

这是一道面试题,将 二叉搜索树  ->  排序双向链表, 虽然是一道面试题, 不过也给我们提供了一种思路, 二叉搜索树和双向链表这两种我们常用的数据结构, 他们之间可以进行互相转换吗?  倒也是一个值得玩味的想法。


思路:根据 二叉搜索树 的性质,要转换为 有序双向链表, 则, 中序遍历最适合。  因为中序遍历出来是有序的,由小到大。

二叉搜索树每个节点有两个指针分别指向左右两个孩子, 双向链表每个结点有两个指针分别指向前一个结点和后一个结点。如图:


我们需要将如左图的二叉搜索树 转换为 右下角的 有序双向链表。






我们给出实现代码:

//将二叉搜索树->排序双向链表,不能创建任何新节点,只能调整树中结点指针的指向.

//思路:根据 二叉搜索树 的性质,要转换为 有序双向链表, 则, 中序遍历最适合。  因为中序遍历出来是有序的,由小到大。
//二叉搜索树每个节点有两个指针分别指向左右两个孩子, 双向链表每个结点有两个指针分别指向前一个结点和后一个结点, 如图。


#include <iostream>
#include <windows.h>
using namespace std;


//定义二叉搜索树结点结构
struct BSTNode
{  
    BSTNode* _left;  
    BSTNode* _right;  
    int _data;  

	BSTNode( int data, BSTNode* left = NULL, BSTNode* right = NULL )
		: _data( data )
		, _left( left )
		, _right( right )
	{}
};  


//插入新结点到树中
void Insert( BSTNode*& tree, int data );  

//将二叉搜索树tree转化成双向链表,并返回头结点  
BSTNode* BSTreeToList( BSTNode* tree );

//遍历二叉搜索树tree的各个结点,并进行指针调整  
void ConvertNode( BSTNode* tree, BSTNode*& lastNodeInList );  

//查找二叉搜索树tree的最左结点  
BSTNode* FindLeftmostNode( BSTNode* tree );

//以中序遍历打印二叉搜索树tree  
void PrintBiTree( BSTNode* tree );  

//打印链表  
void PrintList( BSTNode* headOfList );  

   
void Insert( BSTNode*& tree, int data )  
{  
	if ( NULL == tree )
	{
		tree = new BSTNode( data, NULL, NULL );
	}
	else if ( data < tree->_data )
	{
		Insert( tree->_left, data );
	}
	else if ( data > tree->_data )
	{
		Insert( tree->_right, data );
	}
	else
	{
		return;
	}
}  

BSTNode* BSTreeToList( BSTNode* tree )  
{  
    if ( NULL == tree )
	{
        return NULL;  
	}

    //找到最左边的结点,即转换后链表的头结点  
	BSTNode* headOfList = FindLeftmostNode( tree );
    BSTNode* lastNodeInList = NULL;  
    
	//进行转换  
    ConvertNode( tree, lastNodeInList );

    return headOfList; 
}  

BSTNode* FindLeftmostNode( BSTNode* tree )  
{  
	if ( NULL == tree )
	{
		return NULL;
	}

	while ( NULL != tree->_left )
	{
		tree = tree->_left;
	}

	return tree;
}  

void ConvertNode( BSTNode* tree, BSTNode*& lastNodeInList )  
{  
    if ( NULL == tree )
	{
        return;  
	}

    //对tree的左子树进行转换,lastNodeInList是转换后链表中最后一个结点的指针  
	if ( NULL != tree->_left )
	{
        ConvertNode( tree->_left, lastNodeInList );  
	}

    //调整tree的left指针,指向上一个结点  
    tree->_left = lastNodeInList;  

    //调整最后一个结点指针的指向,使它的 right 指向下一个结点(即此时的结点tree)  
    if ( NULL != lastNodeInList )
	{
        lastNodeInList->_right = tree;
	}

    //调整指向最后链表一个结点的指针  
    lastNodeInList = tree;  

    //对tree的右子树进行转换,lastNodeInList是转换后链表最后一个结点的指针  
	if ( NULL != tree->_right )
	{
        ConvertNode( tree->_right, lastNodeInList );  
	}
}

void PrintBSTree( BSTNode* tree )  
{  
	if ( NULL == tree )
	{
		return;
	}

	PrintBSTree( tree->_left );

	cout << tree->_data << " ";

	PrintBSTree( tree->_right );
}  

void PrintList( BSTNode* headOfList )  
{  
	if ( NULL == headOfList )
	{
		return;
	}

	BSTNode* node = headOfList;

	while ( NULL != node )
	{
		cout << node->_data << " ";

		node = node->_right; 
	}

	cout << endl;
}  

int main()  
{  
    BSTNode* tree = NULL;

	int a[] = { 626, 1226, 521, 100, 600, 80, 110 };

    for ( size_t i = 0; i < (sizeof(a) / sizeof( a[0] )); ++i )  
    {  
		Insert( tree, a[i] );
    }

    PrintBSTree(tree);  
	cout << endl;

    //进行转换  
    BSTNode* headOfList = BSTreeToList( tree );  

    PrintList( headOfList );  

	system( "pause" );
    return 0;  
}  


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值