摘选自《大话数据结构》
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
struct ThreadBinaryTree
{
char data;
struct ThreadBinaryTree* leftChild;
struct ThreadBinaryTree* rightChild;
bool LTag = 0; //左标记位
bool RTag = 0; //右标记位
//标记位是0表示指向左右孩子的指针
//标记位是1表示指向前驱或后继的线索
};
ThreadBinaryTree* creatTree(ThreadBinaryTree* root, string s, int& index)
{
if (s[index] == '#')
return NULL;
else
{
root = new ThreadBinaryTree;
root->data = s[index];
root->leftChild = creatTree(root->leftChild, s, ++index);
root->rightChild = creatTree(root->rightChild, s, ++index);
}
return root;
}
void preTraverse(ThreadBinaryTree* root)
{
if (root == NULL)
return;
cout << root->data << endl;
preTraverse(root->leftChild);
preTraverse(root->rightChild);
}
ThreadBinaryTree* preNode; //设置全局变量,指向刚刚访问过的节点 全局变量默认初始化为NULL
//中序遍历线索化
void InThreading(ThreadBinaryTree* node)
{
if (node)
{
InThreading(node->leftChild);
//前驱节点线索化
if (!node->leftChild) //判断是否有左孩子,没有左孩子则执行
{
node->LTag = 1; //没有孩子标记位置1
node->leftChild = preNode; //左孩子指针指向前驱
}
//后继节点线索化
if (preNode != NULL) //为了避免preNode初始值是NULL而编译出错
{
if (!preNode->rightChild) //如果前驱没有右孩子 执行
{
preNode->RTag = 1;
preNode->rightChild = node; //前驱右孩子指针指向后继(当前节点node)
}
}
preNode = node; //将preNode按照遍历顺序走一步 保持preNode为当前节点的前驱
if (node->rightChild == NULL)
node->RTag = 1;
InThreading(node->rightChild);
}
}
void InOrderTraverse_Thr(ThreadBinaryTree* head)
{
ThreadBinaryTree* tmp;
tmp = head->leftChild;
while (tmp != head)
{
while (tmp->LTag == 0)
tmp = tmp->leftChild;
cout << tmp->data << endl;
while (tmp->RTag == 1 && tmp->rightChild != head)
{
tmp = tmp->rightChild;
cout << tmp->data << endl;
}
tmp = tmp->rightChild;
}
}
#if 0
此段代码等于是一个链表的扫描,所以时间复杂度为O[n] 它冲分利用了空指针域的空间
又保证了创建时的一次遍历就可以终生受用的前驱后继的信息,如果所用的二叉树需要经常
遍历或查找节点时需要某种遍历序列中的前驱和后继,那么采用线索二叉链表的存储结构就
是非常不错的选择
#endif
int _tmain(int argc, _TCHAR* argv[])
{
string s = "ABDH##I##EJ###CF##G##";
ThreadBinaryTree* root = NULL;
int index = 0;
root = creatTree(root, s, index);
InThreading(root); //线索化
//改装
//这样定义的好处就是我们既可以从第一个节点起顺后继进行遍历,也可以最后一个节点起顺前驱进行遍历
ThreadBinaryTree* headNode = new ThreadBinaryTree;
headNode->LTag = 0;
headNode->RTag = 1;
headNode->leftChild = root; //①
headNode->rightChild = root->rightChild->rightChild; //②
root->leftChild->leftChild->leftChild->leftChild = headNode; //③
root->rightChild->rightChild->rightChild = headNode; //④
//根据头指针遍历
InOrderTraverse_Thr(headNode);
return 0;
}
图片: