大公司面试题之二叉查找树转双向链表

作者:云梦泽

日期:2013.11.13

地点:软件大楼211

心情:复杂

1、题目

输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。要求不能创建任何新的结点,只调整指针的指向。

比如:

      10

   / \
  6  14
 / \ / \
4  8 12 16
    
转换成双向链表为
4=6=8=10=12=14=16

2.基础知识

先来复习一下什么是二叉查找树和双向链表
二叉查找树也叫二叉排序树(Binary Sort Tree)或者是一个空树,空树总是符合任何树的定义。
性质:1.它的左子树不空,则左子树上的所有节点值均小于它的根节点值
     2.它的右子树不空,则右子树上的所有节点值均大于它的根节点值
     3.它的左右子树也分别为二叉排序树
中序遍历二叉排序树可得一个有序序列,一个无序序列可通过构造一颗二叉树而变为有序序列不仅如此,每次插入新节点时都是二叉树上的叶子节点,因而不必移动其它节点,仅需要改变某个节点的指针,由空变为非空。
双向链表,简单来说就是前驱后继都有的链表。

3.思路

1、构建二叉树,递归算法:对于每个数值,先进行树的访问比较,找到合适的位置,开辟空间放置和链接节点,调整指针指向,如下。
void AddBSTreeNode(BSTNode *&pCurrent,int inputValue)
{
	if (pCurrent==nullptr)                               //当前树(子树)根为空,添加树节点
	{
		BSTNode *pTreeNode=new BSTNode();            //开辟空间
		pTreeNode->iValue=inputValue;
		pTreeNode->pLeft=nullptr;
		pTreeNode->pRight=nullptr;
		pCurrent=pTreeNode;                          //开始为根节点,递归调用时设为树的左或右链接
	}
    	else if (pCurrent->iValue>inputValue)                //访问左子树
	{
		AddBSTreeNode(pCurrent->pLeft,inputValue);
	}
	else if(pCurrent->iValue<inputValue)                 //访问右子树
	{
		AddBSTreeNode(pCurrent->pRight,inputValue);
	}
	else                                                 //相等不做处理
	{
		return;
	}
}

2.构造好二叉排序树后对树进行遍历,以一个根节点为基础,遍历左子树到底,然后退出一层递归对当前根节点转换,然后再深入去遍历右子树,由此而完成转换
void TraceBSTree(BSTNode *&pCurrent,DoubleList *&pDoubleListHead,DoubleList *&pListIndex)
{//遍历二叉查找树,将得到的节点添加到双向二叉链表上
	if (pCurrent==nullptr) //为空,返回,在多层递归中,退出当前层继续,有点类似多层循环的味道
	{
		return;
	}
	if (pCurrent->pLeft!=nullptr)              //二叉树有左子树,访问左子树
	{
		TraceBSTree(pCurrent->pLeft,pDoubleListHead,pListIndex);
	}
	ConvertToDoubleList(pCurrent,pDoubleListHead,pListIndex);//没有将当前左节点转换为双向链表节点

	if (pCurrent->pRight!=nullptr)              //接着访问右子树
	{
		TraceBSTree(pCurrent->pRight,pDoubleListHead,pListIndex);
	} 
}
3.转换即对节点调整指针指向
void ConvertToDoubleList(BSTNode *pCurrent,DoubleList *pDoubleListHead,DoubleList *pListIndex)
{
	//对于一个二叉查找树节点转换为链表节点
	pCurrent->pLeft=pListIndex;
	if(pListIndex==nullptr)//左链接为空,此时为头节点
		pDoubleListHead=pCurrent;
	else                   //否则非头结点,右向链接
		pListIndex->pRight=pCurrent;
	pListIndex=pCurrent;   //链表索引指向当前节点
	cout<<pCurrent->iValue<<endl;
}


4.下面给出标准代码:
 

1.头文件

//Author:云梦泽
//DateTime:2013.11.13
//湖南大学软件大楼211
#ifndef FUNCTION_DEFINE_H
#define FUNCTION_DEFINE_H
struct BSTNode
{
	int iValue;
	BSTNode *pLeft;
	BSTNode *pRight;
};
typedef BSTNode BSTree;
typedef BSTNode DoubleList;
void ConvertToDoubleList(BSTNode *pCurrent);
void AddBSTreeNode(const BSTNode *&pCurrent,int inputValue);
void TraceBSTree(BSTNode *&pCurrent,DoubleList *&pDoubleListHead,DoubleList *&pListIndex);
#endif


2.源文件

//Author:云梦泽
//DateTime:2013.11.13
//湖南大学软件大楼211
#include <iostream>
#include "functiondefine.h"
using namespace std;
void AddBSTreeNode(BSTNode *&pCurrent,int inputValue)
{
	if (pCurrent==nullptr)                           //当前树(子树)根为空,添加树节点
	{
		BSTNode *pTreeNode=new BSTNode();            //开辟空间
		pTreeNode->iValue=inputValue;
		pTreeNode->pLeft=nullptr;
		pTreeNode->pRight=nullptr;
		pCurrent=pTreeNode;                          //开始为根节点,递归调用时设为树的左或右链接
	}
	else if (pCurrent->iValue>inputValue)            //访问左子树
	{
		AddBSTreeNode(pCurrent->pLeft,inputValue);
	}
	else if(pCurrent->iValue<inputValue)             //访问右子树
	{
		AddBSTreeNode(pCurrent->pRight,inputValue);
	}
	else                                             //相等不做处理
	{
		return;
	}
}
void ConvertToDoubleList(BSTNode *pCurrent,DoubleList *pDoubleListHead,DoubleList *pListIndex)
{
	//对于一个二叉查找树节点转换为链表节点
	pCurrent->pLeft=pListIndex;
	if(pListIndex==nullptr)//左链接为空,此时为头节点
		pDoubleListHead=pCurrent;
	else                   //否则非头结点,右向链接
		pListIndex->pRight=pCurrent;
	pListIndex=pCurrent;   //链表索引指向当前节点
	cout<<pCurrent->iValue<<endl;
}
void TraceBSTree(BSTNode *&pCurrent,DoubleList *&pDoubleListHead,DoubleList *&pListIndex)
{//遍历二叉查找树,将得到的节点添加到双向二叉链表上
	if (pCurrent==nullptr)                     //二叉树为空,返回
	{
		return;
	}
	if (pCurrent->pLeft!=nullptr)              //二叉树有左子树,访问左子树
	{
		TraceBSTree(pCurrent->pLeft,pDoubleListHead,pListIndex);
	}
	ConvertToDoubleList(pCurrent,pDoubleListHead,pListIndex);//没有将当前左节点转换为双向链表节点

	if (pCurrent->pRight!=nullptr)              //接着访问右子树
	{
		TraceBSTree(pCurrent->pRight,pDoubleListHead,pListIndex);
	} 
}
int main()
{
	BSTree *pBSTreeRoot=nullptr;                           //二叉查找树根节点
	DoubleList *pDoubleListHead=nullptr;                   //双链表头节点
	BSTNode *pListIndex=nullptr;                           //指向链表节点的指针
	int inData=0;
	cout<<"请输入一串数字,并以 / 结束"<<endl;
	while(cin>>inData)                                     //界面交互输入数据
	{
		AddBSTreeNode(pBSTreeRoot,inData);                 //数据添加到二叉查找树
	}
	BSTree *pBSTreeRoo1=pBSTreeRoot;
	TraceBSTree(pBSTreeRoot,pDoubleListHead,pListIndex);
	return 0;
}

 

 

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值