二叉树的线索化源码:
BinSearchTree.h:
#pragma once
#ifndef __BINSEARCH_H__
#define __BINSEARCH_H__
#include<iostream>
#include<stdio.h>
#include<stack>
#include<queue>
using namespace std;
//搜索二叉树节点
enum BinThread{LINK,THREAD};
template<class T>
struct BinTreeNodeThd
{
BinTreeNodeThd(const T& data)
:_data(data)
, _pLeft(NULL)
, _pRight(NULL)
, _pParent(NULL)
, _pLeftThread(LINK)
, _pRightThread(LINK)
{}
T _data;
BinTreeNodeThd<T>* _pLeft;
BinTreeNodeThd<T>* _pRight;
BinThread _pLeftThread;
BinThread _pRightThread;//标记是否需要线索化
BinTreeNodeThd<T>* _pParent;//父母节点
};
template<class T>
class BinSearchTree
{
typedef BinTreeNodeThd<T> Node;
typedef Node* pNode;
public:
//构造函数
//空搜索二叉树的构造
BinSearchTree()
:_pRoot(NULL)
{}
//带参的搜索二叉树构造函数
BinSearchTree(const T* arr, size_t size, const T& invalid){
size_t index = 0;
pNode parent = NULL;
_CreateNewTree(_pRoot,arr, size, index, invalid,parent);
}
//前序递归遍历
void PreOrder(){
cout << "前序递归遍历" << endl;
_PreOrder(_pRoot);
cout << endl;
}
//前序非递归遍历线索化后的二叉树
void PreOrderNor(){
cout << "前序非递归遍历" << endl;
_PreOrderNor(_pRoot);
cout << endl;
}
//中序递归遍历
void InOrder(){
cout << "中序递归遍历" << endl;
_InOrder(_pRoot);
cout << endl;
}
//中序非递归遍历线索化后的二叉树
void InOrderNor(){
cout << "中序非递归遍历" << endl;
_InOrderNor(_pRoot);
cout << endl;
}
//后序递归遍历
void PostOrder(){
cout << "后序递归遍历" << endl;
_PostOrder(_pRoot);
cout << endl;
}
//后序非递归遍历线索化后的二叉树
void PostOrderNor(){
cout << "后序非递归遍历" << endl;
_PostOrderNor(_pRoot);
cout << endl;
}
//前序线索化二叉树
void PreThread(){
cout << "前序线索化二叉树" << endl;
pNode prev = NULL;
_PreThread(_pRoot, prev);
}
//中序线索化二叉树
void InThread(){
cout << "中序线索化二叉树" << endl;
pNode prev = NULL;
_InThread(_pRoot, prev);
}
//后序线索化二叉树
void PostThread(){
cout << "后序线索化二叉树" << endl;
pNode prev = NULL;
_PostThread(_pRoot, prev);
}
protected:
//创建搜索二叉树
void _CreateNewTree(pNode& pRoot,const T* arr, size_t size, size_t& index, const T& invalid,pNode& parent){
if (index < size && arr[index] != invalid){
pRoot = new Node(arr[index]);
pRoot->_pParent = parent;
_CreateNewTree(pRoot->_pLeft,arr, size, ++index, invalid,pRoot);
_CreateNewTree(pRoot->_pRight,arr, size, ++index, invalid,pRoot);
}
}
//前序递归遍历
void _PreOrder(pNode pRoot){
if (pRoot){
cout << pRoot->_data << " ";
_PreOrder(pRoot->_pLeft);
_PreOrder(pRoot->_pRight);
}
}
//前序非递归遍历线索化后的二叉树
void _PreOrderNor(pNode pRoot){
if (NULL == pRoot)
return;
pNode pCur = pRoot;
while (pCur){
//遍历当前节点
while (LINK == pCur->_pLeftThread){
cout << pCur->_data << " ";
pCur = pCur->_pLeft;
}
cout << pCur->_data << " ";
//不管是当前节点的右子树,或是线索化后指向的下个节点,都可以用此步来进入下一层子循环
pCur = pCur->_pRight;
}
}
//中序递归遍历
void _InOrder(pNode pRoot){
if (pRoot){
_InOrder(pRoot->_pLeft);
cout << pRoot->_data << " ";
_InOrder(pRoot->_pRight);
}
}
//中序非递归遍历线索化后的二叉树
void _InOrderNor(pNode pRoot){
if (NULL == pRoot)
return;
pNode pCur = pRoot;
while (pCur){
//先找到左子树最左边的节点
while (LINK == pCur->_pLeftThread)
pCur = pCur->_pLeft;
//遍历该节点的根节点(该节点一定没有左子树,因为上面的while循环)
cout << pCur->_data << " ";
//遍历该节点的下一节点(线索化后的右指针域)
while (THREAD == pCur->_pRightThread){
pCur = pCur->_pRight;
cout << pCur->_data << " ";
}
//遍历该节点的右子树,进入下一层子循环
pCur = pCur->_pRight;
}
}
//后序递归遍历
void _PostOrder(pNode pRoot){
if (pRoot){
_PostOrder(pRoot->_pLeft);
_PostOrder(pRoot->_pRight);
cout << pRoot->_data << " ";
}
}
//后序非递归遍历线索化后的二叉树
void _PostOrderNor(pNode pRoot){
if (NULL == pRoot)
return;
pNode pCur = pRoot;
pNode prev = NULL;
while (pCur){
//先找到左子树的最左节点
if (pCur && pCur->_pLeft != prev){
//if 防止左边重复走两次
while (LINK == pCur->_pLeftThread)
pCur = pCur->_pLeft;
}
//左为空,右也为空,访问后继节点
while (THREAD == pCur->_pRightThread){
cout << pCur->_data << " ";
prev = pCur;//标记刚刚访问的节点
pCur = pCur->_pRight;
}
//处理根节点
if (pRoot == pCur && (NULL == pRoot->_pRight || prev == pRoot->_pRight)){
cout << pCur->_data << " ";
return;
}
//防止右单支的情况出现
//需要加入父母节点,形成父母孩子节点,可以访问前驱节点
while (pCur && prev == pCur->_pRight/* && pRoot != pCur*/){
cout << pCur->_data << " ";
prev = pCur;
pCur = pCur->_pParent;
}
//遍历右子树,进行下一次子循环
if (pCur && NULL != pCur->_pRight && prev != pCur->_pRight){
if (pCur && LINK == pCur->_pRightThread)
pCur = pCur->_pRight;
}
}
}
//前序线索化二叉树
void _PreThread(pNode& pRoot, pNode& prev){
if (pRoot){
//线索化当前节点
//线索化当前节点的左指针域
if (NULL == pRoot->_pLeft){
pRoot->_pLeft = prev;
pRoot->_pLeftThread = THREAD;
}
//线索化当前节点的右指针域
if (prev && NULL == prev->_pRight){
prev->_pRight = pRoot;
prev->_pRightThread = THREAD;
}
//标记刚刚进行线索化的节点
prev = pRoot;
//线索化左子树
if (LINK == pRoot->_pLeftThread)
_PreThread(pRoot->_pLeft, prev);
//线索化右子树
if (LINK == pRoot->_pRightThread)
_PreThread(pRoot->_pRight, prev);
}
}
//中序线索化二叉树
void _InThread(pNode& pRoot, pNode& prev){
if (pRoot){
//线索化左子树
_InThread(pRoot->_pLeft, prev);
//线索化当前节点
//线索化当前节点的左指针域
if (NULL == pRoot->_pLeft){
pRoot->_pLeft = prev;
pRoot->_pLeftThread = THREAD;
}
//线索化当前节点的右指针域
if (prev && NULL == prev->_pRight){
prev->_pRight = pRoot;
prev->_pRightThread = THREAD;
}
//标记刚刚进行线索化的节点
prev = pRoot;
//线索化右子树
if (LINK == pRoot->_pRightThread)
_InThread(pRoot->_pRight, prev);
}
}
//后序线索化二叉树
void _PostThread(pNode& pRoot, pNode& prev){
if (pRoot){
//线索化左子树
_PostThread(pRoot->_pLeft, prev);
//线索化右子树
_PostThread(pRoot->_pRight, prev);
//线索化当前节点
//线索化当前节点的左指针域
if (NULL == pRoot->_pLeft){
pRoot->_pLeft = prev;
pRoot->_pLeftThread = THREAD;
}
//线索化当前节点的右指针域
if (prev && NULL == prev->_pRight){
prev->_pRight = pRoot;
prev->_pRightThread = THREAD;
}
//标记刚刚进行线索化的节点
prev = pRoot;
}
}
private:
pNode _pRoot;
};
#endif //__BINSEARCH_H__
test.c:
#include"bintree.h"
#include"BinSearchTree.h"
#include<Windows.h>
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
using namespace std;
//测试搜索二叉树
void test1(){
//普通场景
char arr[] = { 'A', 'B', 'D', '#', '#', '#', 'C', 'E', '#', '#', 'F' };
//char arr2[] = { '1', '2', '#', '#', '3' };
BinSearchTree<char> bt(arr, sizeof(arr) / sizeof(arr[0]), '#');
//左子树有可能走两次
char arr1[] = { 'A', 'B', 'D', 'E', '#', '#', 'F', '#', '#', '#', 'C' };
BinSearchTree<char> bt1(arr1, sizeof(arr1) / sizeof(arr1[0]), '#');
//左单支
char arr2[] = { 'A', 'B', 'C', 'D' };
BinSearchTree<char> bt2(arr2, sizeof(arr2) / sizeof(arr2[0]), '#');
//右单支
char arr3[] = { 'A', '#', 'B', '#', 'C', '#', 'D' };
BinSearchTree<char> bt3(arr3, sizeof(arr3) / sizeof(arr3[0]), '#');
//测试后序非递归遍历线索化后的二叉树
cout << "场景:普通场景" << endl;
bt.PostOrder();
bt.PostThread();
bt.PostOrderNor();
cout << endl;
cout << "场景:左子树有可能走两次" << endl;
bt1.PostOrder();
bt1.PostThread();
bt1.PostOrderNor();
cout << endl;
cout << "场景:左单支" << endl;
bt2.PostOrder();
bt2.PostThread();
bt2.PostOrderNor();
cout << endl;
cout << "场景:右单支" << endl;
bt3.PostOrder();
bt3.PostThread();
bt3.PostOrderNor();
cout << endl;
//测试前序递归遍历、前序线索化二叉树、前序非递归遍历
//bt.PreOrder();
//bt.PreThread();
//bt.PreOrderNor();
//测试中序递归遍历、中序线索化二叉树、中序非递归遍历
//bt.InOrder();
//bt.InThread();
//bt.InOrderNor();
}
int main(){
test1();
system("pause");
return 0;
}
测试结果:
前序线索化二叉树:
前序测试结果:
中序线索化二叉树:
中序测试结果:
后续线索化二叉树:
场景一:普通场景
场景二:特殊场景(左子树有可能走两次)
场景三:左单支
场景四:右单支