Árvores e árvores binárias (incluindo implementação de caso de passagem de pré-pedido e pós-pedido)

A definição da estrutura do nó da representação pai da árvore

Vantagens : É fácil encontrar seu nó pai de acordo com o ponteiro pai do nó, e a complexidade de tempo é o (1)

#include <stdio.h>
#include <stdlib.h>
#define MAX_TREE_SIZE 100
typedef int TElemType; //树结点的数据类型,目前暂定为整型
typedef struct PTNode //结点结构
{
    
    
    TElemType data; //结点数据
    int parent; //双亲位置
} PTNode;
typedef struct  //树结构
{
    
    
    PTNode nodes[MAX_TREE_SIZE]; //结点数组
    int r,n; //根的位置和结点数
} PTree;

A definição da estrutura do nó da representação filha da árvore

Existem nós raiz de várias subárvores na árvore. Considere o uso de várias listas vinculadas, ou seja, cada nó tem vários campos de ponteiro e cada ponteiro aponta para o nó raiz de uma subárvore. Isso é chamado de
esquema de representação de lista múltipla 1: O número de campos de ponteiro é igual ao grau da árvore.
Desvantagem: Quando o grau de cada nó na árvore difere muito, é obviamente uma perda de tempo, porque os campos de ponteiro de muitos nós estão vazios, mas se os nós de a árvore A pequena diferença no grau do ponto significa que o espaço é totalmente utilizado
Solução 2: Alocar espaço sob demanda, o número de campos de ponteiro de cada nó é igual ao grau do nó, e um local é especialmente selecionado para armazenar o número de campos de ponteiro de nó. número de
vantagens: supera as desvantagens de espaço desperdiçado; desvantagens: como cada estrutura de nó de lista vinculada não é a mesma, junto com o valor a ser mantido em graus de nó, a perda de tempo trará notação computacionalmente
infantil

  • Organize os nós de cada filho e use a lista vinculada individualmente como o espaço de armazenamento. Então, há n listas vinculadas filho para n nós. Se for um nó folha, a lista vinculada individualmente está vazia e, em seguida, n ponteiros principais formam um linear lista. Estrutura de armazenamento sequencial, colocada em uma matriz unidimensional
  • O nó filho da lista vinculada filha (armazena o subscrito de um nó na matriz de cabeçalho; o campo de ponteiro é usado para armazenar o ponteiro para o próximo nó filho de um nó), o nó de cabeçalho da matriz de cabeçalho (campo de dados, o campo do ponteiro principal armazena o ponteiro principal da lista vinculada filha do nó)
  • Vantagens: Para encontrar os filhos / irmãos de um nó, você só precisa encontrar a lista unida individualmente de filhos desse nó, o que é mais conveniente
  • Desvantagens: Você precisa percorrer toda a árvore para alcançar o pai do nó. Você pode adicionar o ponteiro pai do nó na estrutura do cabeçalho * /
//树的孩子表示法结构定义
#define MAX_TREE_SIZE 100
typedef struct CTNode // 孩子结点
{
    
    
    int child;
    struct CTNode *next;
}*ChildPtr;
typedef struct  //表头结构
{
    
    
    TElemType data;
    ChildPtr firstchild;
}CTBox;
typedef struct  //树结构
{
    
    
    CTBox nodes[MAX_TREE_SIZE]; //结点数组
    int r,n;  //根的位置和结点数
}CTree;

Notação de irmão filho

  • Princípio: Para qualquer árvore, o primeiro filho de um nó é único, se existir, e o irmão certo também é único. Dois ponteiros podem ser definidos para apontar para o primeiro filho do nó e o irmão direito do nó.
  • Vantagens: fácil encontrar um filho de um nó, só precisa encontrar o filho mais velho do nó por meio do primeiro filho e, em seguida, encontrar o segundo irmão por meio do rightsib do nó filho mais velho
  • Desvantagens: Não é fácil encontrar os pais do nó, mas o problema de encontrar os pais rapidamente pode ser resolvido adicionando um campo de ponteiro pai
typedef struct CSNode
{
    
    
    TElemType data;
    struct CSNode *firstchild, *rightsib;
}CSNode,*CSTree;

Árvore binária

1. Estrutura de armazenamento sequencial: Use uma matriz unidimensional para armazenar os nós da árvore binária, e o local de armazenamento do nó, ou seja, o subscrito da matriz, deve refletir a relação lógica entre os nós
2. Binário vinculado lista: cada nó da árvore binária Um ponto tem apenas dois filhos no máximo, então um campo de dados e dois campos de ponteiro são projetados, o que é chamado de lista vinculada. Se necessário, você pode adicionar um campo de ponteiro a seus pais, que é chamado de lista de três pontas

