对于任意一棵节点数为 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 线索二叉树的更多相关文章

  1. 遍历二叉树 traversing binary tree 线索二叉树 threaded binary tree 线索链表 线索化

    遍历二叉树   traversing binary tree 线索二叉树 threaded binary tree 线索链表 线索化 1. 二叉树3个基本单元组成:根节点.左子树.右子树 以L.D.R ...

  2. 笔试算法题(41):线索二叉树(Threaded Binary Tree)

    议题:线索二叉树(Threaded Binary Tree) 分析: 为除第一个节点外的每个节点添加一个指向其前驱节点的指针,为除最后一个节点外的每个节点添加一个指向其后续节点的指针,通过这些额外的指 ...

  3. [LintCode] Invert Binary Tree 翻转二叉树

    Given n points on a 2D plane, find the maximum number of points that lie on the same straight line. ...

  4. 【LeetCode-面试算法经典-Java实现】【104-Maximum Depth of Binary Tree(二叉树的最大深度)】

    [104-Maximum Depth of Binary Tree(二叉树的最大深度)] [LeetCode-面试算法经典-Java实现][全部题目文件夹索引] 原题 Given a binary t ...

  5. 线索二叉树Threaded binary tree

    摘要   按照某种遍历方式对二叉树进行遍历,可以把二叉树中所有结点排序为一个线性序列.在该序列中,除第一个结点外每个结点有且仅有一个直接前驱结点:除最后一个结点外每一个结点有且仅有一个直接后继结点.这 ...

  6. ※数据结构※→☆非线性结构(tree)☆============二叉树 顺序存储结构(tree binary sequence)(十九)

    二叉树 在计算机科学中,二叉树是每个结点最多有两个子树的有序树.通常子树的根被称作“左子树”(left subtree)和“右子树”(right subtree).二叉树常被用作二叉查找树和二叉堆或是 ...

  7. 226. Invert Binary Tree 翻转二叉树

    [抄题]: Invert a binary tree. 4 / \ 2 7 / \ / \ 1 3 6 9 to 4 / \ 7 2 / \ / \ 9 6 3 1 [暴力解法]: 时间分析: 空间分 ...

  8. [LeetCode] Find Leaves of Binary Tree 找二叉树的叶节点

    Given a binary tree, find all leaves and then remove those leaves. Then repeat the previous steps un ...

  9. [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, ...

随机推荐

  1. ubuntu下python3安装类库

    ubuntu是默认安装了python2的,所以直接使用 pip install XXX 是默认安装到python2的,安装到python3 的指令是 pip3 install XXXX 或者 pyth ...

  2. (26)odoo中的序列运用

    * 模块中增加序列    __openerp__.py :    ...     'data': [        'product_data.xml',    ],    ...    ------ ...

  3. PHP + Memcache 实现多服务器session共享

    很多时候一个完整的系统可能运行在多个服务器上,如果这多个服务器之间需要共享session的话,那么php默认的files保存session的方式就无能为力了.这时我们可以考虑使用memcache 来接 ...

  4. jupyter

    Pip install jupyter To run:  jupyter notebook 基本操作 执行当前cell,并自动跳到下一个cell:Shift      Enter 执行当前cell,执 ...

  5. JDE910笔记2--OMW项目建立及简单使用

    1.打开JDE的OBJECT MANAGEMENT WORKBENCH.在工作区中选择ADD,建立项目并选择OMW PROJECT,添加相关信息,如下图所示 其中,ProjectID可以对应不同的数据 ...

  6. [转]Perfmon - Windows 自带系统监测工具

    以下内容转自:http://blog.csdn.net/oscar999/article/details/7918385 ---------------------------分割线--------- ...

  7. Octopus系列之SQLite3常用命令

    导出脚本F:\B2CShop>sqlite3 B2CDB.db .dump > test.sql 导入脚本F:\B2CShop>sqlite3 B2CDB.db < B2C-S ...

  8. FusionCharts ajax 调用方式

    方式一:setJSONUrl function initChart() {                    var myChart = new FusionCharts("Fusion ...

  9. ASP.NET MVC统一异常处理

    前言: 今早看了篇文章:求知成瘾,却无作品 的思考:很有感触,发现原来自己也是这样,对每样东西都抱有很大的兴趣或者希望自己去学,一年后发现原来自己什么都是皮毛什么都不精!最终发现真正的大牛都是在某一个 ...

  10. 闭包 (循环事件获取不到i) 和 各种解决循环获取不到i的解决方法

    for(var i in fav){ (function(){                var p=i;                var obj=$S.getId(fav[i]);     ...