zoukankan      html  css  js  c++  java
  • 将二叉查找树转换成有序双向链表

    一、问题描述

    输入一棵二叉搜索树,现在要将该二叉搜索树转换成一个排序的双向链表。而且在转换的过程中,不能创建任何新的结点,只能调整树中的结点指针的指向来实现。

     

    二、实现思路

    在二叉搜索树中,每个结点都有两个分别指向其左、右子树的指针,左子树结点的值总是小于父结点的值,右子树结点的值总是大于父结点的值。而在双向链表中,每个结点也有两个指针,它们分别指向前一个结点和后一个结点。所以这两种数据结构的结点是一致,二叉搜索树之所以为二叉搜索树,双向链表之所以为双向链表,只是因为两个指针的指向不同而已,通过改变其指针的指向来实现是完全可能的。

     

    例如如下的二叉搜索树,

     

     

    若采用中序遍历,其遍历顺序为1-2-3-4-5-6-7,通过适当的指针变换操作,可变成的双向有序链表如下:

     

    从上图,我们可以看出,为了减少指针的变换次数,并让操作更加简单,在转换成排序双向链表时,原先指向左子结点的指针调整为链表中指向前一个结点的指针,原先指向右子结点的指针调整为链表中指向下一个结点的指针。例如对于上面的值为2的指点,调整后,它的前一个结点为1,后一个结点为3,而结点2的左子结点本来就为1,右子结点本来就为3.

    对于树的操作,通常是在遍历树的各个结点的过程中,通过对结点实施某些操作来完成的,这个算法也不例外。由于要求转换后的双向链表也是有序的,而我们从上面也可以看到,当我们以中序遍历二叉搜索树时,其遍历的结点就是有序的,所以在这里我位采用的遍历顺序应该是中序。 

    那么我们应该如何调整指针,让二叉搜索树变成一个双向有序链表呢?当遍历到根结点时,我们可以把树看成三个部分:根结点,根的左子树和根的右子树。如上图的二叉排序树,就分成了根结点4、以结点2为根的左子对和以结点6为根的右子树。从变换的链表中我们可以看到,应当把结点4的left指针指向结点3,把结点3的right指针指向结点4,而由于我们采用的是中序遍历,所以当我们遍历到结点4时,结点4的左子树已经转化为一个有序的双向链表,而结点3是这个已经转化的双向链表的尾结点,所以我们应该用一个变量last_node来保存最后一个结点的指针,以便在与根结点连续时使用。然后把这个变量last_node的值更新为指向根结点4。对于结点4的右子树,采取相似的操作。至于具体的实现,我们只需要对所有的子树递归地执行上述操作即可。其操作过程如下:

     

     1 struct BinaryTreeNode  
     2 {  
     3     int m_nVlaue;  
     4     BinaryTreeNode* m_pLeft;  
     5     BinaryTreeNode* m_pRight;  
     6 };  
     7   
     8 /* 
     9     递归遍历中的转换过程 
    10     参数:处理当前结点,当前链表的最后一个结点(初始值为空) 
    11     */  
    12 void ConvertNode(BinaryTreeNode* pNode, BinaryTreeNode** pLastNodeInList)  
    13 {  
    14     if(pNode == NULL)  
    15         return;  
    16     BinaryTreeNode* pCurrent = pNode;  
    17     //递归处理左子树  
    18     if (pCurrent->m_pLeft != NULL)  
    19         ConvertNode(pNode->m_pLeft,pLastNodeInList);  
    20     //处理当前结点              
    21     pCurrent->m_pLeft = *pLastNodeInList;    //将当前结点的左指针指向已经转换好的链表的最后一个位置  
    22     if (*pLastNodeInList!=NULL)  
    23         *pLastNodeInList->m_pRight = pCurrent;//将已转换好的链表的最后一个结点的右指针指向当前结点  
    24   
    25     *pLastNodeInList = pCurrent;//更新链表的最后一个结点  
    26     //递归处理当前结点的右子树  
    27     if (pCurrent->m_pRight != NULL)  
    28         ConvertNode(pNode->m_pRight, pLastNodeInList);  
    29 }  
    30   
    31 BinaryTreeNode* Convert(BinaryTreeNode* pRootInTree)  
    32 {  
    33     BinaryTreeNode* pLastNodeInList = NULL;  
    34   
    35     ConvertNode(pRootInTree, &pLastNodeInList);  
    36   
    37     //pLastNodeInList指向双向链表的尾结点,再次遍历找到头结点  
    38     BinaryTreeNode* pHeadOfList = pLastNodeInList;  
    39     while(pHeadOfList != NULL && pHeadOfList->m_pLeft != NULL)  
    40         pHeadOfList = pHeadOfList->m_pLeft;  
    41   
    42     return pHeadOfList;  
    43 } 

     

     

  • 相关阅读:
    ELK7.X中配置x-pack
    ELK报错及解决方案
    ELK + filebeat集群部署
    CentOS7.6中 KVM虚拟机内存、CPU调整
    Linux 设置定时清除buff/cache的脚本
    Nginx中配置https中引用http的问题
    使用Docker搭建Jumpserver堡垒机
    CenterOS7中解决No package mysql-server available.
    Tomcat启动慢的原因及解决方法
    记录 之-- java 的一些小技巧
  • 原文地址:https://www.cnblogs.com/SarahLiu/p/5954726.html
Copyright © 2011-2022 走看看