Notas de Estudio - Figuras

directorio

 

La figura implementado por adyacencia matriz

La figura implementa utilizando lista de adyacencia

BFS

La búsqueda en profundidad

camino más corto

el algoritmo de Dijkstra (de una sola fuente camino más corto)

algoritmo de Floyd (camino más corto entre dos puntos cualesquiera)

Árbol de expansión mínima

Prim cálculo complejidad 0 (n ^ 2)

O complejidad algoritmo de tiempo (eloge) de Kruskal


La figura implementado por adyacencia matriz

La figura implementado adyacencia matriz de estructura se define como

typedef struct graph *Graph;    //Graph是一个类型,为graph型指针
struct graph
{
    WItem NoEdge;//无边标记
    int n;        //顶点数
    int e;        //边数
    WItem **a;    //邻接矩阵,a是一个二级指针
}AWDgraph;

GraphInit Función (n, noEdge) para crear un vértices aislados de la n

Graph GraphInit(int n,WItem noEdge) //返回指向一个图的指针
{
    Graph G=malloc(sizeof*G);    //G是变量名,sizeof要加*
    G->n=n;
    G->e=0;
    G->a=Make2DArray(G->n+1,G->n+1,noEdge);    //创建一个权值全为noEdge的矩阵
    //不赋权图将上一句的NoEdge改为0
    return G;
}

GraphVerticles de función (G) y GraphEdges (G), respectivamente devolver el número de vértices y aristas de un gráfico de G

int GraphVerticles(graph G)
{
    return G->n;
}

int GraphEdges(graph G)
{
    return G->e;
}

GraphExits de función (i, j, G) se determina en el gráfico de borde actual G (i, j) la presencia o ausencia

int GraphExits(int i,int j,graph G)
{
    if(i<1||j<1||i>G->n||j>G->n||G->a[i][j]==G->NoEdge) return 0;
    //输入不在合法范围内或该边值为NoEdge
    //不赋权图把if条件中的NoEdge改为0
    return 1;
}

Función GraphAdd (i, j, w, G) unirse a borde en G (i, j)

void GraphAdd(int i,int j,WItem w,Graph G)
{
    if(i<1||j<1||i>G->n||j>G->n||i==j||G->a[i][j]!=G->NoEdge)
    //若输入不在合法范围或在对角线上或该边已经存在,则报错
    //不赋权图把if条件中的NoEdge改为0
        Error("Bad input");
    G->a[i][j]=w;
  //G->a[j][i]=w;    无向图加一句这个
  //不赋权图只需要将上述语句的w改成1
    G->e++;    //更新边数
}

GraphDelete Función (i, j, G) elimina el borde (i, j) en G

void GraphDelete(int i,int j,graph G)
{
    if(i<1||j<1||i>G->n||j>G->n||G->a[i][j]==G->NoEdge)
    //输入不在合法范围内或待删边本不存在
    //不赋权图把if条件中的NoEdge改为0
        Error("Bad input");
    G->a[i][j]=NoEdge;
  //G->a[j][i]=NoEdge;    无向图加一句这个
  //不赋权图只需要将上述语句的w改成0
    G->e--;    //更新边数
}

Grado de entrada de función (i, G) devuelve el grado de vértices de gráfico G

int InDegree(int i,graph G)
{
    int sum=0;
    /*可单独作为求入度的方法*/
    for(int j=0;j<G->n;j++)
    {
        if(G->a[i][j]!=NoEdge)   //无向图改NoEdge为0
            sum++;
    }
    /*如果是无向图加上以下代码*/
    /*也可单独作为求出度的方法*/
    for(int j=0;j<G->n;j++)
    {
        if(G->a[j][i]!=NoEdge)    //无向图改NoEdge为0
            sum++;
    }
    /**/
    return sum;
}

La figura implementa utilizando lista de adyacencia

adyacencia nodo de la lista de estructura de definición

