1. 题目
输入一棵二叉搜索树,现在要将该二叉搜索树转换成一个排序的双向链表。而且在转换的过程中,不能创建任何新的结点,只能调整树中的结点指针的指向来实现。
二叉树结点的定义如下:
struct BinaryTreeNode
{
intm_nValue;
BinaryTreeNode*m_pLeft;
BinaryTreeNode*m_pRight;
};
如图1-1(a)为一棵二叉搜索树,1-1(b)为对应的双向链表。
图1-1转化示意图
2. 分析
(1) 二叉搜索树中序遍历可得有序的结点序列。图1-1(a)对应的中序序列{4,6,8,10,12,14,16}。
(2) 双向链表中的结点是有序的。如图1-1(b)链表遍历序列为{4,6,8,10,12,14,16}。
由(1)与(2)可得,双向链表求解过程可类比于二叉搜索树的中序遍历操作。中序遍历访问结点时,将该结点插入到双向链表的链尾。因此,递归实现过程中需要两个参数:当前子树的根结点与当前链表的尾指针。在函数调用中需要改变尾指针指向新的子树根结点而并非其指向地址的数据,因此需要使用指针的引用。
3. 测试代码
测试样例:按照先序顺序输入二叉搜索树,当结点没有左孩子时输入-1表示该孩子结点不存在,每数字之间用空格分开。例图1-1(a)的输入方式为:10 64 -1 -1 8 -1 -1 14 12 -1 -1 16 -1 -1。
#include <iostream>
using namespace std;
struct BinaryTreeNode
{
int m_nValue;
BinaryTreeNode* m_pLeft;
BinaryTreeNode* m_pRight;
};
void PrintList(BinaryTreeNode *pRoot)
{
//顺序打印链表
while (pRoot != NULL)
{
cout << pRoot->m_nValue << " ";
pRoot = pRoot->m_pRight;
}
}
void PrintTree(BinaryTreeNode *pRoot)
{
//中序打印二叉树
if (pRoot == NULL)
{
return;
}
if (pRoot->m_pLeft != NULL)
{
PrintTree(pRoot->m_pLeft);
}
cout << pRoot->m_nValue << " ";
if (pRoot->m_pRight != NULL)
{
PrintTree(pRoot->m_pRight);
}
}
void CreatTree(BinaryTreeNode *&pRoot)//必须为指针引用
{
//先序顺序输入一棵搜索树
int newData;
cin >> newData;
if (-1 == newData)
{
pRoot = NULL;
}
else
{
pRoot = new BinaryTreeNode;
pRoot->m_nValue = newData;
CreatTree(pRoot->m_pLeft);
CreatTree(pRoot->m_pRight);
}
}
void Convert(BinaryTreeNode *pRoot, BinaryTreeNode *&pTail)//一定要定义为指针的引用,否则无法改变其指向的地址
{
if (pRoot == NULL)
{
return;
}
//类似于访问左子树
if (pRoot->m_pLeft != NULL)
{
Convert(pRoot->m_pLeft, pTail);
}
//类似于访问当前节点
pRoot->m_pLeft = pTail;
if (pTail != NULL)
{
pTail->m_pRight = pRoot;
}
//若不是引用,函数运行结束,下面赋值无效
pTail = pRoot;
//类似于访问右子树
if (pRoot->m_pRight != NULL)
{
Convert(pRoot->m_pRight, pTail);
}
}
BinaryTreeNode *Convert(BinaryTreeNode *pRoot)
{
BinaryTreeNode *pHead = NULL;
BinaryTreeNode *pTail = NULL;
Convert(pRoot, pTail);
pHead = pTail;
while (pHead != NULL && pHead->m_pLeft != NULL)
{
pHead = pHead->m_pLeft;
}
return pHead;
}
int main()
{
BinaryTreeNode* pRoot = NULL;
BinaryTreeNode* pHead = NULL;
CreatTree(pRoot);
cout << "树的中序遍历:" << endl;
PrintTree(pRoot);
cout << endl;
pHead = Convert(pRoot);
PrintList(pHead);
system("pause");
return 1;
}