//二叉树的二叉链表结点结构
typedef struct BiTNode //结点结构
{
    
    
    TElemType data;  //结点数据
    struct BiTNode *lchild,*rchild; //左右孩子指针
}BiTNode,*BiTree;

Percorra a árvore binária

Princípio: a partir do nó raiz, visite todos os nós na árvore binária em um momento em uma determinada ordem, de modo que cada nó seja visitado uma vez e visitado uma vez (visita, ordem)
1. Visita: Determine o que fazer de acordo com as necessidades de tempo O que, como cálculo / impressão de cada nó, etc.
2. Método transversal
Usamos gráficos para expressar a estrutura da árvore, que é mais intuitiva e fácil de entender, mas para o computador, só tem loops, julgamentos , etc., e apenas processa a sequência linear, o método transversal é transformar os nós da árvore em uma sequência linear com um certo significado

  • Percurso da pré-ordem: se a árvore binária estiver vazia, a operação não operacional retorna, caso contrário, o nó raiz é visitado primeiro, então a subárvore esquerda é percorrida na pré-ordem e a subárvore direita é percorrida na pré-ordem, por exemplo. árvore binária ABCDEFGHI é ABDGHCEIF
  • Travessia hierárquica: Se a árvore binária estiver vazia, a operação sem operação retorna, caso contrário, o nó raiz é visitado primeiro, percorrido camada por camada de cima para baixo, na mesma camada, os nós são visitados um a um na ordem de da esquerda para a direita, a árvore binária ABCDEFGHI O percurso da sequência é ABDGHCEIF
  • Percurso pós-pedido: Se a árvore binária estiver vazia, o no-op retorna, caso contrário, as subárvores esquerda e direita são percorridas para visitar as subárvores esquerda e direita e, finalmente, o nó raiz é visitado.
  • Travessia de ordem média: se a árvore binária estiver vazia, nenhuma operação retorna, caso contrário, a partir do nó raiz (observe que o nó raiz não é visitado primeiro), a ordem média atravessa a subárvore esquerda do nó raiz e visita o siga o nó e, finalmente, em ordem atravesse a subárvore direita
  • Casos de uso de código
    Fonte da imagem: Dahua Data Structure P187
//以下代码都是递归函数
//前序遍历:eg.二叉树ABCDEFGHI的前序遍历为ABDGHCEIF
void PreOrderTraverse(BiTree T)
{
    
    
    if (T==NULL)
        return;
    printf("%c",T->data); //显示结点数据,可以更改为其他对结点操作
    PreOrderTraverse(T->lchild); //前序遍历左子树
    PreOrderTraverse(T->rchild); //前序遍历右子树
}
//中序遍历
void InOrderTraverse(BiTree T)
{
    
    
    if (T==NULL)
        return;
    InOrderTraverse(T->lchild); //中序遍历左子树(遍历直到碰到一个左子树的叶子结点)
    printf("%c",T->data); //显示结点数据,可以更改为其他对结点操作
    InOrderTraverse(T->rchild); //中序遍历右子树
}
//后序遍历
void PostOrderTraverse(BiTree T)
{
    
    
    if (T==NULL)
        return;
    PostOrderTraverse(T->lchild); //后序遍历左子树(遍历直到碰到一个左子树的叶子结点)
    PostOrderTraverse(T->rchild); //后序遍历右子树
    printf("%c",T->data); //显示结点数据,可以更改为其他对结点操作
}
//二叉树的建立,将二叉树中每个空指针引出一个虚结点,其值为一特定值如#
void Create_BiTree(BiTree * T){
    
    
    TElemType ch;
    scanf("%c",&ch);  //“%c”表示输入数据的类型格式 &表示取地址 &ch表示输入数据后存到ch里面等于给ch赋值。
    if(ch == '@'){
    
    
        *T = NULL;
    }
        //# 表示构造结束
    else if(ch == '#'){
    
    
        return ;
    }
        //排除以上两种情况,则为有数据的结点,对其进行构造
    else{
    
    
        *T = (BiTree)malloc(sizeof(BiTNode));
        (*T)->data = ch;  //生成根结点
        //继续构造其左右孩子结点
        Create_BiTree(&(*T)->lchild);
        Create_BiTree(&(*T)->rchild);
    }
}

int main(){
    
    
    BiTree T;
    printf("input PreOrder str:");
    //AB@D@@C@@#
    //构造二叉树
    Create_BiTree(&T);
    printf("\n");
    //分别按照先序、中序、后序的方式遍历二叉树
    printf("preorder list of  T :");
    PreOrderTraverse(T);
    printf("\nInOrder list of T :");
    InOrderTraverse(T);
    printf("\nPostOrder list of T:");
    PostOrderTraverse(T);

Acho que você gosta

Origin blog.csdn.net/weixin_43464554/article/details/113590888
Recomendado
Clasificación