将二叉搜索树转换成一个排序的双向链表
题目:将二叉搜索树转换成一个排序的双向链表。提示:要求不能创建任何新的结点,只能调整树中结点指针的指向,也就是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