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

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

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


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值