用邻接矩阵创建无向图,实现DFS+BFS

由于图的复杂结构,其物理位置与逻辑位置并不匹配,不能用一维数组来存储图。可考虑用一维数组来存储图的结点信息,二维数组来存储节点间的关系,这种存储方式就叫做邻接矩阵。

图的结点结构定义:

typedef struct
{
    char vexs[ MVNum ] ;//存储结点信息
    int arcs[ MVNum ][ MVNum ] ; //存储权值
    int vexnum , arcnum ;//定义图的节点个数和边的条数
}AMGraph ;

查找结点元素在vexs[]数组中的下标:

int LocateVex( AMGraph G , char ch )
{
    int i ;
    for( i = 0 ; i < G.vexnum ; i++ )
        if( ch == G.vexs[ i ] )
            break ;
    return i ;

}

创建图:

在创建图的过程中,如果结点信息是字符,且用scanf()函数从键盘读取的话,一定要用getchar()将键盘输入后的回车键吸收。这是因为当用户按下回车键时,回车符还在缓冲区内,当下一次调用scanf()时,程序会读取缓冲区内遗留的回车符。关于scanf()的更加详细的解释:C语言scanf函数用法详细解释!

Status CreateUDN( AMGraph *G )
{
    int i , j ;
    printf( "请输入结点个数:" ) ;
    scanf( "%d" , &G->vexnum ) ;
    getchar() ;

    for( i = 0 ; i < G->vexnum ; i++ )
    {
        printf( "请输入第%d个结点的信息:" , i+1 ) ;
        scanf( "%c" , &G->vexs[ i ] ) ;
        getchar() ;
    }

    for( i = 0 ; i < G->vexnum ; i++ )
        for( j = 0 ; j < G->vexnum ; j++ )
            G->arcs[ i ][ j ] = MaxInt ;

    printf( "请输入边的条数:" ) ;
    scanf( "%d" , &G->arcnum ) ;
    getchar() ;

    for( i = 0 ; i < G->arcnum ; i++ )
    {
        int w ;
        char a , b ;
        printf( "请输入两个结点以及两节点间的边的权值:" ) ;
        scanf( "%c %c %d" , &a , &b , &w ) ;
        getchar() ;

        G->arcs[ LocateVex( *G , a ) ][ LocateVex( *G , b ) ] = w ;
        G->arcs[ LocateVex( *G , b ) ][ LocateVex( *G , a ) ] = w ;

    }
    return OK ;
}

邻接矩阵实现DFS算法:

DFS就相当于树的前序遍历。

用visited[]数组来标志结点是否已被遍历过。

void DFS( AMGraph G , int i )
{
    int j ;
    visited[ i ] = TRUE ;
    printf( "%c " , G.vexs[ i ] ) ;

    for( j = 0 ; j < G.vexnum ; j++ )
        if( !visited[ j ] && G.arcs[ i ][ j ] < MaxInt && G.arcs[ i ][ j ] > 0 )
            DFS( G , j ) ;
}

void DFSTraverse( AMGraph G )
{
    int i ;
    for( i = 0 ; i < G.vexnum ; i++ )
        visited[ i ] = FALSE ;

    for( i = 0 ; i < G.arcnum ; i++ ) 
        if( !visited[ i ] )
            DFS( G , i ) ;
}

这里对每个结点都实现DFS可以避免不能遍历非连通图的情况。

邻接矩阵实现BFS算法:

BFS算法需借助于队列来实现,其基本思想是:遍历第一个结点,并将其入队之后,再把它出队,然后把与这个结点相连的所有结点都入队,每遍历一次都进行这样的操作,BFS就相当于树的层序遍历

void BFSTraverse( AMGraph G )
{
    char temp ;
    int i , j ;
    Queue Q ;
    InitQueue( &Q ) ;
    for( i = 0 ; i < G.vexnum ; i++ )
        visited[ i ] = FALSE ;

    for( i = 0 ; i < G.vexnum ; i++ )
    {
        if( !visited [ i ] )
        {
            visited[ i ] = TRUE ;
            printf( "%c " , G.vexs[ i ] ) ;
            EnQueue( &Q , G.vexs[ i ] ) ;

            while( !EmptyQueue( Q ) )
            {
                DeQueue( &Q , &temp ) ;
                for( j = 0 ; j < G.vexnum ; j++ )//将与刚刚遍历过的结点相连的结点都入队
                {
                    if( G.arcs[ i ][ j ] < MaxInt && G.arcs[ i ][ j ] > 0 && !visited[ j ] )
                    {
                        visited[ j ] = TRUE ;
                        printf( "%c " , G.vexs[ j ] ) ;
                        EnQueue( &Q , G.vexs[ j ] ) ;
                    }
                }
            }
        }
    }
    printf( "\n" ) ;
}

判断队列已满和入队与出队的操作比较简单,这里就不一一列出。

附上源代码:

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

#define MVNum 100
#define MaxInt 32767
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0

typedef char VerTexType ;
typedef int ArcType ;
typedef int Status ;
typedef int Boolean ;