typedef struct lnode *glink;    //glink是一个类型,为lnode型指针
struct lnode
{
    int v;    //边的另一个顶点
    glink next;    //邻接表指针
  //若是赋权图,加上w属性
  //WItem w;
};

Crear una nueva lista de nodos de adyacencia

glink NewLNode(int v,glink next)    //返回指向lnode的指针
{
    glink x=malloc(sizeof*x);    //x是变量名,sizeof取变量名长度要加*
    x->v=v;
    x->next=next;
  //若是赋权图
  //x->w=w;
    return x;
}

La figura implementa utilizando la estructura de la tabla adyacente definido

typedef struct graph *Graph;
struct graph
{
    int n;    //顶点数
    int e;    //边数
    glink *adj;    //glink型的一维数组,数组中的成员都是指针
}Lgraph;

GraphInit Función (n) para crear una tabla representada por adyacencia con n vértices figura aislado

Graph GraphInit(int n)
{
    Graph G=malloc(sizeof*G)     //G是变量名,sizeof前加*
    G->n=n;
    G->e=0;
    G->adj=malloc(n+1)*sizeof(glink))    //adj是一个指针数组,成员都是glink指针,v此时是0
    for(int i=0;i<=n)
        G->adj[i]=0;
    return G;
}

GraphVerticles de función (G) y funciones GraphEdge (G) devuelven el número de vértices y aristas con la redacción de matriz de adyacencia figura ligeramente.

Función GraphExist (i, j, G) determinar si existe actualmente un borde en el gráfico G (i, j)

int GraphExist(int i,int j,graph G)

{
    if(i<1||j<1||i>G->n||j>G->n) return 0;
    glink p=G->adj[i];
    while(p&&p->v!=j) p=p->next;    //不走到最后且不为目标,则继续向前
    if(p) return 1;
    else return 0;
}

Función GraphAdd (i, j, G) se añadió a alcanzar la cifra de un borde (i, j) es operado por primera inserción de un vértice j de la adyacente vértice i ejemplar

void GraphAdd(int i,int j,Graph G)    //赋权图加上WItem w
{
    if(i<1||j<1||i>G->n||j>G->n||i==j||GraphExits(i,j,G))
        Error("Bad input");
    G->adj[i]=NewLNode(j,G->adj[i]);    //直接取代G->a[i]
  //无向图加上下一句
  //G->adj[j]=NewLNode(i,G->adj[j]);
  //赋权图加上w
  //G->adj[i]=NewLNode(j,w,G->adj[i]);
    G->e++;
}

GraphDelete Función (i, j, G) para borrar el gráfico borde G (i, j)

void GraphDelete(int i,int j,Graph G)
{
    glink p,q;
    if(i<1||j<1||i>G->n||j>G->n||!GraphExists(i,j,G))
    {
        Error("Bad input");
    }
    p=G->adj[i];
    if(p->v==j)    //如果第一个节点就是待删除节点,直接令其成为邻接表数组中的成员
    {
        G->adj[i]=p->next;
        free(p);
    }
    else
    {
        while(p&&p->v!=j) p=p->next;    //若未走到最后且未找到目标则继续向前
        if(p)    //若找到目标
        {
            q=p->next;
            p->next=q->next;
            free(q);
        }
    }
  //有向图加上下面的代码
  /*
    p=G->adj[j];
    if(p->v==i)    //如果第一个节点就是待删除节点,直接令其成为邻接表数组中的成员
    {
        G->adj[j]=p->next;
        free(p);
    }
    else
    {
        while(p&&p->v!=i) p=p->next;    //若未走到最后且未找到目标则继续向前
        if(p)    //若找到目标
        {
            q=p->next;
            p->next=q->next;
            free(q);
        }
    }
    */

    G->e--;
}

Grado de salida de función (i, G) calculado por la lista de adyacencia de vértice i larga, hay un retorno al vértice de la gráfica G

int OutDegree(int i,Graph G)
{
    glink p;
    int sum=0;
    if(i<1||i>G->n) Error("Bad input");
    p=G->adj[i];
    while(p)
    {
        sum++;
        p=p->next;
    }
    return sum;
}

