Un artículo que le ayudará a comprender la diferencia entre matriz de adyacencia, lista de adyacencia y cadena de estrella directa.

Prefacio:

Cuando estaba aprendiendo C ++, frente a varios métodos de almacenamiento de imágenes, mi cerebro era mucho más grande y varios algoritmos todavía corrían hacia mí. Como resultado, una matriz de adyacencia / lista de adyacencia / lista vinculada fácilmente me dio un crítico Déjame KO Directamente, y mientras mi mente aún esté clara, presentaré en detalle la esencia y la implementación del código de estos tres métodos de almacenamiento de imágenes.

Realización de ideas:

La estrella encadenada y la matriz de adyacencia son adecuadas para almacenar gráficos densos, mientras que las listas de adyacencia son adecuadas para almacenar gráficos dispersos. Al hacer preguntas, puede elegir tres formas de almacenar gráficos de acuerdo con diferentes rangos de datos.
Ahora que se menciona la imagen, presentémosla primero.

1. ¿Qué es una imagen?

Un gráfico es una estructura de datos. Para los principiantes, se puede entender que un gráfico es un gráfico con muchos puntos conectados por aristas.
Los gráficos se dividen en gráficos no dirigidos y gráficos dirigidos. Un gráfico no dirigido significa que no hay una direccionalidad clara entre dos puntos y que los dos puntos pueden visitarse y atravesarse entre sí.
El gráfico dirigido es diferente de esto: después de ingresar la directividad, la computadora solo puede atravesar de acuerdo con el gráfico dirigido creado previamente.


inserte la descripción de la imagen aquí
Los dos diagramas son similares, pero algunos detalles son muy diferentes. Sin embargo, la entrada del gráfico dirigido y el gráfico no dirigido son exactamente las mismas, pero el significado es ligeramente diferente. Aquí hay un ejemplo del gráfico anterior: aquí
asumimos que hay un borde de uv en el gráfico, y las entradas de los dos gráficos son:

1 2
1 4
5 1
1 3

Aquí tomemos "1 2" en la primera línea como ejemplo;
en un gráfico no dirigido, puedo acceder al nodo ② desde el nodo ①, y también puedo acceder al nodo ① desde el nodo ②;
en un gráfico dirigido: porque la secuencia de entrada es ' 1 'primero y luego '2', en el proceso de atravesar y acceder al gráfico, solo puede visitar el nodo ② desde el nodo ①.
Además de la relación de los bordes, otra cosa importante en el gráfico es el peso de los bordes: en pocas palabras, es el "costo" requerido para visitar dos nodos.
inserte la descripción de la imagen aquí
Aquí tomamos el gráfico dirigido como ejemplo. No es difícil encontrar en la figura anterior que el peso del borde del nodo ① al nodo ② es 3, y el peso del borde del nodo ② al nodo ③ es 4 ... aquí el El peso de los bordes es La función es que, en algunas preguntas, cuál es la suma de los pesos de los bordes necesarios para ir de un determinado nodo a otro.
Los gráficos también se dividen en gráficos densos y gráficos dispersos: los gráficos dispersos tienen menos aristas que los gráficos completos y los gráficos densos tienen aristas cercanas a los gráficos completos.
Después de hablar sobre el gráfico, a continuación se presentará el principio y la implementación del código de la estrella directa, la matriz de adyacencia y el gráfico de almacenamiento de la tabla de adyacencia uno por uno.

2. Estrella delantera de cadena

La esencia de la estrella delantera encadenada es una lista vinculada, pero también tiene una matriz principal para registrar el nodo principal. Usando la lista vinculada, la operación de almacenamiento de imágenes se puede realizar de acuerdo con las características de un nodo que accede a otro nodo. Supongamos que tiene n puntos ym aristas. Entonces, su eficiencia espacial y su eficiencia espacial son O (m), que es adecuada para almacenar gráficos densos. A continuación se utiliza el código para explicar el principio;

struct EDGE{
    
    
	int v,w,next;
	//v变量记录的是当前点到达那一条边。
	//w变量记录的是走过当前这条边所需的"代价"即权值
	//next变量记录的是以某一个定点为起点,读的上一条边的编号。
	//这三个变量的意义一定要搞明白,不搞明白这个,前向星的写法死记硬背也不一定行。
}e[N<<1];
int head[N],tot=1;
void add(int u,int v,int w)
{
    
    
	e[tot].v=v;
	e[tot].w=w;
	e[tot].next=head[u];
	head[u]=tot++;
}

