A dica e travessia da pré-ordem, ordem do meio e pós-ordem da árvore de pistas binárias

Árvore binária de pistas

Nota: código fonte

  • O conceito de árvore de pista binária A árvore de pista
    binária é baseada na estrutura de árvore binária tradicional, mais sinalizadores para determinar se os filhos esquerdo e direito do nó são LTag, RTag vazios.
    Quando o filho da esquerda está vazio, lchild aponta para o nó predecessor do nó, e quando o filho da direita está vazio, rchild aponta para o nó sucessor do nó. Para aumentar a densidade de armazenamento da lista vinculada. Abaixo, damos a estrutura da árvore de pistas binárias:
	typedef struct BiTNode
	{
    
    
		char data;//数据域
		int LTag = 0;//左标签
		int RTag = 0;//右标签
		struct BiTNode* lchild = nullptr;//指针必须初始化,c11标准
		struct BiTNode* rchild = nullptr;//左右孩子
	}BiTNode, * BiTree;
  • Em comparação com a árvore binária geral, a vantagem da árvore de pistas binárias é a
    lista vinculada binária como estrutura de armazenamento. Ela só pode encontrar as informações dos filhos esquerdo e direito do nó, mas não pode obter as informações do predecessor e do sucessor do nó em qualquer sequência. Essas informações só podem ser percorridas Ele só pode ser obtido no processo dinâmico, e a árvore de pistas binárias pode armazenar as informações do predecessor e do sucessor nesses processos dinâmicos. E porque a árvore binária geral tem n nós, deve haver um (n + 1) domínio de cadeia vazia (fácil de provar). Portanto, esses domínios de cadeia de ar podem ser totalmente utilizados para armazenar o precursor e informações subsequentes e a densidade de armazenamento pode ser aumentada.

  • Criar uma árvore binária
    Criamos uma árvore binária percorrendo primeiro, introduzimos primeiro o nó raiz, depois criamos a subárvore esquerda e, em seguida, criamos a subárvore direita (se os dados do nó forem #, significa uma árvore vazia). código mostrado abaixo:

	void CreateBiTree(BiTree& T,BiTree P)//先序输入 
	{
    
    
		char ch;
		cin >> ch;
		if (ch == '#') T = NULL;
		else
		{
    
    
			T = new BiTNode;//分配空间
			T->data = ch;//根节点赋值
			T->parent = P;
			CreateBiTree(T->lchild,T);//建立左子树
			CreateBiTree(T->rchild,T);//建立右子树
		}
	}
  • Árvore binária encadeada de primeira ordem A encadeamento de primeira ordem é
    realizada na ordem da esquerda para a raiz. O processo específico é:
    primeiro, criamos um BiTree Thrt vazio (por um lado, ele é usado como o nó precursor do primeiro nó e o último nó Nós sucessores. Por outro lado, a árvore binária também pode ser formada em uma lista duplamente vinculada. Ela pode ser percorrida do primeiro nó em sucessão ou do último nó ao predecessor, o que é muito conveniente - ^ - ^ - ), crie um BiTree antes que aponte sempre para o nó recém-visitado.
    Em segundo lugar, primeiro encontramos o nó raiz.Se este nó não tiver um filho esquerdo, apontamos lchild para seu predecessor e atribuímos este nó a pre. Se pre não tem filho certo, apontamos o rchild de pre para o nó atual.
    Finalmente, repita a subárvore esquerda e, em seguida, repita a subárvore direita.
    A árvore que queremos atravessar é a seguinte:

Insira a descrição da imagem aqui
A árvore binária após o encadeamento de pré-encomenda é assim (um pouco feia - ^ - ^ -):
Insira a descrição da imagem aqui
O código está anexado abaixo (pre é uma variável global do tipo BiTree. Se você não quiser a árvore principal do nó, será a primeira mais à esquerda O lchild do nó está vazio e, em seguida, aponta para este nó):

//以结点T为根的子树先序线索化
void PreThreading(BiTree& T)
{
    
    
	if (T)//T非空
	{
    
    
		if (!T->lchild)//左子树为空
		{
    
    
			T->LTag = 1;
			T->lchild = pre;//指向前驱结点
		}
		else
		{
    
    
			T->LTag = 0;
		}
		if (!pre->rchild)
		{
    
    
			pre->RTag = 1;
			pre->rchild = T;//指向后继结点
		}
		else
		{
    
    
			T->RTag = 0;
		}
		pre = T;//pre指向当前节点
		if (T->LTag == 0)//这点很重要,只有结点有左孩子的时候才可以遍历左子树,否则会陷入死循环
		{
    
    
			PreThreading(T->lchild);//遍历左子树
		}
		if (T->RTag == 0)//同上
		{
    
    
			PreThreading(T->rchild);//遍历右子树
		}
	}
}
//以结点T为根的字树先序线索化

//带头节点的二叉树先序线索化
void PreOrderThreading(BiTree& Thrt, BiTree T)
{
    
    
	Thrt = new BiTNode;//头节点
	Thrt->LTag = 0;//左标签为零,表明有左子树
	Thrt->RTag = 1;
	Thrt->rchild = Thrt;//右子树指向自己
	if (!T)//若为空树,右子树指向自己
	{
    
    
		Thrt->lchild = Thrt;
	}
	else
	{
    
    
		Thrt->lchild = T;//左指针指向T
		pre = Thrt;
		PreThreading(T);//进行线索化
		pre->rchild = Thrt;//此时pre为最右面的那个节点,让它的右子树为Thrt
		pre->RTag = 1;
		Thrt->rchild = pre;//Thrt的右子树为pre,形成闭环
	}
}
//带头节点的二叉树先序线索化

Nesse ponto, o encadeamento de pré-encomenda da árvore binária acabou.


  • Árvore binária encadeada de ordem média As etapas da árvore binária encadeada de ordem média são semelhantes à árvore binária de pré-ordem. As etapas específicas são:
    1. Percorra a subárvore esquerda, encontre o nó mais à esquerda, deixe seu filho apontar para pré e apontar pré para o nó atual .
    2. Repita as etapas acima para o nó raiz.
    3. Atravessando a subárvore direita.
    A seguir está um diagrama de uma árvore binária encadeada em ordem (o diagrama ainda é muito feio):
    Insira a descrição da imagem aqui
    O código está anexado abaixo (o código ainda é esse código, mas a ordem foi alterada):
//以结点T为根的子树中序线索化
void InThreading(BiTree &T)
{
    
    
	if (T)//T非空
	{
    
    
		InThreading(T->lchild);//遍历左子树
		if (!T->lchild)//左子树为空
		{
    
    
			T->LTag = 1;
			T->lchild = pre;
		}
		else
		{
    
    
			T->LTag = 0;
		}
		if (!pre->rchild)
		{
    
    
			pre->RTag = 1;
			pre->rchild = T;
		}
		else
		{
    
    
			T->RTag = 0;
		}
		pre = T;
		InThreading(T->rchild);//遍历右子树
	}
}
//以结点T为根的字树中序线索化

//带头节点的二叉树中序线索化
void InOrderThreading(BiTree& Thrt, BiTree T)
{
    
    
	Thrt = new BiTNode;
	Thrt->LTag = 0;
	Thrt->RTag = 1;
	Thrt->rchild = Thrt;
	if (!T)
	{
    
    
		Thrt->lchild = Thrt;
	}
	else
	{
    
    
		Thrt->lchild = T;
		pre = Thrt;
		InThreading(T);
		pre->rchild = Thrt;
		pre->RTag = 1;
		Thrt->rchild = pre;
	}
}
//带头节点的二叉树中序线索化
  • Árvore binária de pista
    pós-ordem A árvore binária de pista pós-ordem é a mesma que a ideia anterior:
    1. Primeiro atravesse a subárvore esquerda, encontre o nó mais à esquerda, se seu lchild estiver vazio, este lchild aponta para pré, se o rchild de pre estiver vazio, então O rchild de pre aponta para o nó atual.
    2. Atravesse a subárvore direita e prossiga com as etapas acima.
    3. Finalmente, execute as operações acima no nó raiz.
    A seguir está um diagrama da árvore binária de dicas pós-pedido (o diagrama ainda é muito feio):
    Insira a descrição da imagem aqui
    Anexe o código:
//以结点T为根的子树后序线索化
void PosThreading(BiTree& T)
{
    
    
	if (T)//T非空
	{
    
    
		PosThreading(T->lchild);//遍历左子树
		PosThreading(T->rchild);//遍历右子树
		if (!T->lchild)//左子树为空
		{
    
    
			T->LTag = 1;
			T->lchild = pre;
		}
		else
		{
    
    
			T->LTag = 0;
		}
		if (!pre->rchild)
		{
    
    
			pre->RTag = 1;
			pre->rchild = T;
		}
		else
		{
    
    
			T->RTag = 0;
		}
		pre = T;
	}
}
//以结点T为根的字树后序线索化

//带头节点的二叉树后序线索化
	void PosOrderThreading(BiTree& Thrt, BiTree T)
	{
    
    
		Thrt = new BiTNode;
		Thrt->LTag = 0;
		Thrt->RTag = 1;
		Thrt->rchild = T;
		if (!T)
		{
    
    
			Thrt->lchild = Thrt;
		}
		else
		{
    
    
			Thrt->lchild = T;
			pre = Thrt; 
			PosThreading(T);
		}
	}
	//带头节点的二叉树后序线索化

Vendo isso, a pista da árvore de pistas binárias acabou, quando nossa história ainda não acabou (a vida não é apenas sobre as pistas que estão diante de nós, mas também a travessia da árvore binária). Vamos falar sobre a travessia da árvore de dicas da árvore binária.

  • Atravessando a árvore de pistas da pré-ordem Ao
    cruzar a árvore de pistas da pré-ordem, primeiro defina uma BiTree p, apontando para a subárvore esquerda do nó principal p, ou seja, p = T-> filho.
    Em seguida, queremos produzir as informações de p. Se o nó tiver uma subárvore à esquerda, então p aponta para a subárvore à esquerda e exibe as informações do nó. Se não houver nenhuma subárvore à esquerda, então p aponta para a subárvore à direita e exibe as informações.
    Finalmente, quando p aponta para T, o laço termina.
    A seguir está um exemplo de passagem de pré-encomenda (a animação não é bem feita):
    Insira a descrição da imagem aqui
    O código está anexado abaixo (é tão simples):
	//遍历先序线索二叉树
	void PreTraverse_Thr(BiTree T)
	{
    
    
		BiTree p = T->lchild;
		while (p != T)
		{
    
    
			cout << p->data;
			if (p->LTag == 0)
			{
    
    
				p = p->lchild;
			}
			else
			{
    
    
				p = p->rchild;
			}
		}
	}
//遍历先序线索二叉树
  • Percorrendo a árvore de pistas de ordem média
    A ideia de percorrer a árvore de pistas de ordem média é seguir a ideia raiz esquerda-direita :
    primeiro, encontre o nó mais à esquerda p e produza o valor do nó.
    Então, se rchild = 1, p = p-> rchild do nó à esquerda, produza o valor do nó e repita.
    Se estiver passando para o nó raiz p, p = p-> rchild. No loop, até que p seja o fim de T.
    A seguir está um exemplo de travessia de ordem intermediária (a animação ainda não está bem feita):
    Insira a descrição da imagem aqui
    anexe o código (ainda tão simples quanto isso):
//遍历中序线索二叉树
void InTraverse_Thr(BiTree T)
{
    
    
	BiTree p = T->lchild;//
	while (p != T)
	{
    
    
		while (p->LTag == 0)
		{
    
    
			p = p->lchild;
		}
		cout << p->data;
		while (p->RTag == 1 && p->rchild != T)
		{
    
    
			p = p->rchild;
			cout << p->data;
		}
		p = p->rchild;
	}
}
//遍历中序线索二叉树
  • Percorrendo a árvore de pistas pós-pedido
    Percorrer a árvore de pistas pós-pedido é um pouco difícil. A estrutura binária original da árvore precisa ser alterada. Precisamos adicionar um nó pai para cada nó para resolver o problema de não ser capaz de acessar o nó pai ao atravessar para a subárvore certa.
    código mostrado abaixo:
	typedef struct BiTNode
	{
    
    
		char data;//数据域
		int LTag = 0;//左标签
		int RTag = 0;//右标签
		struct BiTNode* lchild = nullptr;//指针必须初始化,c11标准
		struct BiTNode* rchild = nullptr;//左右孩子
		struct BiTNode* parent = nullptr;//双亲
	}BiTNode, * BiTree;

Com a estrutura acima, é muito mais simples percorrer a árvore de pistas na ordem subsequente.
1. Em primeiro lugar, devemos encontrar o nó mais à esquerda p primeiro, como o percurso de ordem do meio, e emitir o valor do nó, se p-> rchild == 1; p = p-> rchild, o valor do nó de saída, repetindo, Até p-> lchild == 0 e p-> rchild == 0.
2. Neste momento p é o nó raiz (relativamente falando), precisamos continuar percorrendo pelo nó pai e emitir o valor do nó. Até encontrarmos o nó raiz real p, então p = p-> rchild.
3. Repita as etapas 1 e 2 até que o nó pai de p esteja vazio.
Diagrama de demonstração:
Insira a descrição da imagem aqui
anexe o código (não é simples desta vez):

//后序遍历需要双亲节点
void PosTraverse_Thr(BiTree T)
{
    
    
	BiTree root = T->lchild;//初始节点
	BiTree prev = nullptr;//记录上一个节点
	while (root)
	{
    
    
		if (root->lchild == root->rchild)//如果双亲没有左子树或者右子树
		{
    
    
			root = root->rchild;
		}
		while (root->LTag == 0 && root->lchild != prev)//找到最左边的节点
		{
    
    
			root = root->lchild;
		}
		while (root->RTag == 1)//输出并遍历节点的后继
		{
    
    
			cout << root->data;
			prev = root;//记录上一个节点
			root = root->rchild;
		}
		if (root == T->lchild)//判断是不是根节点
		{
    
    
			cout << root->data;
			return;
		}
		while (root->rchild == prev)//不是根节点,访问当前节点的双亲节点
		{
    
    
			cout << root->data;
			prev = root;
			root = root->parent;
			if (root == nullptr)//遍历到根节点,退出
			{
    
    
				return;
			}
		}
		if (root->RTag == 0)//遍历右子树
		{
    
    
			root = root->rchild;
		}
	}
}
//遍历后序线索二叉树

Acho que você gosta

Origin blog.csdn.net/m0_43456002/article/details/104268875
Recomendado
Clasificación