Grado de entrada de función (i, G) vuelve a tener el grado de vértice i de la gráfica G

int InDegree(int i,Graph G)
{
    int sum=0;
    for(int j=0;j<G->n;j++)
    {
        if(GraphExists(i,j,G))
            sum++;
    }
    return sum;
}

BFS

//用邻接矩阵实现的无向图G中的广度优先搜索算法bfs描述
bfs(G,i)
{
    /*从顶点v开始,广度优先搜索图G的算法*/
    标记顶点i;
    用顶点i初始化顶点队列Q;
    while(!QueueEmpty(Q))
    {
        i=DeleteQueue(Q);
        设j是i的邻接顶点;
        while(j)
        {
            if(j未标记)
            {
                标记顶点j;
                EnterQueue(j,Q);
            }
            j=i的下一个邻接顶点
        }
    }
}

===================================================================
//具体实现时,用一个数组pre来记录搜索到的顶点的状态。初始时对所有顶点v有pre[v]=0。
//用一全局变量cnt记录算法对图中顶点的访问次序。算法结束后,数组pre[i]中的值是算法访问顶点i的序号。


void bfs(Graph G,int i)
{
    Queue Q=QueueInit();
    EnterQueue(i,Q);    //顶点先入队
    while(!QueueEmpty(Q))
    {
        if(pre[i=DeleteQueue(Q)]==0)    //未访问过
        {
            pre[i]=cnt++;    //访问该结点并标记
            for(int j=1;j<=G->n;j++)
            {
                if(G->adj[i][j]&&pre[j]==0)    //若边存在且未访问过,入队
                    EnterQueue(j,Q);
            }
        }
    }
}

//图中可能不止一个连通分量,遍历全图算法如下

void GraphSearch(Graph G)
{
    cnt=1;
    for(int i=1;i<=G->n;i++) pre[i]=0;
    for(int i=1;i<=G->n;i++)
    {
        if(pre[i]==0)bfs(G,i);    //对每个连通分量调用一次bfs
    }
}
//天勤上面用邻接表表示图的bfs写法
int visit[MAXSIZE]=0;    //访问状态数组
void bfs(Graph *G,int v)
{
    ArcNode *p;
    visit[v]=1;
    //Visit(v);
    Queue<int> q;
    q.push(v);
    while(!IsEmpty(q))
    {
        int t=q.top();
        q.pop();
        p=G->adj[t].firstarc;    //p指向当前结点第一条边
        while(p)
        {
            if(visit[p->adjvex]==0)
            {
                visit[p->adjvex]=1;
                //Visit(p->adjvex);
                q.push(p->adjvex);    //若当前邻接顶点未被访问过,则置为已访问,并压入队列
            }
            p=p->nextarc;    //否则,p指向当前结点的下一条邻边
        }
    }
}
void BFS(Graph *G)
{
    for(int i=0;i<G->n;i++)
        if(visit[i]==0)
            bfs(G,i);
}

 

La búsqueda en profundidad

//用邻接矩阵实现的无向图G中的深度优先搜索算法dfs如下
void dfs(Graph G,int i)
{
    pre[i]=cnt++;    //初始化时所有结点pre[i]=0,当pre[i]不为0使表示该结点已访问过,pre[i]的值为算法访问结点i的序号
    for(int j=1;j<=G->n;j++)    //顺序遍历与结点i相邻的结点,
    {
        if(G->[i][j])    //若边<i,j>存在
        {
            if(pre[j]==0)dfs(G,j);    //若结点j还未被访问过,对j递归调用dfs,若访问过,j++探测下一个相邻结点
        }
    }
}

//用邻接表实现的有向图G中的深度优先搜索算法dfs如下
void dfs(Graph G,int i)
{
    glink p;
    pre[i]=cnt++;
    for(p=G->adj[i];p;p=p->next)
    {
        if(pre[i]==0)dfs(G,p->v);    //若p指向的结点已访问过,结束当前层次的递归,返回上一层递归,执行p=p->next探测下一个相邻结点
    }   
}

