Connectivité minimale - (code, analyse, assemblage)

Introduction:

Un arbre couvrant d'un graphe connecté avec n nœuds est un sous-graphe connecté minimal du graphe d'origine, et contient tous les n nœuds du graphe d'origine,
et a le moins d'arêtes qui maintiennent le graphe connecté.
L'arbre couvrant minimum peut être obtenu par l'algorithme kruskal ou l'algorithme prim

L'algorithme de Prim, un algorithme de la théorie des graphes, peut rechercher l'arbre couvrant minimum dans un graphe connexe pondéré.
Dans l'arbre formé par le sous-ensemble d'arêtes recherché par cet algorithme, non seulement tous les sommets du graphe connecté sont inclus, mais toutes les arêtes ont le plus petit poids

Code:

#include <stdio.h>
#include <stdlib.h>

/*
程序描述:
矩阵有多行数据,cost数组从矩阵中提取数据,P记录cost数组的数据分别属于矩阵的哪一行
Mark记录在cost不再进行比较数据的下标(已经是最小值当前cost中最小值的下标了)
在cost数组中找出最小值与其在cost中的下标,再将该下标在mark中标记,下次不再处理这个位置
当前cost比较完成后,用找到的最小值作为下一行要提取数据的行号,然后用该行的数据与cost中的数据
比较,取每个位置较小值,除了已经标记的位置不进行提取。并修改P中对应较小值属于行
更新cost和P后,再进行在cost中找最小值同样的操作,依次循环整个矩阵
*/

#define VNUM 9
#define MV 65536

int P[VNUM];//存储要当前比较的数据是属于哪一行的
int Cost[VNUM];//要用于比较的数据的数组
int Mark[VNUM];//记录列状态,标记为1的列,将不再处理比较
int Matrix[VNUM][VNUM] =    //n行与n列数据一样的矩阵
{
    
    
    {
    
    0, 10, MV, MV, MV, 11, MV, MV, MV},
    {
    
    10, 0, 18, MV, MV, MV, 16, MV, 12},
    {
    
    MV, 18, 0, 22, MV, MV, MV, MV, 8},
    {
    
    MV, MV, 22, 0, 20, MV, MV, 16, 21},
    {
    
    MV, MV, MV, 20, 0, 26, MV, 7, MV},
    {
    
    11, MV, MV, MV, 26, 0, 17, MV, MV},
    {
    
    MV, 16, MV, MV, MV, 17, 0, 19, MV},
    {
    
    MV, MV, MV, 16, 7, MV, 19, 0, MV},
    {
    
    MV, 12, 8, 21, MV, MV, MV, MV, 0},
};
//cost 先取第一行的数据开始比较
void Prim(int sv) // O(n*n)
{
    
    
    int i = 0;
    int j = 0;
    
    if( (0 <= sv) && (sv < VNUM) )//判断sv在矩阵范围内
    {
    
    
        for(i=0; i<VNUM; i++)
        {
    
    
            Cost[i] = Matrix[sv][i];//将sv行所有列赋到cost,表示从sv行的数据开始处理比较
            P[i] = sv;//将P全部赋0,表示当前所有数据属于0行的
            Mark[i] = 0;//Mark数组全赋0,初始化
        }
        
        Mark[sv] = 1;//将0列设为1,刚开始0列不处理比较
        
        for(i=0; i<VNUM; i++)
        {
    
    
            int min = MV;
            int index = -1;
            
            for(j=0; j<VNUM; j++)
            {
    
    
                //从没有被标记数据中取值,找出cost(当前要比较的数据)中最小值和其在cost中的下标
                if( !Mark[j] && (Cost[j] < min) )
                {
    
    
                    min = Cost[j];//给最小值赋值  
                    index = j;//最小值的下标  
                }
            }
            
            if( index > -1 )//表示执行了上面,找到了最小值
            {
    
    
                Mark[index] = 1;  //将该下标进行标记,下次不再比较该列的数据
                
                printf("(%d, %d, %d)\n", P[index], index, Cost[index]); // 输出这次查找出最小值位于的行与下标与数值
            }
            
            for(j=0; j<VNUM; j++) //循环找出下一次用比较的数据
            {
    
    
				//从上次找到的最小值的下标,作为重新提取数据的行
				//只要不是被标记的列,从行中提取的数据比原来比较的数据小就取行中的数和下标
				//也用新的一行中的数据与本来用于比较的数据取对应位置较小的一方,并将该位置的值属于
				//哪一行中提取出来的,存到P中
                if( !Mark[j] && (Matrix[index][j] < Cost[j]) ) //更新到cost数组
                {
    
    
                    Cost[j]  = Matrix[index][j];//更新用来比较数据数组
                    P[j] = index;//更新数据属于的行
                }
				
            }
			
        }
    }
}

int main(int argc, char *argv[]) 
{
    
    
   Prim(0);
    
	
	getchar();
	return 0;
}

une analyse:

Insérez la description de l'image ici
Insérez la description de l'image ici
Insérez la description de l'image ici
Insérez la description de l'image ici
Insérez la description de l'image ici

compilation:

Insérez la description de l'image ici
Insérez la description de l'image ici
Insérez la description de l'image ici
Insérez la description de l'image ici
Insérez la description de l'image ici

Je suppose que tu aimes

Origine blog.csdn.net/m0_37599645/article/details/112168845
conseillé
Classement