C++算法之 二叉搜索树转换为双向链表

题目:

输入一颗二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的节点,只能调整树中节点指针的方向:

 

分析:

1:由于要求链表是有序的,可以借助二叉树中序遍历,因为中序遍历算法的特点就是从小到大访问结点。当遍历访问到根结点时,假设根结点的左侧已经处理好,只需将根结点与上次访问的最近结点(左子树中最大值结点)的指针连接好即可。进而更新当前链表的最后一个结点指针。

2:由于中序遍历过程正好是转换成链表的过程,即可采用递归处理

 

代码:

 

// BT.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
#include <math.h>
#include <queue>
using namespace std;

//节点的数据结构
class BTree
{
public:
	int       m_nValue;
	BTree*    m_nLeft;
	BTree*    m_nRight;
public:
	BTree(int value)
	{
		m_nValue = value;
	}
};

//二叉树的插入实现
void Insert(int value, BTree* &root)
{
	if (root == NULL)
	{
		root = new BTree(value);
	}
	else if(value < root->m_nValue)
		Insert(value,root->m_nLeft);
	else if(value > root->m_nValue)
		Insert(value,root->m_nRight);
	else
		;
}

//利用中序遍历把搜索二叉树进行遍历,同时进行转换为双向链表
void ConvertNode(BTree* pRoot,BTree* &pLastNodeInList)
{
	if (pRoot == NULL)
		return;
	BTree* pCurrentNode = pRoot;

	if (pCurrentNode->m_nLeft != NULL)//先遍历左子树
	{
		ConvertNode(pCurrentNode->m_nLeft,pLastNodeInList);
	}
	/*
	处理当前节点与已经遍历链表节点的链接
	*/
	pCurrentNode->m_nLeft = pLastNodeInList;

	if (pLastNodeInList != NULL)//如果pLastNodeInList已经不为空,那么让他的next节点指向当前的节点(right相当于 next)
		pLastNodeInList->m_nRight = pCurrentNode;

	pLastNodeInList = pCurrentNode;//然后再把pLastNodeInList指向当前的节点

	if (pCurrentNode->m_nRight != NULL)//再遍历右子树
	{
		ConvertNode(pCurrentNode->m_nRight,pLastNodeInList);
	}
}
BTree* Convert(BTree* pRoot)
{
	BTree* pLastNodeInList = NULL;//指向双链表的尾巴节点
	ConvertNode(pRoot,pLastNodeInList);

   //转换完毕后,pLastNodeInList指向双向链表的尾巴节点
   //我们需要返回头结点
	BTree* pHeadOfList = pLastNodeInList;
	//头结点先指向尾巴节点,从尾巴节点开始遍历
	while (pHeadOfList!= NULL && pHeadOfList->m_nLeft != NULL)
	{
		pHeadOfList = pHeadOfList->m_nLeft;
	}
	return pHeadOfList;//返回头节点
}

void PrintInPrev(BTree* pRoot)
{
	if(pRoot == NULL)
		return;
	PrintInPrev(pRoot->m_nLeft);
	cout<<pRoot->m_nValue<<" ";
	PrintInPrev(pRoot->m_nRight);
}

void PrintList(BTree* &t)
{
	if(t == NULL)
		return;
	while (t != NULL)
	{
		cout<<t->m_nValue<<" ";
		t = t->m_nRight;
	}
}

int _tmain(int argc, _TCHAR* argv[])
{
	BTree* m_pRoot = new BTree(7);
	Insert(3,m_pRoot);
	Insert(6,m_pRoot);
	Insert(1,m_pRoot);
	Insert(2,m_pRoot);
	Insert(5,m_pRoot);
	Insert(8,m_pRoot);
	Insert(7,m_pRoot);
	Insert(10,m_pRoot);

	PrintInPrev(m_pRoot);
	BTree* p = Convert(m_pRoot);
	cout<<endl<<"链表:"<<endl;
	PrintList(p);

	getchar();
	return 0;
}


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值