void GraphSearch(Graph G)
{
    cnt=1;
    for(int i=1;i<=G->n;i++) pre[i]=0;
    for(int i=1;i<=G->n;i++) if(pre[i]==0) dfs(G,i);
}
//天勤上面用邻接表表示图的dfs写法
int visit[MAXSIZE]=0;    //全局变量用来保存访问状态
int dfs(Graph *G,int v)
{
    ArcNode *p;
    visit[v]=1;    //置当前结点为已访问
    Visit(v);
    p=G->adj[v].firstarc;    //p指向顶点v的第一条边
    while(p)
    {
        if(visit[p->adjvex])==0    //若当前结点未被访问过,则往深处继续访问
        {
            dfs(G,p->adjvex)
        }
        p=p->nextarc;    //否则检测下一个与v邻接的结点
    }    //执行到这一步时,所有与v邻接的结点已经检查完毕,该层dfs也执行到了最后一句,自动返回上一层递归
}
void DFS(Graph *G)
{
    for(int i=0;i<G->n;i++)
        if(visit[i]==0)
            dfs(G,i);
}

 

//天勤上判断图G是否是树的算法,基于dfs
int vc=0,ec=0;    //定义全局变量vc和ec,就不用在函数里面传了
int visit[MAXSIZE]=0;
void dfs(Graph *G,int v)
{
    ArcNode *p;
    visit[v]=1;    //置当前结点为已访问
    vc++;    //结点数自增1
    p=G->adj[v].firstarc;
    while(p)
    {
        if(visit[p->adjvex]==0)    //若当前顶点的邻接点未被访问过,则访问它,并对ec自增1
        {
            ec++;
            dfs(G,p->adjvex);
        }    
        p=p->next;
    }
}

int IsTree(Graph *G)
{
    dfs(G,1);
    if(vc==G->n&&(ec/2)==G->e)    //若vc等于图中顶点数,ec等于图中边数的2倍
        return 1;
    return 0;
}
//由于每次访问顶点ec都会累加上之前所有与访问过的结点关联的边数,因此遍历完之后,相当于ec中的数值是图的度数,(一条边2个度),因此ec/2就是访问过的边数。

camino más corto

el algoritmo de Dijkstra (de una sola fuente camino más corto)

la idea del algoritmo:

Establecer un conjunto de vértices S, y seguir ampliando esta colección tan codicioso. Un vértice que pertenece al conjunto S si y sólo si la fuente tiene la longitud de la trayectoria más corta desde el vértice. Inicial, S contiene única fuente. Sea u G es un vértice de la trayectoria a través del vértice S de la fuente a ser una ruta especial de la fuente a solamente U y U intermedio, y se trató con dist especial matriz para registrar la longitud del camino más corto correspondiente a cada uno del vértice actual. Dijkstra algoritmo para cada vértice u se retira de la VS tiene la longitud del camino más corto especial, u se añade al conjunto S, mientras que la matriz DIST hacer los cambios necesarios. Una vez V S contiene todos los vértices, dist en el registro de la longitud del camino más corto entre la otra desde el vértice fuente a todos.

Descripción algoritmo:

Paso 1: Inicialización dist [v] = a [s] [v]

             Para todos los vértices adyacentes V a pre opuesto s [v] = s;

             Por otro vértice u pre conjunto [u] = 0;

             Tabla L contiene todos los pre establecido [v] ≠ vértice v 0 es el tiempo inicial @ es decir, L s es la fuente directamente vértices adyacentes

Paso 2: Si lista vacía L, a continuación, los extremos de algoritmo, de lo contrario, ir al Paso 3

Paso 3: Eliminar el valor mínimo de dist es decir, el vértice fuente v // s último de la lista de vértice L