Supongamos que hay un gráfico aquí:
inserte la descripción de la imagen aquí
este es un gráfico ponderado dirigido, por lo que la entrada entre sus lados debe ser:
inserte la descripción de la imagen aquí
las tres variables correspondientes a v, w y la siguiente en la matriz de estructura deben ser:
inserte la descripción de la imagen aquí
no es difícil ver que aquí Tot registra el número de la línea anterior, es decir, puedo encontrar el número de la línea anterior hasta tot, para encontrar el hasta, w, siguiente de la imagen guardada anterior; entonces, ¿para qué sirve la matriz principal
? Dibujemos otro gráfico;
inserte la descripción de la imagen aquí

Se puede ver en esta figura que la matriz principal es en realidad el número del último borde que leí a partir del i-ésimo punto numerado.
Para aquellos que no entienden, el blogger da un ejemplo para explicarlo basado en código e imágenes.
Se puede decir que la matriz principal es la idea central de la cadena de estrellas delanteras.

Supongamos que queremos encontrar el borde cuyo punto inicial es 1, el punto final es 4 y el peso del borde es 9.
Debido a que el punto inicial es 1, encontramos que el valor almacenado en head[1] es 4, lo que significa que el número del último borde que leemos comenzando desde 1 es 4.
inserte la descripción de la imagen aquí
Según el número, encontramos el conjunto de datos en la línea horizontal de la figura anterior. Hasta ahora, se ha desempeñado el papel de la matriz principal, y luego entra en juego la siguiente variable.
El siguiente valor variable de la línea con la línea roja en la figura anterior es 3, lo que indica que el número de la arista anterior que comienza en 1 es 3, por lo que encontramos la línea con el número 3, ya que no es lo que estamos buscando. Entonces, miremos la línea numerada como El siguiente de la fila de 3 es 2, entonces visitamos la fila numerada 2 y encontramos que es exactamente el borde que estamos buscando, y luego finalizamos la búsqueda.
inserte la descripción de la imagen aquí
Por lo tanto, encontramos el borde número 2 del borde número 3 y encontramos el borde del resultado, como se muestra en la figura anterior. Por lo tanto, la búsqueda continua no es solo como una cadena, por lo que esta forma de almacenar imágenes se llama cadena. estrella delantera.
El principio es claro y luego explicaré cada paso del código uno por uno de acuerdo con la leyenda y el principio mencionados anteriormente.

Explicación del código:

Lo dividimos en dos partes, una parte es la matriz de estructura y la otra parte es la operación de adición de construcción de bordes.

struct EDGE{
    
    
	int v,w,next;
}e[N<<1];

Los 'v, w, next' almacenados en la matriz de estructura son, respectivamente, el borde al que apunta, el peso del borde y el número del borde anterior leído desde un punto fijo como punto de partida.

void add(int u,int v,int w)
{
    
    
	e[tot++].v=v;//将指向的边存进去。这里注意一个点,此时是新的一条边,cnt要++;
	e[tot].w=w;//将当前的边的边权存进去
	//下面两步是最为核心的两步。
	e[tot].next=head[u];
	//我们说了,next数组存的是以某个定点为起点,读的上一条边的编号。head数组里记录的是以某个点为起点,
	//我读进去的最后一条边的编号。想一下,此时的e[tot]的这条边还没有加进去,所以此时的e[tot]的数组的
	//上一条边的编号就是我head数组存的最后一条边的编号。所以我得e[tot].next=head[u]就行啦!
	head[u]=tot;
	//此时我已经读进去了新的一条边,那此时head最后指向的是不是就是当前的边?就是此时的cnt呀,我直接赋
	//值给head[u]就行
}

Huh ~ Esta es la idea + código de la estrella delantera encadenada. El blogger piensa que es más detallada. Mientras escribía, también acarició sus propias ideas, por lo que adoptó el método más torpe. ¡A continuación, les explicaré la matriz de adyacencia!

3. Matriz de adyacencia

