数据结构《9》----Threaded Binary Tree 线索二叉树
对于任意一棵节点数为 n 的二叉树,NULL 指针的数目为 n+1 , 线索树就是利用这些 "浪费" 了的指针的数据结构。
Definition:
"A binary tree is threaded by making
all right child pointers that would normally be null point to the inorder successor of the node, and all left child pointers that would normally be null point to the inorder predecessor of the node."
将一棵普通的二叉树中任一节点的 空右孩子指针 指向 中序遍历的后继节点, 空左孩子指针 指向 中序遍历的前继节点。
实际上就是利用那些空指针,使其指向节点中序遍历的后继节点,前继节点。
特点:
1. 能够用常数空间复杂度,来进行二叉树的遍历。
2. 在不显式使用 parent pointer 或 栈 的情况, 也能够找到节点的父亲节点, 虽然比较慢。
假设某一节点 k, 有一个右孩子 r。 那么 r 的 left pointer 要么是一个thread 指向 k, 要么就是一个孩子。如果 r 有一个左孩子,那么这个左孩子的 left pointer 要么是一个thread指向 k, 要么也是一个孩子,如此类推。。所以在r 的“最左”的孩子一定指向 k。
对于k 的 左孩子的情况是类似的,也能够找到父亲节点。
线索二叉树的数据结构:
typedef enum {THREAD, LINK } PointerFlag;
//标记指针是 线索 还是 正常的Link
struct ThTreeNode{
char val;
ThTreeNode *left;
ThTreeNode *right;
PointerFlag l_tag;
PointerFlag r_tag;
ThTreeNode()
:left(NULL), right(NULL), l_tag(LINK), r_tag(LINK){}
};
二叉树的线索化:
利用中序遍历,将叶子节点空指针线索化。
void InThreading(ThTreeNode *root)
{
if(root == NULL) return; InThreading(root->left); //线索化左子树 if(g_pre->right == NULL){ //全局变量g_pre指向中序遍历访问的前一个节点
g_pre->r_tag = THREAD;
g_pre->right = root;
}
if(root->left == NULL){
root->l_tag = THREAD;
root->left = g_pre;
}
g_pre = root; InThreading(root->right); //线索化右子树
}
线索二叉树的遍历:
时间复杂度O(n), 空间复杂度O(1).
void InOrderTraversal(ThTreeNode *head)
{
ThTreeNode *p = head->left; // head指向头节点,头节点的左孩子是 根节点 while(p != head){
while(p->l_tag == LINK) p = p->left;
cout << p->val << " "; while(p->r_tag == THREAD && p->right != head){
p = p->right;
cout << p->val << " ";
} p = p->right;
}
}
完整的代码:
/**
* copyright @ L.J.SHOU Feb.10, 2014
* threaded binary tree
*/
#include "threaded-binary-tree.h"
#include <iostream>
#include <cstring>
#include <cassert>
using std::cout;
using std::cin;
using std::string;
using std::endl; // global variant: previous visited node
ThTreeNode *g_pre(NULL); void InThreading(ThTreeNode *root)
{
if(root == NULL) return; InThreading(root->left); if(g_pre->right == NULL){
g_pre->r_tag = THREAD;
g_pre->right = root;
}
if(root->left == NULL){
root->l_tag = THREAD;
root->left = g_pre;
}
g_pre = root; InThreading(root->right);
} ThTreeNode* InOrderThreading(ThTreeNode *root)
{
ThTreeNode *head(NULL); //头节点
head = new ThTreeNode();
head->l_tag = LINK;
head->r_tag = THREAD;
if(root == NULL) head->left = head;
else{
head->left = root; g_pre = head;
InThreading(root);
g_pre->right = head; g_pre->r_tag = THREAD;
head->right = g_pre; //head->right指向中序遍历最后一个节点
} return head;
} void InOrderTraversal(ThTreeNode *root)
{
ThTreeNode *p = root->left; // p 指向根节点 while(p != root){
while(p->l_tag == LINK) p = p->left;
cout << p->val << " "; while(p->r_tag == THREAD && p->right != root){
p = p->right;
cout << p->val << " ";
} p = p->right;
}
} ThTreeNode* Destroy(ThTreeNode *root)
{
if(root){
if(root->l_tag == LINK)
root->left = Destroy(root->left);
if(root->r_tag == LINK)
root->right = Destroy(root->right);
delete root;
}
return NULL;
}
数据结构《9》----Threaded Binary Tree 线索二叉树的更多相关文章
- 遍历二叉树 traversing binary tree 线索二叉树 threaded binary tree 线索链表 线索化
遍历二叉树 traversing binary tree 线索二叉树 threaded binary tree 线索链表 线索化 1. 二叉树3个基本单元组成:根节点.左子树.右子树 以L.D.R ...
- 笔试算法题(41):线索二叉树(Threaded Binary Tree)
议题:线索二叉树(Threaded Binary Tree) 分析: 为除第一个节点外的每个节点添加一个指向其前驱节点的指针,为除最后一个节点外的每个节点添加一个指向其后续节点的指针,通过这些额外的指 ...
- [LintCode] Invert Binary Tree 翻转二叉树
Given n points on a 2D plane, find the maximum number of points that lie on the same straight line. ...
- 【LeetCode-面试算法经典-Java实现】【104-Maximum Depth of Binary Tree(二叉树的最大深度)】
[104-Maximum Depth of Binary Tree(二叉树的最大深度)] [LeetCode-面试算法经典-Java实现][全部题目文件夹索引] 原题 Given a binary t ...
- 线索二叉树Threaded binary tree
摘要 按照某种遍历方式对二叉树进行遍历,可以把二叉树中所有结点排序为一个线性序列.在该序列中,除第一个结点外每个结点有且仅有一个直接前驱结点:除最后一个结点外每一个结点有且仅有一个直接后继结点.这 ...
- ※数据结构※→☆非线性结构(tree)☆============二叉树 顺序存储结构(tree binary sequence)(十九)
二叉树 在计算机科学中,二叉树是每个结点最多有两个子树的有序树.通常子树的根被称作“左子树”(left subtree)和“右子树”(right subtree).二叉树常被用作二叉查找树和二叉堆或是 ...
- 226. Invert Binary Tree 翻转二叉树
[抄题]: Invert a binary tree. 4 / \ 2 7 / \ / \ 1 3 6 9 to 4 / \ 7 2 / \ / \ 9 6 3 1 [暴力解法]: 时间分析: 空间分 ...
- [LeetCode] Find Leaves of Binary Tree 找二叉树的叶节点
Given a binary tree, find all leaves and then remove those leaves. Then repeat the previous steps un ...
- [LeetCode] Verify Preorder Serialization of a Binary Tree 验证二叉树的先序序列化
One way to serialize a binary tree is to use pre-oder traversal. When we encounter a non-null node, ...
随机推荐
- XPath的语法
XPath 是XML的查询语言,和SQL的角色很类似.以下面XML为例,介绍XPath 的语法. <?xml version="1.0" encoding="ISO ...
- $(document).ready(function (){}) , $(function(){}) , $().ready(function(){}) , jquery(function(){}) , (function($){})(jquery)有什么区别
$(document).ready(function(){...}) , $().ready(function(){...}) , $(function(){...}) , jquery(funct ...
- Echart多图联动
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 3 ...
- 聚类算法:ISODATA算法
1. 与K-均值算法的比较 –K-均值算法通常适合于分类数目已知的聚类,而ISODATA算法则更加灵活: –从算法角度看, ISODATA算法与K-均值算法相似,聚类中心都是通过样本均值的迭代运算来决 ...
- HDU 3466
Proud Merchants Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others) ...
- kafka技术要点
转载:http://blog.csdn.net/caisini_vc/article/details/48007297 Kafka是分布式发布-订阅消息系统.它最初由LinkedIn公司开发,之后成为 ...
- 常用的js函数
function $(){ return document.getElementById(arguments[0])}; /** * 得到上一个元素 * @param {Object} elem */ ...
- 最原始的COM组件调用过程(不使用注册表信息)
最原始的COM组件调用过程(不使用注册表信息) 最近因为项目的关系开始研究COM组件了,以前都认为COM过时了,所以也没怎么接触. 现在好好补补课了. 一般调用COM都是通过注册表找到它的位置, 然后 ...
- tomcat 下虚拟机部署导致应用filter失效的问题
遇到一个困扰我两天的问题 服务器的tomcat上面挂了3个项目 1个项目在D:\tomcat\\webapps\ROOT下 运行正常 1个项目在D:\heyefan下 运行正常 1个项目在D:\MA ...
- 编程思考 PetShop读后感
标准,插拔式的设计思想建立一致的标准是通向“复用”的通道.分层,使其得到的充分的独立.一个东西如果独立了[不是孤立],这个事物就具有很强大的力量,这个和一个人的成长是相同的道理.所以呢,在写程序的过程 ...