Para un árbol binario con n nodos:
tiene 2 * n campos de puntero
Correspondiente tiene n-1 ramas de puntero
Hay n + 1 campos de puntero que están vacíos (en las hojas, o no en los nodos del árbol binario completo)
El árbol binario de pistas utiliza n + 1 dominios de cadena vacíos para almacenar la información del predecesor y sucesor del nodo.
La solución es agregar dos campos de bandera: ltag de bandera izquierda y rtag de bandera derecha.
En este momento, la estructura del nodo del árbol binario de pistas es la siguiente:
lchild ltag data rtag rchild
Donde
ltag es 0 se refiere al hijo izquierdo del nodo, cuando es 1, se refiere al predecesor del nodo
Cuando rtag es 0, apunta al hijo derecho del nodo, y cuando es 1, apunta al sucesor del nodo.
La esencia de la pista es cambiar el puntero nulo del árbol binario por una pista del predecesor o sucesor. Este proceso se obtiene al atravesar el árbol binario
——————————————————————————————————————
// pre es siempre el nodo en el proceso El anterior uno del árbol (el orden es de acuerdo con el recorrido)
// Dado que el pre está en el frente y el árbol está en la parte de atrás,
primero haga que el hijo izquierdo del árbol apunte al pre nodo
// y luego haga el hijo derecho del punto pre al nodo del árbol
// atravesar El árbol sigue cambiando durante el proceso, y el pre también está cambiando
// No entendí cómo generar una lista doblemente enlazada al principio
可以这样思考 我们输入时是以二叉树的顺序输入
然后遍历时有着不一样的顺序
这个时候已经可以根据不一样的遍历方式根据A点找到其他点(而非拘泥于输入时候的顺序)
那么这些点又重新建立了关系
但这些关系是单向的
加上线索的原因就是使这些新的关系变为双向的
从而变为了双向链表!!!
比如这里输入的顺序是A B C D E F G
这也是前序遍历的顺序
但中序遍历可以得到B D C E A F G这样的顺序
同理 后序遍历也是如此
El predecesor y el sucesor de un nodo pueden ser diferentes con diferentes reglas de recorrido;
el árbol binario de pistas correspondientes a preorden, orden medio y postorden se llama árbol binario pre-cue, árbol binario de cue de orden medio y árbol binario de cue subsiguiente.
//pre始终在过程中的结点tree的前一个(顺序是按照遍历的来)
//既然pre在前 tree在后
//那么先使tree的左孩子指向pre结点
//再使得pre的右孩子指向tree结点
//在遍历的过程中tree一直变化, pre也在变化
//刚开始没有理解双向链表如何生成 看图可以推一下
#include<iostream>
using namespace std;
typedef int Status;
typedef char elementype;
typedef enum {
Link,thread}Pointertag;//枚举类型 第一个不声明的话就为1,后面依次增加
typedef struct TBree
{
elementype data;
struct TBree *lchild, *rchild;
Pointertag ltag, rtag;
}*TB_NODE,BNODE;
//中序线索二叉树
Status InitThread_mid(TB_NODE &tree,TB_NODE &pre)
{
if (tree == NULL)
{
return 0;
}
else
{
InitThread_mid(tree->lchild,pre);
if (!tree->lchild)//如果某元素的左孩子不存在的话,则使pre为其它的前驱 使得遍历顺序直接能用指针找到
{
tree->ltag = thread;
tree->lchild = pre;
}
if (pre->rchild == NULL)//如果前驱元素的右孩子不存在的话,使其右孩子指向下一个 即建立后继
{
pre->rtag = thread;
pre->rchild = tree;
}
pre = tree;//保持pre为 前面的元素
//这里原为中序遍历的输出
InitThread_mid(tree->rchild,pre);
}
return 0;
}
//前序线索二叉树
Status InitThread_before(TB_NODE &tree, TB_NODE &pre)
{
if (tree == NULL)
{
return 0;
}
else
{
if (tree->lchild == NULL)//建立该结点的前驱
{
tree->ltag = thread;
tree->lchild = pre;
}
if (pre->rchild == NULL)//建立前驱的后继
{
pre->rtag = thread;
pre->rchild = tree;
}
pre = tree;
InitThread_before(tree->lchild, pre);
InitThread_before(tree->rchild,pre);
}
return 0;
}
//后续线索二叉树
Status Initthread_after(TB_NODE &tree, TB_NODE &pre)
{
if(tree == NULL)
{
return 0;
}
else
{
Initthread_after(tree->lchild, pre);
Initthread_after(tree->rchild,pre);
if (tree->lchild == NULL)
{
tree->ltag = thread;
tree->lchild = pre;
}
if (pre->rchild == NULL)
{
pre->rtag = thread;
pre->rchild = tree;
}
pre = tree;
}
}
//当有了线索之后,二叉树可以被认为是一个双向链表