typedef struct
{
    VerTexType vexs[ MVNum ] ;
    ArcType arcs[ MVNum ][ MVNum ] ;
    int vexnum , arcnum ;
}AMGraph ;

typedef struct
{
    char *base ;
    int front ;
    int rear ;
}Queue ;

Boolean visited[ MaxInt ] ;

Status CreateUDN( AMGraph *G ) ;
void DFS( AMGraph G , int i ) ;
void DFSTraverse( AMGraph G ) ;
int LocateVex( AMGraph G , char ch ) ;

void InitQueue( Queue *Q ) ;
int EmptyQueue( Queue Q ) ;
int EnQueue( Queue *Q , char ch ) ;
int DeQueue( Queue *Q , char *ch ) ;
void BFSTraverse( AMGraph G ) ;

int main( void )
{
    AMGraph G ;
    CreateUDN( &G ) ;
    DFSTraverse( G ) ;
    BFSTraverse( G ) ;
    return 0 ;
}

int LocateVex( AMGraph G , char ch )
{
    int i ;
    for( i = 0 ; i < G.vexnum ; i++ )
        if( ch == G.vexs[ i ] )
            break ;
    return i ;

}

Status CreateUDN( AMGraph *G )
{
    int i , j ;
    printf( "请输入结点个数:" ) ;
    scanf( "%d" , &G->vexnum ) ;
    getchar() ;

    for( i = 0 ; i < G->vexnum ; i++ )
    {
        printf( "请输入第%d个结点的信息:" , i+1 ) ;
        scanf( "%c" , &G->vexs[ i ] ) ;
        getchar() ;
    }

    for( i = 0 ; i < G->vexnum ; i++ )
        for( j = 0 ; j < G->vexnum ; j++ )
            G->arcs[ i ][ j ] = MaxInt ;

    printf( "请输入边的条数:" ) ;
    scanf( "%d" , &G->arcnum ) ;
    getchar() ;

    for( i = 0 ; i < G->arcnum ; i++ )
    {
        int w ;
        char a , b ;
        printf( "请输入两个结点以及两节点间的边的权值:" ) ;
        scanf( "%c %c %d" , &a , &b , &w ) ;
        getchar() ;

        G->arcs[ LocateVex( *G , a ) ][ LocateVex( *G , b ) ] = w ;
        G->arcs[ LocateVex( *G , b ) ][ LocateVex( *G , a ) ] = w ;

    }
    return OK ;
}

void DFS( AMGraph G , int i )
{
    int j ;
    visited[ i ] = TRUE ;
    printf( "%c " , G.vexs[ i ] ) ;

    for( j = 0 ; j < G.vexnum ; j++ )
        if( !visited[ j ] && G.arcs[ i ][ j ] < MaxInt && G.arcs[ i ][ j ] > 0 )
            DFS( G , j ) ;
}

void DFSTraverse( AMGraph G )
{
    int i ;
    for( i = 0 ; i < G.vexnum ; i++ )
        visited[ i ] = FALSE ;

    for( i = 0 ; i < G.arcnum ; i++ )
        if( !visited[ i ] )
            DFS( G , i ) ;

    printf( "\n" ) ;
}

void InitQueue( Queue *Q )
{
    Q->base = ( char * )malloc( sizeof( char ) * MaxInt ) ;
    Q->front = Q->rear = 0 ;
}

int EmptyQueue( Queue Q )
{
    if( Q.front == Q.rear )
        return TRUE ;
    else
        return FALSE ;
}

int EnQueue( Queue *Q , char ch )
{
    if( ( Q->rear + 1 ) % MaxInt == Q->front )
        return ERROR ;
    else
    {
        Q->base[ Q->rear ] = ch ;
        Q->rear = ( Q->rear +1 ) % MaxInt ;
    }
        return OK ;
}

int DeQueue( Queue *Q , char *ch )
{
    if( EmptyQueue( *Q ) )
        return ERROR ;
    else
    {
        *ch = Q->base[ Q->front ] ;
        Q->front = ( Q->front + 1 ) % MaxInt ;
    }
        return OK ;
}

void BFSTraverse( AMGraph G )
{
    char temp ;
    int i , j ;
    Queue Q ;
    InitQueue( &Q ) ;
    for( i = 0 ; i < G.vexnum ; i++ )
        visited[ i ] = FALSE ;

    for( i = 0 ; i < G.vexnum ; i++ )
    {
        if( !visited [ i ] )
        {
            visited[ i ] = TRUE ;
            printf( "%c " , G.vexs[ i ] ) ;
            EnQueue( &Q , G.vexs[ i ] ) ;

            while( !EmptyQueue( Q ) )
            {
                DeQueue( &Q , &temp ) ;
                for( j = 0 ; j < G.vexnum ; j++ )
                {
                    if( G.arcs[ i ][ j ] < MaxInt && G.arcs[ i ][ j ] > 0 && !visited[ j ] )
                    {
                        visited[ j ] = TRUE ;
                        printf( "%c " , G.vexs[ j ] ) ;
                        EnQueue( &Q , G.vexs[ j ] ) ;
                    }
                }
            }
        }
    }
    printf( "\n" ) ;
}
  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值