La définition de la structure des nœuds de la représentation parente de l'arbre
Avantages : il est facile de trouver son nœud parent en fonction du pointeur parent du nœud, et la complexité temporelle est 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;
La définition de la structure des nœuds de la représentation enfant de l'arborescence
Il existe des nœuds racine de plusieurs sous-arbres dans l'arborescence. Pensez à utiliser plusieurs listes liées, c'est-à-dire que chaque nœud a plusieurs champs de pointeur et que chaque pointeur pointe vers le nœud racine d'un sous-arbre. C'est ce qu'on appelle le
schéma de représentation de plusieurs listes liées 1: Le nombre de champs de pointeur est égal au degré de l’arbre.
Inconvénient: lorsque le degré de chaque nœud de l’arbre diffère beaucoup, c’est évidemment une perte de temps, car les champs de pointeur de nombreux nœuds sont vides, mais si les nœuds de l'arbre La petite différence de degré de point signifie que l'espace est pleinement utilisé.
Solution 2: Allouez de l'espace à la demande, le nombre de champs de pointeur de chaque nœud est égal au degré du nœud et un emplacement est spécialement sélectionné pour stocker le nombre de champs de pointeur de nœud. nombre d'
avantages: surmonte les inconvénients de l'espace gaspillé; inconvénients: puisque chaque structure de nœud de liste chaînée n'est pas la même, avec la valeur à maintenir en degrés de nœud, la perte de temps apportera une notation enfant par calcul
- Réorganisez les nœuds de chaque enfant et utilisez la liste liée individuellement comme espace de stockage. Ensuite, il y a n listes liées enfants pour n nœuds. S'il s'agit d'un nœud feuille, la liste liée individuellement est vide, puis n pointeurs d'en-tête forment un linéaire liste. Structure de stockage séquentielle, placée dans un tableau unidimensionnel
- Le nœud enfant de la liste liée enfant (stocke l'indice d'un nœud dans le tableau d'en-tête; le champ pointeur est utilisé pour stocker le pointeur vers le nœud enfant suivant d'un nœud), le nœud d'en-tête du tableau d'en-tête (champ de données, le champ de pointeur de tête stocke le pointeur de tête de la liste chaînée enfant du nœud)
- Avantages: pour trouver les enfants / frères d'un nœud, il vous suffit de trouver la liste des enfants de ce nœud, ce qui est plus pratique
- Inconvénients: vous devez parcourir toute l'arborescence pour atteindre le parent du nœud. Vous pouvez ajouter le pointeur parent du nœud dans la structure d'en-tête * /
//树的孩子表示法结构定义
#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;
Notation de frère enfant
- Principe: Pour tout arbre, le premier enfant d'un nœud est unique s'il existe, et le bon frère est également unique. Deux pointeurs peuvent être positionnés pour pointer vers le premier enfant du nœud et le frère droit du nœud.
- Avantages: facile de trouver un enfant d'un nœud, il suffit de trouver le fils aîné du nœud via firstchild, puis de trouver le deuxième frère via le rightsib du nœud enfant le plus âgé
- Inconvénients: Il n'est pas facile de trouver les parents du nœud, mais le problème de trouver rapidement les parents peut être résolu en ajoutant un champ de pointeur parent
typedef struct CSNode
{
TElemType data;
struct CSNode *firstchild, *rightsib;
}CSNode,*CSTree;
Arbre binaire
1. Structure de stockage séquentiel: utilisez un tableau unidimensionnel pour stocker les nœuds de l'arborescence binaire, et l'emplacement de stockage du nœud, c'est-à-dire l'indice du tableau, doit refléter la relation logique entre les nœuds
2. Binaire lié list: chaque nœud de l'arbre binaire Un point n'a que deux enfants au maximum, donc un champ de données et deux champs de pointeur sont conçus, ce que l'on appelle une liste chaînée. Si nécessaire, vous pouvez ajouter un champ de pointeur à ses parents, qui est appelé une liste à trois volets
//二叉树的二叉链表结点结构
typedef struct BiTNode //结点结构
{
TElemType data; //结点数据
struct BiTNode *lchild,*rchild; //左右孩子指针
}BiTNode,*BiTree;
Traversez l'arbre binaire
Principe: À partir du nœud racine, visitez tous les nœuds de l'arbre binaire à la fois dans un certain ordre, de sorte que chaque nœud soit visité une fois et visité une fois (visite, ordre)
1. Visite: Déterminez ce qu'il faut faire en fonction des besoins du temps Quoi, comme le calcul / impression de chaque nœud, etc.
2. Méthode de traversée
Nous utilisons des graphiques pour exprimer la structure de l'arbre, qui est plus intuitive et facile à comprendre, mais pour l'ordinateur, il n'a que des boucles, des jugements , etc., et ne traite que la séquence linéaire, la méthode de traversée consiste à transformer les nœuds de l'arbre en une séquence linéaire avec une certaine signification
- Traversée de pré-ordre: si l'arbre binaire est vide, l'opération no-op retourne, sinon le nœud racine est visité en premier, puis le sous-arbre de gauche est parcouru en pré-ordre, et le sous-arbre de droite est parcouru en pré-ordre, par exemple. Le parcours de pré-ordre du arbre binaire ABCDEFGHI est ABDGHCEIF
- Traversée hiérarchique: Si l'arbre binaire est vide, l'opération no-op retourne, sinon le nœud racine est visité en premier, parcouru couche par couche de haut en bas, dans la même couche, les nœuds sont visités un par un dans l'ordre de de gauche à droite, l'arbre binaire ABCDEFGHI Le parcours de séquence est ABDGHCEIF
- Traversée post-ordre: Si l'arbre binaire est vide, le no-op retourne, sinon les sous-arbres gauche et droit sont traversés pour visiter les sous-arbres gauche et droit, et enfin le nœud racine est visité.
- Traversée d'ordre moyen: si l'arborescence binaire est vide, aucune opération ne retourne, sinon à partir du nœud racine (notez que le nœud racine n'est pas visité en premier), l'ordre intermédiaire traverse le sous-arbre gauche du nœud racine, puis visite le suivez le nœud, et enfin ordonné traversez le sous-arbre de droite
- Cas d'utilisation du code
//以下代码都是递归函数
//前序遍历: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);