二叉树的线索化

Posted 勇士后卫头盔哥

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二叉树的线索化相关的知识,希望对你有一定的参考价值。

前言

线索化二叉树就是将二叉树转换为双向链表的过程,也就是从非线性到线性的转化,对于结点的先后访问次序每次都去遍历的话效率太低,所以得引入双向链表来反映某种二叉树的遍历次序,利用结点的right指针指向遍历中的后继结点,利用结点的left指针指向遍历中的前驱结点,那么如何在遍历时记录结点间的访问次序,我们可以使用队列来进行操作,遍历结束后队列记录了访问次序,循环访问队列连接队列中的结点,如下图所示

这里还需要引入二叉树的层次遍历,层次遍历算法的步骤有以下4步
1.将根节点压入队列中
2.访问队头元素指向的二叉树结点
3.队头元素弹出,将队头元素的孩子压入队列中
4.判断队列是否为空

我们需要准备两个队列,tmp队列用来搬运二叉树的结点,queue队列用来保存二叉树层次遍历后的结果,也就是对应图1的的队列,它的具体操作流程如下所示

代码如下

 void LevelOrderTraversal(BTreeNode<T>* node,LinkQueue<BTreeNode<T>*>& queue)

     void LevelOrderTraversal(BTreeNode<T>* node,LinkQueue<BTreeNode<T>*>& queue)
      
          if(node!=NULL)
          
              LinkQueue<BTreeNode<T>*>  tmp;
              tmp.add(node);
              while(tmp.length()>0)
              
                 BTreeNode<T>* n = tmp.front();
                 if(n->l_pointer!=NULL)
                 
                    tmp.add(n->l_pointer);
                 
                 if(n->r_pointer!=NULL)
                 
                    tmp.add(n->r_pointer);
                 
                 tmp.remove();
                 queue.add(n);
            
      
 

线索化设计

BTreeNode<T>* thread(BTTraversal order)

对于线索化设计的接口设计原型如上所示,根据参数order选择线索化的次序(先序,中序,后序,层次),返回值线索化之后指向链表首结点的指针,线索化结束之后对应的二叉树变为空树,流程如下图所示,先创建一个队列来保存遍历后的结果,接着就根据队列里面节点的先后次序进行连接成双向链表,因为结点被重新组织了,所以root需要赋值为NULL,我们还需要实现connect函数

connect函数代码

BTreeNode<T>* connect(LinkQueue<BTreeNode<T>*>& queue)

    BTreeNode<T>* ret = NULL;
    if(queue.length()>0)
    
       ret   = queue.front();
       BTreeNode<T>* slider = queue.front();
       queue.remove();
       slider->l_pointer  = NULL;
       while(queue.length()>0)
       
           slider->r_pointer = queue.front();
           queue.front()->l_pointer = slider;
           slider  = queue.front();
           queue.remove();
       
       slider->r_pointer = NULL;
    
    return ret;


如上图所示,首先将队列的首结点node1赋给slider,然后踢走首结点,把slider的左指针赋值为NULL,这是初始化部分,接着继续将队列的首结点node2赋给slider的右指针,把silder赋给node2的左指针,然后将node2赋给silder,踢走首结点node2,循环结束后,队列里面的元素就会转化一个循环双链表,返回该链表的首结点指针ret.
线索化操作代码

BTreeNode<T>* thread(BTTraversal order)

    LinkQueue<BTreeNode<T>*> queue;//用来存放遍历后的结点的队列
    traversal(order,queue);//遍历操作,order决定用什么遍历方式
    BTreeNode<T>* ret = connect(queue);//把队列里面的结点连接成一个双向链表
    this->m_root = NULL;//因为原来的二叉树已经被破坏了,所以需要将原来二叉树的根节点赋值为NULL
    BQueue.clear();//清空层次遍历的树
    return ret;

实验代码

#include <iostream>
#include "Tree.h"
#include "GTree.h"
#include "BTree.h"
#include "Array.h"
using namespace std;
using namespace CGSLib;
int main()

  BTree<int> bt;
  BTreeNode<int>* n = NULL;
  bt.insert(1,NULL);

  n = bt.find(1);
  bt.insert(2,n);
  bt.insert(3,n);


  n = bt.find(2);
  bt.insert(4,n);
  bt.insert(5,n);

  n = bt.find(4);
  bt.insert(8,n);
  bt.insert(9,n);

  n = bt.find(5);
  bt.insert(10,n);

  n=bt.find(3);
  bt.insert(6,n);
  bt.insert(7,n);

  SharedPointer < Aarry<int> > tr = bt.traversal(LevelOrder);
  for(int i =0;i<tr->length();i++)
  
      cout<<(*tr)[i]<<" ";
  
  cout<<endl;
  //cout<<(bt==*clonenode)<<endl;
  BTreeNode<int>* head = bt.thread(LevelOrder);//线索化二叉树,返回双向链表的首结点
  while(head!=NULL)
  
      cout<<head->value<<" ",
      head = head->r_pointer;
  
  return 0;

以上是关于二叉树的线索化的主要内容,如果未能解决你的问题,请参考以下文章

线索二叉树的建立与遍历

线索化二叉树详解

数据结构二叉树

java实现线索化二叉树的前序中序后续的遍历(完整代码)

二叉树的线索化

二叉树的线索化