线索二叉树 C++
以此二叉树为例进行创建:
前序法创建节点,输入’#'表示为NULL
用前序创建的话需要输入 :ABD##E##C#G##
前序遍历:ABD##E##C#G##
中序遍历:#D#B#E#A#C#G#
后序遍历: ##D##EB###GCA
层序遍历: ABCDEG
在进行线索二叉树线索化的过程中我们并不设置 头结点, 而是**直接设置一个全局变量 指针 Prev **, 表示指向上一个节点的位置 。
思想:
1.首先对创建好的二叉树利用一次中序遍历的过程设置好 lTag 与 rtag 。
在这个过程中 T指针负责设置 T->ltag(前驱), prev指针负责设置 prev->rtag(后继)
2.中序线索二叉树的遍历 ,由于设置了前驱和后继,就可以不使用栈, 直接用迭代法进行中序遍历。
ThreadBiTree.h
#pragma once
#include <iostream>
using namespace std;
#define MAX 30
typedef char ElemType;
typedef struct ThreadBiNode {
ElemType data;
struct ThreadBiNode *lchild, *rchild;
int ltag, rtag;//0表示正常连接孩子, 1表示前缀后缀
ThreadBiNode() :data(-1), lchild(NULL), rchild(NULL), ltag(0), rtag(0) {};//无参的构造函数
ThreadBiNode(ElemType e) :data(e), lchild(NULL), rchild(NULL), ltag(0), rtag(0) {};//有参的构造函数
}ThreadBiNode, *ThreadBiTree;
//创建线索二叉树(前序创建),等到中序遍历时才设置ltag, rtag
ThreadBiTree CreateThreadBiTree(const string& tree, int& i);
//中序遍历
void InTraverse_Settag(ThreadBiTree& T, ThreadBiTree& prev);
//中序遍历测试ltag rtag设置得是否正确
void InTraverse(ThreadBiTree T);
//线索二叉树的遍历 此时因为设置了tag, 所以不再需要借助栈了
void InTraverse_Thread(ThreadBiTree root);
ThreadBiTree.cpp
#include "ThreadBiTree.h"
//创建线索二叉树(前序创建),等到中序遍历时才设置ltag, rtag
ThreadBiTree CreateThreadBiTree(const string& tree, int& i) {
if (tree[i] == '#') {//如果节点'#'则表示这个节点为NULL
return NULL;
}
else {
ThreadBiTree pNew = new ThreadBiNode(tree[i]);
i++;
pNew->lchild = CreateThreadBiTree(tree, i);
i++;
pNew->rchild = CreateThreadBiTree(tree, i);
return pNew;
}
}
/*
设置两个指针(注意这两个指针会改变树的结构) T, prev
T只负责左孩子 (前缀)
prev只负责右孩子 (后缀)
*/
//中序遍历
void InTraverse_Settag(ThreadBiTree& T, ThreadBiTree& prev) {//prev刚开始设置成头结点
if (T == NULL) {
//printf("#");
return;
}
else {
InTraverse_Settag(T->lchild, prev);
if (T->lchild == NULL) {
T->ltag = 1;
T->lchild = prev;
}
if ((prev != NULL) && (prev->rchild == NULL)) {//prev!= NULL 这个条件容易被遗漏
prev->rtag = 1;
prev->rchild = T;
}
prev = T;//注意这一步是关键的步骤,只要能进入递归条件这里,则说明一定会有pre的交替
InTraverse_Settag(T->rchild, prev);
}
}
//中序遍历测试ltag rtag设置得是否正确
void InTraverse(ThreadBiTree T) {
if (T == NULL) {
//printf("#");
return;
}
else {
if (T->ltag == 0)
InTraverse(T->lchild);
printf("ltag = %d, data = %c, rtag = %d\n", T->ltag, T->data, T->rtag);
if (T->rtag == 0)
InTraverse(T->rchild);
}
}
//线索二叉树的遍历 此时因为设置了tag, 所以不再需要借助栈了
void InTraverse_Thread(ThreadBiTree root) {
ThreadBiTree p = root;
while (p) {
//向左
while (p->ltag == 0 && p->lchild) {
p = p->lchild;
}
printf("%c", p->data);//visit
while (p->rtag != 0) {
p = p->rchild;
printf("%c", p->data);//visit
}
p = p->rchild;
}
}
main.cpp
#include "ThreadBiTree.h"
int main() {
const string tree = "ABD##E##C#G##";
int i = 0;
ThreadBiTree root = CreateThreadBiTree(tree, i);
ThreadBiTree prev = new ThreadBiNode();//用于表示前面的节点
//线索二叉树设置通过中序遍历 设置 tag
InTraverse_Settag(root, prev);
//测试 tag是否设置正确
InTraverse(root);
//线索二叉树的遍历 :因为是通过中序遍历的方式设置的tag ,线索二叉树的遍历默认为 中序遍历的结果
//InTraverse_Thread(root);
return 0;
}
从程序的编写角度来看, C++确实要比C方便很多。
来源:CSDN
作者:Worthy_Wang
链接:https://blog.csdn.net/Worthy_Wang/article/details/103523578