Paso 4: Para todos los vértices adyacentes al vértice v u oponerse a dist [u] = min {dist [u], dist [v] + a [v] [u]}

             Si dist cambio [u], es decir, después de la adición de camino especial vértice v es más corto, el conjunto pre [u] = v; y si no en la lista L u, se añade L u; vaya al paso 2

//在用邻接矩阵实现的赋权有向图中,单源最短路径问题的Dijkstra算法实现如下
void Dijkstra(int s,WItem dist[],int prev[],Graph G)
{
    int i,j;
    List L=ListInit();    //初始化L表
    if(s<1||s>G->n) Error("Out of bounds")    //处理非法输入
    /*初始化dist,prev和L*/
    for(int i=1;i<=G->n;i++)
    {
        dist[i]=a[s][i];    //顶点i到源点s的初始距离为a[s][i]的值
        if(dist[i]==G->NoEdge) prev[i]=0;    //若顶点i与源点s之间不存在边,则置i的前驱结点为0
        else{prev[i]=s;ListInsert(0,i,L);}    //否则,置i的前驱结点为s,并将顶点i加入L表,参数啥意思?
    }
    dist[s]=0;    //源点s的前驱为0
    /*修改dist和prev*/
    while(!ListEmpty(L))
    {
        /*找L中具有最小dist值得顶点v*/
        /*将顶点v从表L中删除,并修改dist的值*/
        i=ListDelMin(L,dist);    //顶点i是L表中所有已知特殊路径长度的结点中路径最短的
        for(int j=1;j<=G->n;j++)    //遍历所有与顶点i相邻的顶点
        {
            if(G->a[i][j]!=G->NoEdge&&(!prev[j]||dist[j]>dist[i]+G->a[i][j]))    //若边(i,j)存在,且加入结点i之后,结点j到源点s的距离缩短
            {
                /*dist减少*/
                dist[j]=dist[i]+G->a[i][j];    //更新结点j到源点s的特殊路径距离
                /*顶点j插入表L*/
                if(!prev[j]ListInsert(0,j,L))    //结点j的特殊路径长度已知,加入表L
                prev[j]=i;    //更新结点j的前驱
            }
        }
    }
}
//天勤上的写法,我觉得更好理解一些
void Dijkstra(Graph G,int v,int dist[],int path[])    //dist是v到某点vu的距离,path是vu到v最短路径上前驱结点的下标,dist是一维数组,因为将它看作二维数组时,有一维是不变的,下标都是v
{
    int sex[MAXSIZE];    //set记录顶点是否被加入路径,取值为1则为加入,0为未加入

    /*以下是对各数组进行初始化*/
    for(int i=0;i<G.n;i++)
    {
        dist[i]=G.edges[v][i];
        path[i]=v;
        set[i]=0;
    }
    set[v]=1;
    /*初始化完毕*/

    /*以下是找到剩余结点中与已生成的路径距离最短的结点*/
    int min=INF;
    for(int i=0;i<G.n;i++)
    {
        if(set[i]==0&&dist[i]<min)
        {
            u=i;
            min=G.dist[i];
        }
    }
    set[u]=1;
    /*找到该结点后,加入路径中*/

    /*加入顶点u到路径中之后,更新dist和path*/
    for(int i=0;i<G.n;i++)
    {
        if(set[i]==0&&dist[u]+G.edges[u][i]<dist[i])
        {
            dist[i]=dist[u]+G.edges[u][i];
            path[i]=u;    //u为i在路径上的前驱
        }
    }
}

 

algoritmo de Floyd (camino más corto entre dos puntos cualesquiera)

la idea del algoritmo:

