数据结构《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, ...
随机推荐
- Redis与Java - 实践
Redis与Java - 实践 标签 : Java与NoSQL Transaction Redis事务(transaction)是一组命令的集合,同命令一样也是Redis的最小执行单位, Redis保 ...
- 第四周 课堂Scrum站立会议
项目名称:连连看游戏(C#) 小组名称:4Boys 小组成员:武志远.李权.张金生.张政 站立会议内容 昨天完成的: 1.完成了游戏界面 2.做查阅关于技术方面的资料并且发布博客 3.发布项目的进度p ...
- nginx 搭配 lua
据说lua的效率高,公司要求,路过学习下.哎 安装 需要最新版的Nginx,LuaJIT,ngx_devel_kit,ngx_lua等安装文件. 安装Lua或者LuaJIT都是可以的,但是出于效率的考 ...
- servlet 配置
<servlet> <servlet-name>HelloServlet</servlet-name> <servlet-class>com.web.s ...
- Sumblime Text2安装Package Control两种方法+安装插件+注册码
刚开始不认识sumblime的时候,就直接在网上下载了一个最新版的sumblime text3,只是在配合使用go语言时,出现了一些不为自己知道的奇葩问题,于是果断把3卸载了,改成了sumblime ...
- Go运行环境搭建(Mac\Linux)
转载:http://blog.csdn.net/nellson/article/details/51523159 1. 下载安装文件 http://www.golangtc.com/download ...
- 百度上传android包:应用名解析失败!
manifest 里面<application增加android:label="@string/app_name"
- DataGridView的按钮列的点击事件
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e) { ) { DataGr ...
- Rhel7的基本使用
1.修改主机名 [root@localhost ~]# cat /etc/hostname localhost.localdomain[root@localhost ~]# hostnamectl s ...
- Rhel6-集群管理(luci&&ricci)配置文档
理论基础: User → HA → Lb → web → sql → 分布式filesystem ->磁盘I/O 用户 高可用 负载均衡 应用 数据库 mf ...