二叉树的线索化
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;
以上是关于二叉树的线索化的主要内容,如果未能解决你的问题,请参考以下文章