zoukankan      html  css  js  c++  java
  • 遍历输入图的遍历

    PS:今天上午,非常郁闷,有很多简单基础的问题搞得我有些迷茫,哎,代码几天不写就忘。目前又不当COO,还是得用心记代码哦!

        

    概述

        遍历分为深度优先遍历和广度优先遍历,其对有向图和无向图都实用。深度优先,望文生义,就是只要存在后续节点就始终往下走,直到没有后续节点或者后续节点已经被访问输出了;广度优先,就是节点一层一层的输出。举个例子,

        遍历和输入遍历和输入

        下面的两个图,深度优先遍历的结果为ABCD;而广度优先遍历的结果为ABDC。

        如何存储下面的图结构呢?可以采用数组表现法和邻接法。我这里只介绍数组表现法。

        图的结构体定义如下:

       

    typedef struct 
    {
        VertexType vexs[MAX_VERTEX_NUM];            //顶点向量
         VRType arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM];//邻接矩阵
         int vexnum,arcnum;                          //顶点数和弧数
         GKind kind;                                 //图的种类标识	
    }MGraph;

        
        要对图停止遍历,首先应当把图建立起来。以建立无向图为例。

        输入:定点数、边数、定点标号、边的长度。

        详细的创立代码如下:

    //创立无向图
    void CreatUDG(MGraph &G)
    {
        int i,j,k,w;
        char v1,v2;
    
        printf("输入顶点数和边数:");
        scanf("%d%d",&G.vexnum,&G.arcnum); 
    
        visited = (int *)malloc(G.vexnum*sizeof(int));
        for ( i = 0; i < G.vexnum; i++ )
            visited[i] = 0;
        printf("请按次序输入%d个顶点字母标号(如ABC等):",G.vexnum);
    
        getchar();//弹出缓冲区中前次最后出入的换行符,即最后按下的回车键
         for ( i = 0; i < G.vexnum; i++ )
    	scanf("%c",&G.vexs[i]);
    		
        getchar();//弹出缓冲区中前次最后出入的换行符,即最后按下的回车键
         for ( i = 0; i < G.vexnum; ++i )
    	for ( j = 0; j < G.vexnum; ++j )
        	{//初始化邻接矩阵
    	    if ( i == j )
    		G.arcs[i][j] = 0;
    	    else
    		G.arcs[i][j] = INT_MAX;
        	}
        
        printf("输入边的顶点和权值(如A B 1):\n");
        
        for ( k = 0; k < G.arcnum; k++ )
        {
    	scanf("%c %c %d",&v1,&v2,&w);
    	i = LocateVex(G,v1);
             j = LocateVex(G,v2);
    	G.arcs[i][j] = w;
    	G.arcs[j][i] = w;
    	getchar();//弹出缓冲区中前次最后出入的换行符,即最后按下的回车键
        }
    }

        


        源代码

        以下是遍历的完全代码:

    
    
        每日一道理
    聪明人学习,像搏击长空的雄鹰,仰视一望无际的大地;愚笨的人学习,漫无目的,犹如乱飞乱撞的无头飞蛾;刻苦的人学习,像弯弯的河流,虽有曲折,但终会流入大海;懒惰的人学习,像水中的木头,阻力越大倒退得越快。
    //myGraph.cpp
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <limits.h>
    
    #define MAX_VERTEX_NUM 20
    
    typedef int QElemType; 
    typedef int VRType;
    typedef char VertexType;
    typedef enum {DG,UDG} GKind;  //{有向图,无向图}
    
    typedef struct QNode
    {
        QElemType data;
        struct QNode *next;
    }QNode,*QPtr;
    
    typedef struct
    {
        QPtr front;
        QPtr tail;
    }LinkQueue;
    
    typedef struct 
    {
        VertexType vexs[MAX_VERTEX_NUM];            //顶点向量
         VRType arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM];//邻接矩阵
         int vexnum,arcnum;                          //顶点数和弧数
         GKind kind;                                 //图的种类标识	
    }MGraph;
    
    //初始化队列
    void InitQ(LinkQueue &Q);
    //从队尾插入元素
    void EnQueue(LinkQueue &Q,QElemType e);
    //从对首删除元素
    void DeQueue(LinkQueue &Q,QElemType &e);
    //队列是否为空,为空返回1,否则返回0
    int QEmpty(const LinkQueue &Q);
    
    //选择创立图的类型
    void CreatGraph(MGraph &G);
    //创立无向图
    void CreatUDG(MGraph &G);
    //创立有向图
    void CreatDG(MGraph &G);
    //打印邻接矩阵
    void printArcs(const MGraph &G);
    //返回字符在定点向量中的下标值
    int LocateVex(const MGraph &G,VertexType ch);
    //深度优先遍历函数
    void DFSTraverse(const MGraph &G);
    void DFS(const MGraph &G,int v);
    //广度优先遍历函数
    void BFSTraverse(const MGraph &G);
    //失掉第一个未被访问的相邻节点下标,若无,则返回-1
    int firstAjdVex(const MGraph &G,int v);
    //失掉下一个未被访问的相邻节点下标,若无,则返回-1
    int nextAjdVex(const MGraph &G,int v,int w);
    int *visited;   //记录顶点是否被访问
    
    //主函数
    int main()
    {
    	MGraph G;
    	CreatGraph(G);
    	printf("\n原始连接矩阵:\n");
    	printArcs(G);
    	//深度优先遍历结果
    	printf("\n深度优先遍历:");
    	DFSTraverse(G);
    	//广度优先遍历结果
    	printf("\n广度优先遍历:");
    	BFSTraverse(G);
    	printf("\n");
             return 0;
    
    }
    
    
    //初始化队列
    void InitQ(LinkQueue &Q)
    {
    	Q.front = Q.tail = (QPtr)malloc(sizeof(struct QNode));
    	if ( !Q.front )
    	{
    		printf("InitQ分配内存出错!\n");
    		return ;
    	}	
    	Q.front->next = NULL;
    }
    
    //从队尾插入元素
    void EnQueue(LinkQueue &Q,QElemType e)
    {
    	QPtr q = (QPtr)malloc(sizeof(struct QNode));
    	if ( !q )
    	{
    		printf("EnQueue分配内存出错!\n");
    		return ;
    	}
    	q->data = e;
    	q->next = NULL;
    	Q.tail->next = q;  //如果是第一次插入,Q.front->next也指向了q
    	Q.tail = q;
    }
    
    //从对首删除元素
    void DeQueue(LinkQueue &Q,QElemType &e)
    {
    	if ( Q.front == Q.tail )
    	{
    		printf("DeQueue队列为空,不能删除元素!\n");
    		return ;
    	}
    	QPtr q = Q.front->next;
    	e = q->data;
    	Q.front->next = q->next;
    	if ( Q.tail == q )
    		Q.tail = Q.front;
    	free(q);
    }
    
    //队列是否为空,为空返回1,否则返回0
    int QEmpty(const LinkQueue &Q)
    {
    	if ( Q.front == Q.tail )
    	{
    		return 1;
    	}
    	else
    	{
    		return 0;
    	}
    }
    
    
    //选择创立图的类型
    void CreatGraph(MGraph &G)
    {
        int k;
        printf("---------------------\n创立有向图,输入0;\n创立无\
    向图,输入1;\n并按下确认键.\n---------------------\n输入:");
        scanf("%d",&k);
        switch(k)
        {
    	case 0:
    	    G.kind = DG;
    	    CreatDG(G);
      	    break;
    	case 1:
    	    G.kind = UDG;
    	    CreatUDG(G);
      	    break;
    	default:
    	    printf("图类型输入有误!");
    	    break;
        } 
    }
    
    //创立无向图
    void CreatUDG(MGraph &G)
    {
        int i,j,k,w;
        char v1,v2;
    
        printf("输入顶点数和边数:");
        scanf("%d%d",&G.vexnum,&G.arcnum); 
    
        visited = (int *)malloc(G.vexnum*sizeof(int));
        for ( i = 0; i < G.vexnum; i++ )
    	visited[i] = 0;
        printf("请按次序输入%d个顶点字母标号(如ABC等):",G.vexnum);
    
        getchar();//弹出缓冲区中前次最后出入的换行符,即最后按下的回车键
         for ( i = 0; i < G.vexnum; i++ )
    		scanf("%c",&G.vexs[i]);
    		
         getchar();//弹出缓冲区中前次最后出入的换行符,即最后按下的回车键
          for ( i = 0; i < G.vexnum; ++i )
    	for ( j = 0; j < G.vexnum; ++j )
        	{//初始化邻接矩阵
    	    if ( i == j )
    		G.arcs[i][j] = 0;
    	    else
    		G.arcs[i][j] = INT_MAX;
        	}
        
        printf("输入边的顶点和权值(如A B 1):\n");
        
        for ( k = 0; k < G.arcnum; k++ )
        {
    	scanf("%c %c %d",&v1,&v2,&w);
    	i = LocateVex(G,v1);
             j = LocateVex(G,v2);
    	G.arcs[i][j] = w;
    	G.arcs[j][i] = w;
    	getchar();//弹出缓冲区中前次最后出入的换行符,即最后按下的回车键
        }
    }
    
    //创立有向图
    void CreatDG(MGraph &G)
    {//和创立无向图类似,只是少了一句将G.arcs[j][i] = w;
     //因为无向图是对称的,而有向图不是
         int i,j,k,w;
        char v1,v2;
    
        printf("输入顶点数和边数:");
        scanf("%d%d",&G.vexnum,&G.arcnum); 
    
        visited = (int *)malloc(G.vexnum*sizeof(int));
        for ( i = 0; i < G.vexnum; i++ )
    		visited[i] = 0;
        printf("请按次序输入%d个顶点字母标号(如ABC等):",G.vexnum);
    
        getchar();//弹出缓冲区中前次最后出入的换行符,即最后按下的回车键
         for ( i = 0; i < G.vexnum; i++ )
    	scanf("%c",&G.vexs[i]);
    		
        getchar();//弹出缓冲区中前次最后出入的换行符,即最后按下的回车键
         for ( i = 0; i < G.vexnum; ++i )
    	for ( j = 0; j < G.vexnum; ++j )
        	{//初始化邻接矩阵
    	    if ( i == j )
    		G.arcs[i][j] = 0;
    	   else
    		G.arcs[i][j] = INT_MAX;
        	}
        
        printf("输入边的顶点和权值(如A B 1):\n");
        
        for ( k = 0; k < G.arcnum; k++ )
        {
    	scanf("%c %c %d",&v1,&v2,&w);
    	i = LocateVex(G,v1);
             j = LocateVex(G,v2);
    	G.arcs[i][j] = w;
    	getchar();//弹出缓冲区中前次最后出入的换行符,即最后按下的回车键
        }
    }
    
    
    //打印邻接矩阵
    void printArcs(const MGraph &G)
    {
    	int i;
    	int j;
    	for ( i = 0; i < G.vexnum; i++ )
    	{
    		for ( j = 0; j < G.vexnum; j++ )
    		{
    		    if ( INT_MAX == G.arcs[i][j])
    			printf("%6s%","INF");
    		    else 
    			printf("%6d",G.arcs[i][j]);
    		}			
    		printf("\n");
    	}		
    }
    
    //返回字符在定点向量中的下标值
    int LocateVex(const MGraph &G,VertexType ch)
    {
    	int i;
    	for ( i = 0; G.vexnum; i++ )
    	    if ( ch == G.vexs[i] )
    		return i;
    	return -1;
    }
    
    //深度优先遍历函数
    void DFSTraverse(const MGraph &G)
    {
    	int i;
    
    	for ( i = 0; i < G.vexnum; i++ )
    		visited[i] = 0;   //初始化访问标记数组
    	for ( i = 0; i < G.vexnum; i++ )
    		if ( !visited[i] )
    		{//对尚未访问的顶点调用DFS
    			DFS(G,i);
    		}
    		printf("\n");
    }
    
    
    void DFS(const MGraph &G,int v)
    {
    	int w;
    	visited[v] = 1;
             printf("%-4c",G.vexs[v]);
             for ( w = firstAjdVex(G,v); w >= 0; w = nextAjdVex(G,v,w) )
    	    if ( !visited[w] )
    		DFS(G,w);
    }
    
    //广度优先遍历函数
    void BFSTraverse(const MGraph &G)
    {
    	int i,w,v;
    	LinkQueue Q;
    	InitQ(Q);
    
    	for ( i = 0; i < G.vexnum; i++ )
    		visited[i] = 0;   //初始化访问标记数组
    
    	for ( i = 0; i < G.vexnum; i++ )
    	{
    		if ( !visited[i] )
    		{
    			visited[i] = 1;
    			printf("%-4c",G.vexs[i]);
    			EnQueue(Q,i);
    			while (!QEmpty(Q))
    			{
    				DeQueue(Q,v);
    				for ( w = firstAjdVex(G,v); w >= 0; w = nextAjdVex(G,v,w) )
    				{
    					if ( !visited[w] )
    					{
    						visited[w] = 1;
    						printf("%-4c",G.vexs[w]);
    						EnQueue(Q,w);
    					}
    				}
    			}
    		}
    
    	}
    	
    }
    
    
    //失掉第一个未被访问的相邻节点下标,若无,则返回-1
    int firstAjdVex(const MGraph &G,int v)
    {
    	int i;
    	for ( i = 0; i < G.vexnum; i++ )
    	{
    		if ( !visited[i] && G.arcs[v][i] > 0 && G.arcs[v][i] < INT_MAX)
    			return i;
    	}
    	return -1;	
    }
    
    //失掉下一个未被访问的相邻节点下标,若无,则返回-1
    int nextAjdVex(const MGraph &G,int v,int w)
    {
    	int i;
    	for ( i = w; i < G.vexnum; i++ )
    	{
    		if ( !visited[i] && G.arcs[v][i] > 0 && G.arcs[v][i] < INT_MAX)
    			return i;
    	}
    	return -1;
    }

        程序运行结果(参照下面给出的例子):

        遍历和输入遍历和输入
     

    文章结束给大家分享下程序员的一些笑话语录: 系统程序员
      1、头皮经常发麻,在看见一个蓝色屏幕的时候比较明显,在屏幕上什幺都看不见的时候尤其明显;
      2、乘电梯的时候总担心死机,并且在墙上找reset键;
      3、指甲特别长,因为按F7到F12比较省力;
      4、只要手里有东西,就不停地按,以为是Alt-F、S;
      5、机箱从来不上盖子,以便判断硬盘是否在转;
      6、经常莫名其妙地跟踪别人,手里不停按F10;
      7、所有的接口都插上了硬盘,因此觉得26个字母不够;
      8、一有空就念叨“下辈子不做程序员了”;
      9、总是觉得9号以后是a号;
      10、不怕病毒,但是很害怕自己的程序;

  • 相关阅读:
    nginx-1.8.1的安装
    ElasticSearch 在3节点集群的启动
    The type java.lang.CharSequence cannot be resolved. It is indirectly referenced from required .class files
    sqoop导入导出对mysql再带数据库test能跑通用户自己建立的数据库则不行
    LeetCode 501. Find Mode in Binary Search Tree (找到二叉搜索树的众数)
    LeetCode 437. Path Sum III (路径之和之三)
    LeetCode 404. Sum of Left Leaves (左子叶之和)
    LeetCode 257. Binary Tree Paths (二叉树路径)
    LeetCode Questions List (LeetCode 问题列表)- Java Solutions
    LeetCode 561. Array Partition I (数组分隔之一)
  • 原文地址:https://www.cnblogs.com/xinyuyuanm/p/3091440.html
Copyright © 2011-2022 走看看