Dispuestos en una matriz c, inicialmente c [i] [j] = a [i] [j]. A continuación, el c-matriz hacer n iteraciones, después de la primera iteración k, c [i] [j] es un valor de vértice i al vértice j, y no pasa a través de la longitud de la trayectoria intermedia es mayor que el número k de vértices. Al hacer la k-ésima iteración en c, c [i] [j] = min {c [i] [k] + c [k] [j], c [i] [j]}, para calcular c [i ] [j] puede compararse con la corriente c [i] [j] y c [i] [k] + c [k] [j] tamaño. c actual [i] [j] valor indica desde el vértice i a j, los números de vértices intermedios no es mayor que k-1 más corta longitud de la trayectoria, y c [i] [k] + c [k] [j] denota el i vértice a k, a continuación, a partir de k para j, y no pasa a través de la longitud de la trayectoria intermedia es mayor que el número de los vértices k.

ruta matriz bidimensional se utiliza para registrar el camino más corto. Cuando k es la manipulación c [i] [j] para obtener un número entero de un valor mínimo, se establece en p [i] [j] = k. Cuando el camino [i] [j] = 0, representa la ruta más corta desde el nodo i a j es el borde de i a j. Después de calcular el c [i] [j] de valor, fácilmente registrada por la información de la ruta para encontrar el camino más corto correspondiente.

void Floyd(WItem **c,int **path,Graph G)
{
    /*初始化c[i][j]*/
    for(int i=1;i<=G->n;i++)
        for(int j=1;j<=G->n;j++)
        {
            if(i==j)
                c[i][j]=0;
            else
            { 
                c[i][j]=G->a[i][j];
                path[i][j]=0;    //path=0表示当前顶点i到顶点j的最短路径就是它们之前的边
            }
        }
    for(int k=1;k<=G->n;k++)
        for(int i=1;i<=G->n;i++)
            for(int j=1;j<G->n;j++)
            {
                if(c[i][k]!=NoEdge&&c[k][j]!=NoEdge&&(c[i][j]==NoEdge||c[i][j]>c[i][k]+c[k][j]))    
                //确保加入的顶点k与顶点i,顶点k与顶点j之前是可达的,当顶点i到顶点j无边或小于顶点i到k加上顶点k到j的距离时,更新顶点i到j的路径长度
                {
                    c[i][j]=c[i][k]+c[k][j];
                    p[i][j]=k;    //加入的点k是使c[i][j]取最小值的数
                }
            }
}

Árbol de expansión mínima

Prim cálculo complejidad 0 (n ^ 2)

la idea del algoritmo:

Primer conjunto S = {1} y, a continuación, siempre y cuando S es un subconjunto de V (que es, sin embargo, no contiene todos los nodos), para ser codicioso seleccionado como sigue: Seleccionar el punto i conjunto S, VS en el punto j, y una [I] [j] el borde más pequeño y el vértice añadido al conjunto S j. Este tipo de proceso a la alimentación S = V hacia arriba. (No se requiere para juzgar si un bucle, porque los dos lados de los vértices de diferentes sets)

Cómo averiguar el estado de i y j, tenemos que establecer dos conjuntos de armario y de bajo coste. Para vértices j de un VS, más cercano [j] es adyacente a un vértice S j en la que J y K otros vértices adyacentes en S se comparan con un [j] [más cercano [j]] <= a [j] [k]. lowcost [j] es el valor de a [j] [más cercano [j]]

Prim durante la ejecución del algoritmo, para encontrar el mínimo VS manipulación lowcost vértice j, y seleccionar de la banda de matriz más cercano (j, más cercano [j]), y finalmente añadir el S, j, y más cercano a la necesaria y de bajo coste modificaciones.

