[Estructura de datos] Representación secundaria del árbol

Representación de árbol hijo

(Consulte "Estructura de Big Data", Tutorial de estructura de datos de Xie Xuewu)

Notación secundaria: el método específico es organizar los nodos secundarios de cada nodo, con una sola lista vinculada como estructura, luego los nodos tienen n listas vinculadas secundarias, si el nodo es un nodo hoja, la lista vinculada única está vacía . Luego, los punteros de la cabeza n forman una tabla lineal nuevamente, utilizando una estructura de almacenamiento secuencial y almacenada en una matriz unidimensional. Como se muestra:

JP9IAJ.png

La notación secundaria almacena árboles ordinarios utilizando una estructura combinada de " lista de secuencias + lista vinculada ". El proceso de almacenamiento es: a partir del nodo raíz del árbol, utilizando la lista de secuencias para almacenar cada nodo en el árbol en secuencia. Cabe señalar que con la notación parental De manera diferente, la notación secundaria equipará cada nodo con una lista vinculada, que se usa para almacenar la posición del nodo secundario de cada nodo en la tabla de secuencia. (Si el nodo no tiene hijos (nodos hoja), la lista vinculada del nodo es una lista vinculada vacía).

Por ejemplo, usando la notación secundaria para almacenar el árbol ordinario en la Figura 1a), el estado de almacenamiento final se muestra en la Figura 1b):

JPS7VJ.png

Figura 1 Diagrama esquemático del almacenamiento normal de árboles en notación infantil

JPCVHg.png

El siguiente es el código de definición de estructura de la notación secundaria:

/*树的孩子表示法结构定义*/
#define MAX_TRUE_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;

Con esta estructura, si desea encontrar un hijo de un nodo determinado o un hermano de un nodo determinado, solo necesita encontrar la lista de hijos de este nodo. También es conveniente para atravesar todo el árbol, simplemente recorra la matriz de nodos principales.

El código completo se implementa de la siguiente manera: (Extracto de Xuewu Data Structure Tutorial)

#include<stdio.h>
#include<stdlib.h>
#define MAX_SIZE 20
#define TElemType char
//孩子表示法
typedef struct CTNode{
    int child;//链表中每个结点存储的不是数据本身,而是数据在数组中存储的位置下标
    struct CTNode * next;
}ChildPtr;
typedef struct {
    TElemType data;//结点的数据类型
    ChildPtr* firstchild;//孩子链表的头指针
}CTBox;
typedef struct{
    CTBox nodes[MAX_SIZE];//存储结点的数组
    int n,r;//结点数量和树根的位置
}CTree;
//孩子表示法存储普通树
CTree initTree(CTree tree){
    printf("输入节点数量:\n");
    scanf("%d",&(tree.n));
    for(int i=0;i<tree.n;i++){
        printf("输入第 %d 个节点的值:\n",i+1);
        fflush(stdin);
        scanf("%c",&(tree.nodes[i].data));
        tree.nodes[i].firstchild=(ChildPtr*)malloc(sizeof(ChildPtr));
        tree.nodes[i].firstchild->next=NULL;

        printf("输入节点 %c 的孩子节点数量:\n",tree.nodes[i].data);
        int Num;
        scanf("%d",&Num);
        if(Num!=0){
            ChildPtr * p = tree.nodes[i].firstchild;
            for(int j = 0 ;j<Num;j++){
                ChildPtr * newEle=(ChildPtr*)malloc(sizeof(ChildPtr));
                newEle->next=NULL;
                printf("输入第 %d 个孩子节点在顺序表中的位置",j+1);
                scanf("%d",&(newEle->child));
                p->next= newEle;
                p=p->next;
            }
        }
    }
    return tree;
}

void findKids(CTree tree,char a){
    int hasKids=0;
    for(int i=0;i<tree.n;i++){
        if(tree.nodes[i].data==a){
            ChildPtr * p=tree.nodes[i].firstchild->next;
            while(p){
                hasKids = 1;
                printf("%c ",tree.nodes[p->child].data);
                p=p->next;
            }
            break;
        }
    }
    if(hasKids==0){
        printf("此节点为叶子节点");
    }
}

int main()
{
    CTree tree;
    tree = initTree(tree);
    //默认数根节点位于数组notes[0]处
    tree.r=0;
    printf("找出节点 F 的所有孩子节点:");
    findKids(tree,'F');
    return 0;
}

El resultado de ejecución del programa es:

输入节点数量:
10
输入第 1 个节点的值:
R
输入节点 R 的孩子节点数量:
3
输入第 1 个孩子节点在顺序表中的位置1
输入第 2 个孩子节点在顺序表中的位置2
输入第 3 个孩子节点在顺序表中的位置3
输入第 2 个节点的值:
A
输入节点 A 的孩子节点数量:
2
输入第 1 个孩子节点在顺序表中的位置4
输入第 2 个孩子节点在顺序表中的位置5
输入第 3 个节点的值:
B
输入节点 B 的孩子节点数量:
0
输入第 4 个节点的值:
C
输入节点 C 的孩子节点数量:
1
输入第 1 个孩子节点在顺序表中的位置6
输入第 5 个节点的值:
D
输入节点 D 的孩子节点数量:
0
输入第 6 个节点的值:
E
输入节点 E 的孩子节点数量:
0
输入第 7 个节点的值:
F
输入节点 F 的孩子节点数量:
3
输入第 1 个孩子节点在顺序表中的位置7
输入第 2 个孩子节点在顺序表中的位置8
输入第 3 个孩子节点在顺序表中的位置9
输入第 8 个节点的值:
G
输入节点 G 的孩子节点数量:
0
输入第 9 个节点的值:
H
输入节点 H 的孩子节点数量:
0
输入第 10 个节点的值:
K
输入节点 K 的孩子节点数量:
0
找出节点 F 的所有孩子节点:G H K

La estructura de árbol almacenada usando la notación secundaria es exactamente la opuesta a la notación primaria. Es adecuada para encontrar el nodo secundario de un determinado nodo, no para encontrar su nodo primario.

De hecho, puede combinar la notación principal y la notación secundaria en una, como se muestra en la siguiente figura:

JPk6yt.png

Figura 2 Notación para padres

El uso de la estructura que se muestra en la Figura 2 para almacenar un árbol ordinario puede encontrar rápidamente el nodo primario del nodo especificado y el nodo secundario del nodo especificado.

Supongo que te gusta

Origin www.cnblogs.com/desola/p/12707029.html
Recomendado
Clasificación