二叉线索树

来源:互联网 发布:911色主站新域名 编辑:程序博客网 时间:2024/05/16 08:40

对于普通二叉树, 对于最底部的结点和只有一个孩子的结点, 我们通常将其没有元素的左右指针指向NULL. 对于线索树, 简而言之就是将这些NULL指针再次利用, 对于空闲的左指针, 将其指向该结点的前驱结点, 反之, 对于空闲的右指针, 将其指向该节点的后驱结点, 完成线索后的二叉树看上去是这样的中序二叉线索树
上图是一个中序二叉线索树, 直线是原始的二叉树指针, 曲线则是我们添加的线索.

对于线索二叉树的每个结点, 包含以下五项. 除了常规的三项, 还有ltagrtag, ltag标记左边指针是二叉树指针还是一根线索, 同样rtag标记右指针.

struct Node{    int data;    bool ltag, rtag;//0指向孩子, 1为前后趋线索    Node *left, *right;};

既然名字叫二叉线索树, 问题显然在于线索和构建线索, 假如要实现中序的线索, 在一次中序遍历中就能搞定, 下面看看代码的实现, 不过在众多的树中, 没有发现加个线索能带来多大的优点.

#include <iostream>using namespace std;struct Node{    int data;    bool ltag, rtag;//0指向孩子, 1为前后趋线索    Node *left, *right;};Node *insert(Node *root, int key){    if (root == NULL)    {        root = new Node();        root->data = key;        root->ltag = 1;        root->rtag = 1;        root->left = NULL;        root->right = NULL;    }    else if (key >= root->data)    {        root->right = insert(root->right, key);        root->rtag = 0;    }    else    {        root->left = insert(root->left, key);        root->ltag = 0;    }    return root;}void in_order_traverse(Node *root){    if (root)    {        in_order_traverse(root->left);        cout << "[" << root->ltag << "," <<root->data << "," << root->rtag << "]" << endl;        in_order_traverse(root->right);    }}void in_order_threading(Node *root, Node *pre, Node *next){    cout << "pos:" << root->data << " ";    cout << "pre:";    if (pre == NULL)        cout << "NULL ";    else        cout << pre->data << " ";    cout << "next:";    if (next == NULL)        cout << "NULL " << endl;    else        cout << next->data << " " << endl;    if (root->left)//左子树的后继节点一定是当前作为跟的节点        in_order_threading(root->left, pre, root);    else    {        root->left = pre;        cout << "\t\t\tset:" << root->data << "'s L as:";        if (pre)            cout << pre->data << endl;        else            cout << "NULL" << endl;    }    if (root->right)//右子树的前驱一定是当前作为跟的节点        in_order_threading(root->right, root, next);    else    {        root->right = next;        cout << "\t\t\tset:" << root->data << "'s R as:";        if (next)            cout << next->data << endl;        else            cout << "NULL" << endl;    }}Node *find(Node *root, int key){    if (!root)        return NULL;    if (root->data == key)        return root;    else if (key > root->data)        return find(root->right, key);    else         return find(root->left, key);}int main(int argc, char const *argv[]){    int n = 10;    int num[1000] = {4,5,1,2,7,6,9,8,0,3};    Node *root = NULL;    for (int i = 0; i < n; i++)        root = insert(root, num[i]);    in_order_traverse(root);    cout << endl;    in_order_threading(root, NULL, NULL);    Node *res = find(root, 6);    if (res)    {        cout << res->left->data << endl;        cout << res->data << endl;        cout << res->right->data << endl;    }    return 0;}

看看运行效果, 从下可以清楚的看到递归的执行过程.与上图比较, 一点不差
这里写图片描述
为了输出执行过程, 在线索化函数中加了很多输出的代码, 将其全部都删除后代码可以更加简短

void in_order_threading(Node *root, Node *pre, Node *next){    if (root->left)//左子树的后继节点一定是当前作为跟的节点        in_order_threading(root->left, pre, root);    else        root->left = pre;    if (root->right)//右子树的前驱一定是当前作为跟的节点        in_order_threading(root->right, root, next);    else        root->right = next;}
0 0
原创粉丝点击