¿Cómo escribir código para una estructura de almacenamiento secuencial de un árbol binario en una estructura de datos?
Representación de almacenamiento secuencial e implementación del árbol binario de estructura de datos en lenguaje C
P126
Compilado en Dev-C 4.9.9.2
Fecha: 13 de febrero de 2011
*/
#clude stdio: 13 de febrero de 2011
p>*/
#include lt; stdio.hgt;
typedef char TElemType
//Representación de almacenamiento secuencial del árbol binario
p>
#define MAX_TREE_SIZE 100 //El número máximo de nodos en el árbol binario
typedef TElemType SqBiTree[MAX_TREE_SIZE];
typedef struct
{
int nivel, //El nivel del nodo
orden; //El número de secuencia de este nivel (según el árbol binario completo)
}posición.
typedef int QElemType;
//Estructura de almacenamiento ordenada de la cola (se puede utilizar para colas circulares y colas acíclicas)
#define MAXQSIZE 5 // Cola La longitud máxima (para colas circulares, la longitud máxima de la cola debe ser menos 1)
typedef struct<
{
QElemType *base; / Inicialización dinámica El espacio de almacenamiento asignado es equivalente a una matriz
int front; // El puntero principal, si la cola no está vacía, apunta al encabezado de la cola, equivalente al subíndice de una matriz.
int rear; // Puntero de cola, si la cola no está vacía, apunta al final de la cola. siguiente posición
// Equivalente al subíndice de matriz
}SqQueue;
#define ClearBiTree InitBiTree // En la estructura de almacenamiento secuencial, estas dos funciones son iguales
TElemType Nil = ' '; // Establece nulo como el carácter de espacio del tipo de carácter
// Construye un árbol binario vacío T. Dado que T es una matriz fija y no cambiará, no es necesario amp
int InitBiTree(SqBiTree T)
{
int
for(i=0; ilt; MAX_TREE_SIZE; i )
T[i]=Nil // El valor inicial está vacío
Devuelve 1;
}
void DestroyBiTree()
{
// SqBiTree no se puede destruir porque es un tipo de longitud fija
}
//Ingrese los valores de los nodos en el árbol binario en orden jerárquico.
int CreateBiTree(SqBiTree T)
{
int i = 0, l
char s[MAX_TREE_SIZE]; p>
p>
printf("Ingrese los valores de los nodos en orden jerárquico.
Ingrese los valores de los nodos (caracteres) en orden jerárquico, los espacios representan nodos vacíos, el número de nodos ≤ d:\n",
MAX_TREE_SIZE);
printf("por ejemplo: abcefgh\n" );
gets(s); // Ingresa la cadena
l = strlen(s); // Encuentra la longitud de la cadena
for(; ilt; l; i ) // Asignar cadena a T
{
T[i]=s[i]; Este nodo (no vacío) no tiene un nodo principal y no es un nodo raíz T[(i 1)/2-1] == Nil significa que T[i] no tiene un nodo principal
if(. i!=0 amp; T[(i 1)/2-1] == Nil amp; T[i] = Nil)
{
printf ("Aparece el nodo no raíz c\ n sin doble padre", T[i]
exit(0); /p>
}
for(i=l; ilt; MAX_TREE_SIZE; i ) // Asignar nulo al nodo después de T
T[i]=Nil;
Devuelve 1;
}
//Si T es un árbol binario vacío, devuelve 1; de lo contrario, devuelve 0
int BiTreeEmpty( SqBiTree T)
{
if(T[0]==Nil) // La raíz del árbol está vacía, entonces el nodo está vacío.
Si el nodo está vacío, el árbol está vacío
Devuelve 1
En caso contrario
Devuelve 0
}
;// Devuelve la profundidad de T
int BiTreeDepth(SqBiTree T)
{
int i, j=-1;
p>for(i=MAX_TREE_SIZE-1;igt;=0;i--) // Encuentra el último nodo
if(T[i] != Nil)
break;
i ; // Para facilitar el cálculo
do
j ;
while(igt;= pow(2, j)); //i gt; pow(2, profundidad-1) amp; i lt; = pow(2, profundidad)
return j; ; p>
}
// Cuando T no está vacío, usa e para devolver la raíz de T y devuelve 1; de lo contrario, devuelve 0 y e no está definido
int Raíz (SqBiTree T, TElemType *e)
{
if( p>
Valor TElemType(SqBiTree T, posición e)
{
// Convierte el número de serie de la capa y el nivel actual en el número de serie de la matriz
return T[((int)pow(2, e. nivel-1) - 1) ( e.order - 1)];
// ((int)pow(2, e.level-1) - 1) es el número de nodos del e.level,
// (e .order - 1) es la posición del nodo de e.level order - 1) es la posición de la capa.
}
int Assign(SqBiTree T, posición e, valor TElemType)
{
// Convierte la capa y el número de secuencia de la capa en una matriz Número de serie
int i = (int)pow(2, e.level-1) e.order - 2;
if(value != Nil amp; amp; T[ (i 1)/2-1] == Nil) // hoja con valor no nulo pero dos padres son nulos
devolver 0;
else if(valor == Nil amp ;amp; (T[i*2 1] ! = Nil || T[i*2 2] ! = Nil))
// El nodo padre está vacío, pero tiene hojas (no vacías)
Devuelve 0;
T[i]=valor;
Devuelve 1;
}
/// Si e es un nodo no raíz de T, devuelve su nodo padre; de lo contrario, devuelve "nulo".
"
TElemType Padre(SqBiTree T, TElemType e)
{
int i;
if(T[0]== Nil) // Árbol vacío
return Nil;
for(i =1; ilt; =MAX_TREE_SIZE-1; i )
if(T[i ]==e) // encontrado e
return T[(i 1)/2-1]
return Nil // encontrado e no
}
// Devuelve el nodo secundario izquierdo de e. Si e no tiene un nodo secundario izquierdo, devuelve "null"
TElemType LeftChild(SqBiTree T, TElemType e) p >
{
int i;
if(T[0]==Nil) // Árbol vacío
return Nil // Aún no; Encontrado p>
return Nil;
for(i=0;ilt;=MAX_TREE_SIZE-1;i)
if(T[i]= =e) // encontré e
return T[i*2 1];
return Nil // encontré e no
}
// Devuelve el nodo hijo derecho de e. Si e no tiene un nodo hijo derecho, devuelve Null
TElemType RightChild(SqBiTree T, TElemType e)
{
int i;
if(T[0]==Nil) // Árbol vacío<
Devuelve Nil; 0 ;ilt;=MAX_TREE_SIZE-1;i )
if(T[i]==e) // encontrar e
devolver T[i*2 2]; p >
return Nil; // no se encontró e
}
// Devuelve el nodo secundario izquierdo de e.
Devuelve "nulo" si e es el subárbol izquierdo de T o no tiene un hermano izquierdo
TElemType LeftSibling(SqBiTree T, TElemType e)
{
int i ;
if(T[0]== Nil) // árbol vacío
return Nil
for(i=1; ilt;=MAX_TREE_SIZE - 1; i )
if(T[i] == e amp; amp; i2 == 0) // se encuentra e y su número de secuencia es par (es un hijo derecho) p >
Si e es hijo derecho de T o no tiene hermano derecho, devuelve Nil
TElemType RightSibling(SqBiTree T, TElemType e)
{
int i;
if(T[0]== Nil) // Árbol vacío
Devuelve Nil; =MAX_TREE_SIZE-1; i )
if(T[i]==eamp; amp; i2) // Encuentra e, y su número de secuencia es impar (es el hijo izquierdo)
Return T[ i 1];
Return Nil; // e no fue encontrado
}
// El niño a partir del nodo j de q Mueve el árbol al subárbol comenzando desde el nodo i de T
//// Se usa InsertChild()
void Move(SqBiTree q, int j, SqBiTree T, int i)
{
if(q[2*j 1] != Nil) // El subárbol izquierdo de q no está vacío
Move( q, (2*j 1), T, (2*i 1)); // Mueve el subárbol izquierdo del nodo j de q al subárbol izquierdo del nodo i de T
if(q[ 2*j 2] ! = Nil) // El subárbol derecho de q no está vacío
Move(q, (2*j 2), T, (2*i 2)); el subárbol derecho del nodo j de q al subárbol derecho del nodo i de T
T[i]=q[j] // Mueve el nodo j de q al nodo i de T
;q[j]=Nil; // Deja que el nodo j de q esté vacío
}
If (q[2*j 2]! p>
}
// Inserte c como el subárbol izquierdo o derecho del nodo p en T, dependiendo de si LR es 0 o 1.
El subárbol izquierdo o derecho original de p
//El subárbol derecho se convierte en el subárbol derecho de c
int InsertChild(SqBiTree T, TElemType p, int LR, SqBiTree c) p>
{
int j, k, i=0;
for(j=0; jlt; (int)pow(2,BiTreeDepth(T))- 1; j ) // Encuentra el número de serie de p
if(T[j]==p) // j es el número de serie de p
break;
k= 2*j 1 LR; // k es el número de secuencia del subárbol izquierdo o derecho de p
if(T[k] != Nil) // El subárbol izquierdo original o el subárbol derecho de p no está vacío
Move(T, k, T, 2*k 2 // Mueve el subárbol comenzando desde el nodo k de T al subárbol comenzando desde el subárbol derecho de); el nodo k
Move(c, i, T, k); // Mueve el subárbol comenzando desde el nodo i de c al subárbol comenzando desde el nodo k de T
Retornar 1 ;
}
//Construir una cola vacía Q
int InitQueue(SqQueue *Q)
{
(*Q).base=(QElemType *)malloc(MAXQSIZE*sizeof( QElemType)); // Asigna espacio de longitud fija, equivalente a una matriz
if(! (*Q). base) // Error en la asignación de espacio de almacenamiento
exit(0);
(*Q).front=(*Q).rear=0 // Subíndice de inicialización
return 1;
}
//Insertar elemento e como nuevo elemento final de cola de Q
int EnQueue(SqQueue *Q, QElemType e)
{
if((*Q).reargt;=MAXQSIZE)
{ // La cola está llena, la unidad de almacenamiento se incrementa en 1
(*Q).base=(QElemType *)realloc(((*Q).*Q).base, ((*Q).rear 1)*sizeof(QElemType));
if(! (*Q).base) // No se pudo agregar la unidad
Devuelve 0;
}
*(( *Q).base (* Q).rear)=e;
(*Q).rear;
Devuelve 1;
}
// if La cola no está vacía.
Luego elimine el elemento principal de Q, devuelva su valor con e y devuelva 1; de lo contrario, devuelva 0
int DeQueue(SqQueue *Q, QElemType *e)
{
if((*Q).front==(*Q).rear) // La cola está vacía
Devuelve 0;
*e=(*Q ) .base[(*Q).front];
(*Q).front=(*Q).front 1;
Devuelve 1;
}
int DeleteChild(SqBiTree T, posición p, int LR)
{
int
int k=1; ; // La cola de banderas no está vacía
SqQueue q;
InitQueue(amp; q); Se utiliza para guardar el nodo que se va a eliminar
i=(int)pow(2, p.level-1) p.order-2 //Convierte el nivel y el número de serie del nivel en el número de serie de la matriz
if(T[i]==Nil) // El nodo está vacío
return
i=i*2; 1 LR; // Esperar El nodo raíz eliminado es el número de secuencia del nodo raíz del subárbol eliminado en la matriz
while(k)
{
if(T[2*i 1] ! =Nil) // El nodo izquierdo no está vacío
EnQueue(amp; q, 2*i 1); nodo
if(T [2*i 2]! =Nil) // El nodo derecho no está vacío
EnQueue(amp; q, 2*i 2); El número de secuencia del nodo derecho entrante
T[i]=Nil; // Eliminar este nodo
k=DeQueue(amp; q, amp; i); la cola no está vacía
}
Devuelve 1;
}
int(*VisitFunc)(TElemType);
void PreTraverse(SqBiTree T, int e)
{
// llamadas a PreOrderTraverse()
VisitFunc(T[e] ); // Primero llama a la función VisitFunc para procesar la raíz p>
if(T[2*e 1]!=Nil) // El subárbol izquierdo no está vacío
PreTraverse( T, 2*e 1); // Luego procesa el subárbol del lado izquierdo
if(T[2*e 2]! =Nil) // El subárbol derecho no está vacío
PreTraverse(T, 2*e 2); p>
}
// Recorre T en el primer orden, llamando a la función Visit solo una vez para cada nodo.
int PreOrderTraverse(SqBiTree T, int(*Visit)(TElemType))
{
VisitFunc=Visita;
if( !BiTreeEmpty(T))
PreTraverse(T, 0
printf("\n");
devuelve 1; p>}
// llamada InOrderTraverse()
void InTraverse(SqBiTree T, int e)
{
if(T[2*e 1]! =Nil) // El subárbol izquierdo no está vacío
InTraverse(T, 2*e 1);
VisitFunc(T[e]);
if(T[2*e 2]! =Nil) // El subárbol derecho no está vacío
InTraverse(T, 2*e 2);
}
// Atraviesa T en orden intermedio, llamando a la función Visita solo una vez para cada nodo.
int InOrderTraverse(SqBiTree T, int(*Visit)(TElemType))
{
VisitFunc=Visita
if( !BiTreeEmpty(T))
InTraverse(T, 0
printf("\n");
devuelve 1; p>}
// Llamada a PostOrderTraverse()
void PostTraverse(SqBiTree T, int e)
{
if(T [2*e 1]! =Nil) // El subárbol izquierdo no está vacío
PostTraverse(T, 2*e 1);
if(T[2*e 2] ]! =Nil) // El subárbol derecho no está vacío
PostTraverse(T, 2*e 2);
VisitFunc(T[e]);
}
// Realiza un recorrido posterior en T y llama a la función Visita solo una vez para cada nodo.
int PostOrderTraverse(SqBiTree T, int(*Visit)(TElemType))
{
VisitFunc = Visita
if( !BiTreeEmpty(T))
PostTraverse(T, 0
printf("\n");
Devuelve 1; p>}
// Recorrido de orden de nivel del árbol binario
void LevelOrderTraverse(SqBiTree T, int(*Visit)(TElemType))
{< / p>
int i=MAX_TREE_SIZE-1, j;
while(T[i] == Nil)
i-- // Encuentra el último no nulo Número de serie del nodo
for(j=0;jlt;=i;j) //Comience desde el nodo raíz y recorra nivel por nivel.
Nodos, recorre el árbol binario en orden jerárquico
if(T[j] != Nil)
Visit(T[j]); // Solo recorre nodos no vacíos
printf("\n");
}
/// Genera el árbol binario capa por capa según el número de capas
void Print(SqBiTree T)
{
int j, k
posición p
TElemType e
p>for(j= 1;jlt;=BiTreeDepth(T);j )
{
printf("Nivel d:",j);
for(k=1 ; k lt ;= pow(2,j-1);k )
{
p.level=j;
p.order=k;
e=Valor(T, p);
if (e!=Nil)
printf("d :c ",k,e);
}
printf("\n");
}
} p>
int visita(TElemType e)
{
printf("c ",e);
return 0;
}
int main()
{
int i, j
posición p; > TElemType e;
SqBiTree T, s;
InitBiTree(T);
CreateBiTree(T); Después de crear el árbol binario, ¿está vacío? d(1: sí 0: no) profundidad del árbol=d\n",
BiTreeEmpty(T), BiTreeDepth(T)); >
i=Root(T, amp; e);
if(i)
printf("La raíz del árbol binario es: c\n", e
else
printf("Árbol vacío, sin raíz \n");
printf("Atravesando el árbol binario en orden de niveles:\n"
LevelOrderTraverse (T, visita);
printf("Atravesando el árbol binario en orden medio:\n"); );
printf ("Atravesando el árbol binario en orden de publicación:\n");
PostOrderTraverse(T, visita);
printf("Por favor, ingrese el número de nivel del nodo que se va a modificar El número ordinal de este nivel: ");
scanf("dd*c", amp; p. nivel, amp; p.order.level, amp
; p.order);
e=Value(T, p);
printf("El valor original del nodo a modificar es c Ingrese el nuevo valor:" , e);
scanf("c*c", amp; e);
Assign(T, p, e); > printf("Árbol binario PreOrderTraverse:\n");
PreOrderTraverse(T, visita);
printf("Los dos padres del nodo c son c, y los izquierdo y los hijos derechos son ", e, Parent(T, e));
printf("c, c, los hermanos izquierdo y derecho son ", LeftChild(T, e), RightChild(T, e)) ;
printf("c, c\n", LeftSibling(T, e), RightSibling(T, e));
InitBiTree(s); p> printf("Creando árbol s con subárbol derecho vacío:\n");
CreateBiTree(s);
printf("El árbol s se inserta en el árbol T, ingrese el nodo biparental s del árbol s en el árbol T como un subárbol izquierdo(0) o derecho(1):");
scanf("cd*c",amp;e,amp;j);
InsertChild(T, e, j, s);
Print(T);
printf("Eliminando un subárbol, ingrese el número de nivel de el nodo raíz del subárbol que se va a eliminar Este número de nivel Subárbol izquierdo(0) o derecho(1):");
scanf("ddd*c",amp;p.level,amp;p .orden, & j);
DeleteChild(T, p, j
Imprimir(T);
ClearBiTree(T); >
p>
printf("Después de borrar el árbol binario, ¿está vacío el árbol? d(1: sí 0: no) La profundidad del árbol = d\n",
BiTreeEmpty(T), BiTreeDepth (T));
i=Root(T,amp;e);
if(i)
printf(" La raíz del árbol binario es: c\n", e);
else
printf("Árbol vacío, sin raíz \n");
system("pause");
return 0;
}
/*
Efecto de salida:
Ingrese el valor del nodo (en caracteres) en orden jerárquico. Los espacios representan nodos vacíos. Número de nodos ≤ 100:
Ejemplo: abcefgh
abcdefgh
Después de construir el árbol binario, ¿está vacío el árbol? (1: Sí 0: No) Profundidad del árbol = 4
La raíz del árbol binario es: a
Recorrido jerárquico del árbol binario:
a b c d e f g h
Recorrido de nivel medio de un árbol binario:
h d b e a f c g
Recorrido posterior al orden de un árbol binario:
h d e b f g c a
Ingrese el nodo a modificar. El número de capa es: 3 2
El valor original del nodo a modificar es e. Ingrese el nuevo valor: i
.Primero recorra el árbol binario:
a b d h i c f g
El nodo i es el primer nodo que se modifica. p>
El nodo i tiene dos nodos principales b, dos nodos secundarios izquierdo y derecho, y dos nodos hermanos izquierdo y derecho d.
Cree un árbol s con un subárbol derecho vacío:
p>Ingrese el valor del nodo en orden jerárquico (en caracteres). Un espacio indica un nodo vacío. El número de nodos es ≤100:
Por ejemplo, abcefgh.
jk l
El árbol s se inserta en el árbol T. Ingrese los nodos principales de los árboles en el árbol T. s es el subárbol izquierdo (0) o derecho (1): i 0
Nivel 1: 1: a
Nivel 2: 1: b 2: c
Nivel 3: 1: d 2: i 3: f 4: g
Nivel 4: 1: h 3: j
Nivel 5: 5: k
Nivel 6: 9: l
Para eliminar un subárbol, ingrese el número de nivel del nodo raíz del subárbol que desea eliminar Número de nivel izquierdo (0) o derecho (1) Subárbol: 2 1 0
Nivel 1: 1: a
Nivel 2: 1: b 2: c
Nivel 3: 2: i 3: f 4: g< / p>
Nivel 4: 3: j
Nivel 5: 5: k
Nivel 6: 9: l
Nivel 7: 9: k
Nivel 8: 9:k
Nivel 9: 9:k
Nivel 9: 9:k
Nivel 10 Nivel : 9: k
Nivel 10: 9:k
Nivel 11: 9:l Nivel 6: 9:l
Después de borrar el árbol binario, es ¿El árbol vacío? 1(1: Sí 0: No) Profundidad del árbol = 0
El árbol está vacío y no tiene raíces
Presione cualquier tecla para continuar. .
*/.