void Prim(WItem *lowcost,int *closest,Graph G)
{
    /*初始化*/
    int *s;    //集合S,值为1表示在集合中,为0表示不在集合中
    s=malloc((G->n+1)*sizeof(int));
    for(int i=1;i<=G->n;i++)
    {
        lowcost[i]=a[1][i];    //先设置顶点1在S中
        closest[i]=1;
        s[i]=0;    //除1以外所有点都不在集合S中
    }
    s[1]=1;    //把顶点1加入集合S
    
    for(int i=1;i<=G->n;i++)    //执行n次
    {
        min=G->NoEdge;    //要找出最小值,先把min设为最大
        j=1;    //j用来记录到集合S距离最短的顶点序号,一开始先设为1作为初始值
        for(int k=2;k<=G->n;k++)    //k=2是因为一开始只有1在S中,V-S要从2开始
        {
            if(lowcost[k]<min)&&(!s[k])    //k到集合S最短距离小于min且k不在集合S中,即k在V-S中
            
            {
                min=lowcost[k];    //更新最小值,j为当前V-S中里S最近的顶点,现在令j为k
                j=k;
            }
        }
        //此时j是到集合S距离最短的顶点序号
        s[j]=1;    //把j加入集合S
        for(int k=2;k<=G->n;k++)    //j加入集合S后,要修改原来的closest和lowcost
        {
            if((G->a[k][j]<lowcost[k])&&(!s[k]))    //若K不在集合S且顶点j和k之间距离小于j加入集合S前顶点k到集合S的最短距离
            {
                //更新closest,lowcost
                closest[k]=j;
                lowcost[k]=G->a[k][j]
;            }
        }
    }
}

//V-S中的顶点为焦点向S中的顶点逐个连线找最短,j是通过k来更新的
//利用closest还能找到最短路径
//while(k>0)
//p=closest[k];
//k=p;

O complejidad algoritmo de tiempo (eloge) de Kruskal

En primer lugar, los n vértices de G n como una comunicación rama aislado. Todas las partes en peso de pequeño a grande, a partir de los primeros bordes, cada una vista lateral en orden ascendente del lado derecho, cuando se observa el borde de la k-ésimo (v, w), V y W si los puntos finales son Apex actual dos componentes conectados diferentes T1 y T2, a la orilla uso (v, w) está conectado a la T1 y T2 conectado componente, y luego continuar para ver el lado de la k + 1, o directamente acceder a la k + 1 lado, el proceso continúa hasta que sólo un tiempo hasta que el componente conectado.

La configuración descrita anteriormente Kruskal expansión mínima algoritmo de árbol requiere G Véase la Fig orden ascendente de pesos de todos los bordes. Esto requiere que todos los bordes laterales G ordenados por peso. Definición de la estructura se almacena en cada borde:

typedef struct edge
{
    int u;
    int v;
    WItem w;
}Edge;

/*函数EDGE(u,v,w)创造一条权威w的边(u,v)*/
Edge EDGE(int u,int v,WItem w)
{
    Edge e;
    e->u=u;
    e->v=v;
    e->w=w;
    return e;
}
/*函数Edges(a,G)抽取图G的所有边到赋权边数组a中,并返回图G的边数*/
int Edges(Edges a[],Graph G)
{
    int k=0;
    for(int i=1;i<=G->n;i++)
        for(int j=1;j<=G->n;j++)
            if(G->a[i][j]!=G->NoEdge)
                a[k++]=EDGE(i,j,G->a[i][j]);
    return k;
}

void Kruskal(Edge mst[],Graph G)
{
    Edge a[maxE];
    UFset U;    //并查集u
    int e=Edges(a,G);    //抽取G的所有边,e为边数
    quicksort(a,0,e-1);    //对边数组a排序,参数意义为对数组a从元素0到元素e-1进行排序
    U=UFinit(G->n);    //初始化并查集U
    for(int i=0,int k=0;i<e&&k<G->n-1;i++)    //k记录循环次数,执行n-1次结束
    {
        int s=UFind(a[i].u,U);    //a[i].u是当前最短边的一个端点,找出它所属的连通分支
        int t=UFind(a[i].v,U);    //a[i].v是当前最短边的另一个端点,找出它所属的连通分支
        if(s!=t)    //若s和t不是同一个连通分支
        {
            mst[k++]=a[i];    //更新最小生成树
            UFunion(s,t,U);    //合并连通分支s和t
        }
    }
    
}

 

Publicado 35 artículos originales · ganado elogios 2 · Vistas 1390

Supongo que te gusta

Origin blog.csdn.net/weixin_41001497/article/details/101385955
Recomendado
Clasificación