数据结构《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, ...
随机推荐
- php_curl.dll libssh2.dll 始终无法加载的原因 及解决办法
在StackOverflow得到最终原因及解决办法 http://stackoverflow.com/questions/16424117/php-unable-to-load-php-curl-dl ...
- cookie、sessionStorage、localStorage区别
相同:不管sessionStorage localStorage 还是 cookie 都是存储用户数据的. 不同: 1.cookie的存储空间小, cookie的数据是会通过http请求带到服务器的( ...
- Unique Paths II [LeetCode]
Follow up for "Unique Paths": Now consider if some obstacles are added to the grids. How m ...
- struts2视频学习笔记 22-23(基于XML配置方式实现对action的所有方法及部分方法进行校验)
课时22 基于XML配置方式实现对action的所有方法进行校验 使用基于XML配置方式实现输入校验时,Action也需要继承ActionSupport,并且提供校验文件,校验文件和action类 ...
- this和super关键字
this关键字: 1.引用成员变量 2.通过this(参数列表)调用类的重载的构造方法 3.返回对象的值:使用return this,来返回某个类的引用. super关键字: 1.super是一个引用 ...
- Axis2 webservice入门--开发环境搭建,概念理解
关于webservice的概念,网上有各种解释,但是不太好懂. 可以这样理解:1.一个webservice就是一个“功能”,只是这个功能是别人写好的,被放在别人的网站上. ...
- Linux CC攻击脚本
CC(ChallengeCollapsar)主要是用来攻击页面的.大家都有这样的经历,就是在访问论坛时,如果这个论坛比较大,访问的人比较多,打开页面的速度会比较慢,访问的人越多,论坛的页面越多,数据库 ...
- drbd
1.DRBD安装 1.1.安装依赖包: [java] view plaincopy yum -y install gcc kernel-devel kernel-headers flex 下载安装dr ...
- Prime Palindromes
题目大意:求出区间[a,b]之间的回文质数. a<=b<=10^8; 解题过程: 1.先打个素数表,新学了个 欧拉筛法,是对普通筛法的改进.普通筛法是每找到一个素数,就把它的所有倍数标记成 ...
- cmd的xcopy命令
C#项目的PostEvent里经常会用到xcopy命令,复制目录时容易出错,如下: xcopy sourceDir targetDir,其中的2个目录最后不能有反斜杠"",而目录类 ...