Matriz, tan pronto como escuche el nombre, probablemente pueda adivinar que es una matriz bidimensional (quiero mencionar aquí, quien piense que es una matriz unidimensional no necesita aprenderlo, su cerebro también lo es). estúpido... como yo ... . )
Alejarse, retirarse~ Pero esta no es una simple matriz bidimensional. Cuando no hay límites, los números '1' y '0' almacenados en la matriz, como para ¿Por qué hay dos números almacenados? Espere. Le explicaré que para gráficos con pesos de borde, los pesos de borde se almacenan en nuestra matriz.
A diferencia de la estrella delantera encadenada, la matriz de adyacencia necesita considerar gráficos dirigidos, gráficos no dirigidos y gráficos ponderados... pero la idea es un poco más simple que la de la estrella delantera, los cuales son gráficos densamente almacenados.
Consideremos desde la perspectiva de gráficos dirigidos y no dirigidos (1) Gráficos dirigidos:
para gráficos dirigidos, voy del punto i al punto j y del punto j al punto i El punto es Dos caminos completamente diferentes, si no se agregan al gráfico con anticipación, no se pueden tomar sin una declaración previa, también puede entenderse como e [i] [j]! = e [j] [i]; (2
) Gráfico no dirigido:
Un gráfico no dirigido es completamente diferente de un gráfico dirigido. Si digo que hay un borde para ir de i a j, entonces es factible para mí ir de i a j y de j a i, lo cual es comprensible. Conviértete en e[i][j]==e[j][i];
Después de hablar de grafos dirigidos y no dirigidos, llega el tema del derecho y no derecho. Antes de hablar de esto, hablemos de cómo usar un dos- ¿Matriz dimensional para almacenar pesos de borde o el '0' '1' mencionado anteriormente?
Como todos sabemos, el método de escritura de una matriz bidimensional es a [i] [j], luego asumimos que hay un lado con un peso lateral de 4 desde el segundo lado hasta el tercer lado, entonces podemos usar e[2][
3 ] almacena un valor de 4, si queremos verificar a qué lado apunta a qué lado, ¿podemos usar bucles for dobles para ver sus valores i y j? Como en la imagen de abajo.

#include<iostream>
using namespace std;
int main()
{
    
    
	int m;
	int u,v,w;
	int e[10][10];
	for(int i=0;i<m;i++)
	{
    
    
		cin>>u>>v>>w;
		e[u][v]=w;
	}
	return 0;
}

En el código anterior, podemos ver que nuestros dos puntos son la base para encontrar su peso de borde. Si desea consultar el peso de borde de 2-3 en el título, puede generar directamente e [2] [3]
. Por supuesto, este es solo el código para gráficos dirigidos y ponderados. Para gráficos no dirigidos y ponderados, solo necesita construir una arista a la inversa después de e [u] [v] = w.
Después de hablar de la gráfica con pesos, ¿cómo escribir la gráfica sin pesos?
Nuestra idea es que si hay un borde desde el punto ij, entonces asignamos el valor de e [i] [j] a 1. Después de ingresarlo una vez, recorremos la matriz e nuevamente y todos los valores en ella no son 1. El punto significa que no hay aristas desde ij, por lo que todos los valores sin aristas en el medio se asignan a 0.
Debido a que no hay código aquí, i y j se han mencionado muchas veces. Los estudiantes que no entiendan pueden ver la explicación del código a continuación.

#include<iostream>
using namespace std;
const int N=10005;
int e[N][N];
int main()
{
    
    
	int m;//m条边
	for(int i=0;i<m;i++)
	{
    
    
		int u,v;//说明从u-v有一条边
		e[u][v]=1;//其值赋为1
	}
	for(int i=1;i<=m;i++)
	{
    
    
		for(int j=1;j<=m;j++)
		{
    
    
			if(e[i][j]!=1) e[i][j]=0;//!=1说明之前没有输入过,说明i-j没有边,赋为0;
		}
	}
	return 0;
}

El método de procesamiento del gráfico no dirigido no ponderado es aproximadamente el mismo que el método de procesamiento del gráfico no dirigido ponderado anterior, por lo que no entraré en detalles aquí.

3. Lista de adyacencia

La lista de adyacencia es buena para almacenar gráficos dispersos. Se utiliza principalmente para reemplazar la matriz de adyacencia para almacenar algunos gráficos que consumirían mucha complejidad de espacio con la matriz de adyacencia. Sin embargo, los bloggers no tienen mucho contacto con ella, por lo que se omite aquí. . . Según mi propia experiencia en resolución de problemas, a menos que sea muy desagradable, no me quedaré atrapado en el espacio, siempre que sea suficiente usar una matriz de adyacencia.
Si la comprensión del seguimiento es exhaustiva, actualice otro problema.

No es fácil de crear, ¡no te prostituyas por nada www! ¡Dale al autor un me gusta + triple! gracias ~

Supongo que te gusta

Origin blog.csdn.net/2301_76331300/article/details/131852295
Recomendado
Clasificación