您的位置:首页 > 其它

将二叉搜索树转换成一个排序的双向链表

2017-07-29 17:22 447 查看

将二叉搜索树转换成一个排序的双向链表

题目:将二叉搜索树转换成一个排序的双向链表。提示:要求不能创建任何新的结点,只能调整树中结点指针的指向,也就是left当prev,right当next。--中序线索化的变型。 

在二叉搜索树中,每个结点都有两个指向子节点的指针,在双向链表中,每个结点也有两个指针,分别指向前一个结点和后一个结点。在二叉搜索树中,左子节点的值总是小于右子结点的值,右子结点的值总是大于父节点的值。因此,我们在转换为双向链表时,原先指向左子节点的指针调整为链表中指向前一个节点的指针,原先指向右子结点的指针调整为链表中指向后一个结点的指针。
例如:



要求将二叉搜索树转换成一个排序的双向链表,我们可以中序遍历每一个节点。当遍历到根节点时,将树看为3部分:值为4的节点,根节点为2的左子树,根节点为6的右子树,根据排序好的链表可以看出应当把结点4的left指针指向3,把结点3的right指针指向4,结点4的左子树已经转换为一个有序的双向链表,并且结点3是这个已经转化的双向链表的尾结点,我们可以用一个变量lastNode来保存最后一个结点的指针,方便与根节点连续时使用,然后将这个变量的值更新为指向根节点4,对于结点4的右子树采用相同的逻辑。
代码实现:

#include
using namespace std;
template
struct BinaryTreeNode
{
BinaryTreeNode* _left;
BinaryTreeNode* _right;
T _data;

BinaryTreeNode(const T& x)
:_left(NULL)
,_right(NULL)
, _data(x)
{}

};

template
class BinaryTree
{
typedef BinaryTreeNode Node;
public:
BinaryTree()
:_root(NULL)
{}

~BinaryTree()
{
Destroy(_root);
}

void Destroy(Node* root)
{
if (root == NULL)
return;
Destroy(root->_left);
Destroy(root->_right);
delete root;
}

bool Insert(const T& x)        //构成搜索二叉树
{
if (_root == NULL)
{
_root = new Node(x);
return true;
}
Node* parent = NULL;
Node* cur = _root;
while (cur)
{
if (cur->_data > x)
{
parent = cur;
cur = cur->_left;
}
else if (cur->_data < x)
{
parent = cur;
cur = cur->_right;
}
else
{
return false;  //不能有相同的_data;
}
}
if (parent->_data < x)
{
parent->_right = new Node(x);
return true;
}
if (parent->_data > x)
{
parent->_left = new Node(x);
return true;
}
return false;
}

void InOrder()        //中序遍历二叉树
{
_InOrder(_root);
cout << endl;
}

Node* Convert()
{
return _Convert(_root);
}

void ConvertNode(Node* root, Node** lastNode)
{
if (root == NULL)
return ;

if (root->_left)        //找到最左节点,即转换后链表的头结点
ConvertNode(root->_left, lastNode);
root->_left = *lastNode;  //调整root的左指针,指向左子树的最后一个结点
if (*lastNode != NULL)
(*lastNode)->_right = root;//调整左子树所构成链表的最后一个结点指向根节点,将其连接起来
*lastNode = root;              //调整指向最后一个结点的指针
if (root->_right != NULL)      //依次对右子树进行转换,lastNode是转换后链表的最后一个结点的指针
ConvertNode(root->_right, lastNode);
}

void Printf1()
{
Node* cur = _root;
while (cur->_left!=NULL)
{
cur = cur->_left;
}
while (cur)
{
cout << cur->_data << " ";
cur = cur->_right;
}
cout << endl;
}
void Printf2()
{
Node* cur = _root;
while (cur->_right!=NULL)
{
cur = cur->_right;
}
while (cur)
{
cout << cur->_data << " ";
cur = cur->_left;
}
cout << endl;
}

protected:
void _InOrder(Node* root)
{
if (root == NULL)
return;
_InOrder(root->_left);
cout << root->_data << " ";
_InOrder(root->_right);
}

Node* _Convert(Node* rootOfTree)
{
Node* lastNode = NULL;
ConvertNode(rootOfTree, &lastNode);

Node* HeadOfList = lastNode;   //lastNode指向双向链表的尾结点,需要返回头结点
while (HeadOfList != NULL && HeadOfList->_left != NULL)
HeadOfList = HeadOfList->_left;
return HeadOfList;
}

protected:
Node* _root;
};

void Test()
{

int arr[] = { 11, 23, 1, 4, 5, 7, 8, 10, 9 };
size_t size = sizeof(arr) / sizeof(arr[0]);
BinaryTree s;
for (size_t i = 0; i < size; ++i)
{
s.Insert(arr[i]);
}
cout << "搜索二叉树中序遍历:" << " ";
s.InOrder();

BinaryTreeNode* head = s.Convert();
cout << "双向链表从左到右序列:" << "";
s.Printf1();
cout << "双向链表从右到序列:" << "";
s.Printf2();

}empty

测试结果:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