10月12日笔记数据结构图

                                                                 本文具体代码都在第一个的代码上面进行的相应修改而成

1.图的基本概念
    定义:图(Gragh)是一种非线性化的数据的结构
    Gragh = (V,R)
    其中V = {Vi|Vi属于datatype }是图中元素Vi(顶点 Vertex )
    的集合 当n = 0; V是空集
    R = {<Vi,Vj>|<Vi,Vj>属于V 且p(Vi,Vj)存在}}是图中顶点之间的关系集
    P(Vi,VJ)表示顶点Vi和Vj之间是否存在一条路径  也就是P(Vi,Vj)存在,
    那么关系P(Vi,VJ)属于R

    分类:
        有向图与无向图
            有向图的顶点之间的路径有方向 顶点之间的连线称为弧
            无向图的顶点之间的路径没有方向 双向导通 其连线称为 边        


       权 w
            若在图的关系上<Vi,Vj>附加一个值w 这个值称为权值
            表示的是一个“成本” 在不同领域的,所代表的含义也不同
            比如地图上表示两个城市之间的距离
        
        网 带权的图

        路径 两个顶点之间,怎么走


2.图的存储结构
    “数组表示法”   邻接矩阵
    “邻接表”
    “十字链表”
    “邻接多重表”

    1.数组表示法 顺序结构
        G = (V,R)
        其中V 是顶点的集合  1 2 3 4 5 6 7 8 9
        用一个一维数组去保存
        R为关系的集合
            A   B   C   D  顶点集合

        A   255 255 3   2

        B   1   255 255  5

        C   3   255 255 6

        D   255 4   7   255
        关系用一个二维数组去保存
        如果这个图有权值,数据关系填权值
        两个顶点之间没有直接的关系 则填无穷大

        对于没有权值的图 一般选择0/1表示两个顶点之间
        能够直接到达 无穷大表示不能够直接到达

        typedef int vType;  //顶点元素的类型
        typedef int adjType;//权值类型

        #define NUM_MAX 100 //图中顶点的个数

        typedef struct MyGragh   //顶点的数据类型
        {
            //数据域
            vType Vertex[NUM_MAX];
            //关系域
            adjType Relation[NUM_MAX][NUM_MAX];

            //图中有效顶点的个数
            int vexNum;
            /*
                看你需要什么参数
            */
        }MyGragh;

        可读性 函数 变量 类型的命名
        可复用性 代码可以简单修改或者不修改后用于另一个项目

数组表示法具体代码:

/*
Graph.c
Graph.h
main.c
三个文件
*/
//-------------
//  Graph.h
#ifndef __GRAPH_H__
#define __GRAPH_H__
#define VMAX 100
typedef char VElemtype;//顶点元素的类型
typedef int adjType;    //边上权的类型

typedef struct MyGragh
{
    VElemtype Vertex[VMAX];//顶点集合V
    adjType A[VMAX][VMAX];//临界矩阵 "边"
    int VexNum;//图中有效的顶点数;
}MyGragh;



MyGragh *CreateGraph();
//依次按照深度优先的规则访问图G
void DFSTravers(MyGragh *G);
void BFSTravers(MyGragh *G);
void myVisit(MyGragh *G,int v0);
void Dijkstra(MyGragh *G,int v0);

#endif

//---------------------
//---------------------
//Graph.c
#include <stdio.h>
#include <stdlib.h>
#include "Graph.h"
#define INT_MAX 65535
#define TRUE    1
#define FALSE   0 

void myVisit(MyGragh *G,int v0)
{
    if(sizeof(VElemtype) == sizeof(int))
    {
        printf("%d ",G->Vertex[v0]);
    }
    else if(sizeof(VElemtype) == sizeof(char))
    {
        printf("%c ",G->Vertex[v0]);
    }
    
}
static int GetVexIndex(MyGragh *G,VElemtype v0)
{
    for(int i = 0;i < G->VexNum;i++)
    {
        if(G->Vertex[i] == v0)
        {
            return i;
        }
    }
    return -1;
}
MyGragh *CreateGraph()
{
    //先输入顶点集合 再输入关系集
    int i,j;
    VElemtype data;
    MyGragh *G = (MyGragh*)malloc(sizeof(MyGragh));
    G->VexNum = 0;
    for(i = 0;i < VMAX;i++)
    {
        G->Vertex[i] = 0;
    }
    for(i = 0;i < VMAX;i++)
    {
        for(j = 0;j < VMAX;j++)
        {
            G->A[i][j] = INT_MAX;
        }
    }
    //1.顶点集合
    printf("请输入顶点集合 以#号键结束\n");

    for(i = 0;1;i++)
    {
        scanf("%c",&data);
        if(data == '#' && G->VexNum < VMAX )//假设输入-1结束输入
        {
            break;
        }
        G->Vertex[i] = data;
        G->VexNum ++;
    }
    //打印出来 检查一下
    for(int i = 0;i < G->VexNum;i++)
    {
        printf("%c ",G->Vertex[i]);
    }
    printf("\n");
    // 2.关系集合
    // 输入边的关系 起点 终点 起点到终点的权值
    // 假设起点 输入 -1 结束
    printf("请输入关系集合: 起点 终点 起点到终点的权值\n");
    VElemtype startData,endData;
    int w;
    int StratIndex,endIndex;
    while(1)
    {
        getchar();//把回车读出来
        scanf("%c %c %d",&startData,&endData,&w);
        if(startData == '#')
        {
            break;
        }
        StratIndex = GetVexIndex(G,startData);
        endIndex = GetVexIndex(G,endData);
        if(StratIndex == -1 || endIndex == -1)
        {
            printf("你输入的起点或终点有错 请重新输入\n");
            continue;
        }
        G->A[StratIndex][endIndex] = w;
    }
    for(i = 0;i < G->VexNum;i++)
    {
        for(j = 0;j < G->VexNum;j++)
        {
            printf("%d\t",G->A[i][j]);
        }
        printf("\n");
    }
    return G;

}

//--------------------
//--------------------
//main.c
#include <stdio.h>
#include "Graph.h"

int main()
{ 
    MyGragh *G = CreateGraph();
    return 0;
}


//---------



    2.邻接表 链式结构
    所谓的邻接表(adjacency Lists),是将图中每一个顶点V和由V出发的
    边或弧构成的单链表 

    数据类型
    typedef int  vType;//顶点元素的类型
    typedef int  adjType;//边的权值w类型
    //图中顶点的最大个数
    #define NUM_MAX 100

    //关系的类型
    typedef struct MySide
    {
        //终点下标
        int term;
        //权值
        adjType w;
        //下一个关系的指针
        struct MySide* next;

    }MySide;
    //顶点的类型
    typedef struct
    {
        //数据域
        vType data;
        //关系域
        MySide *first;
    }Vertex;

    Vertex MyGragh[NUM_MAX]


3.图的遍历
    图的遍历是树的遍历的推广 是按照规则有且仅有一次的去访问图中每个顶点
    这是将网状结构按照某种规则线性化的过程

    对图的遍历通常由广度优先搜索深度优先搜索方法,二者是人工智能基础

    1.深度优先搜索(DFS:Depth First Search)
        设初始时,图中各顶点均未被范文,以图中顶点V0出发
        访问V0 然后搜索V0的邻接点Vi如果Vi未被访问,则访问Vi
        再以同样的规则(DFS)去遍历Vi。直到所有邻接点都被访问过,
        则回溯到它的上一个顶点
        直到所有顶点都被访问过了

        首先我需要一个标志 告诉我那些顶点被访问过了
        char visited[NUM_MAX] = {0};//0表示未被访问 1表示被访问了

        DFS(G,vi)
        {
            //1.递归先考虑终止条件 所有的邻接点都被访问了
                我们有两种方式 一种是满足了终止条件 结束函数
                                一种是满足了条件才执行
            if(如果vi的第一个邻接点未被访问 才进行访问改节点)
            {
                myVisit(Vi的第一个邻接点);
                标记这个顶点被访问
                visited[Vi的第一个邻接点] = 1;
                DFS(G,Vi的第一个邻接点)
            }

            vi的第二个邻接点以同样的方式
            第三个...
            第四个...
            =》所以代码可以写成 循环的方式
            for(v = Vi的第一个邻接点;v存在;v 等于 vi的下一个邻接点)
            {
                if(v未被访问)
                {
                    myVisit(v);
                    标记v被访问;

                    DFS(G,v的第一个邻接点)
                }
            }
        }

        //按照深度优先的规则访问图G
        DFSTravest(G)
        {
            for(int i = 0;i < G->vexNum;i++)
            {
                if(这个顶点未被访问)
                {
                    深度优先搜索的方式访问这个顶点
                    DFS(G,V0);
                }
            }
        }

DFS具体代码:

/*
Gragh.c
Gragh.h
main.c
三个文件
*/
//----------
//Graph.h
#ifndef __GRAGH_H__
#define __GRAGH_H__
#define VMAX 100
typedef char VElemtype;//顶点元素的类型
typedef int adjType;    //边上权的类型

typedef struct MyGragh
{
    VElemtype Vertex[VMAX];//顶点集合V
    adjType A[VMAX][VMAX];//临界矩阵 "边"
    int VexNum;//图中有效的顶点数;
}MyGragh;

MyGragh *CreateGraph();
//依次按照深度优先的规则访问图G
void DFSTravers(MyGragh *G);
void BFSTravers(MyGragh *G);
void myVisit(MyGragh *G,int v0);
void Dijkstra(MyGragh *G,int v0);

#endif

//-------------------
//-------------------
//Gragh.c
#include <stdio.h>
#include <stdlib.h>
#include "Gragh.h"
#define INT_MAX 65535
#define TRUE    1
#define FALSE   0 

void myVisit(MyGragh *G,int v0)
{
    if(sizeof(VElemtype) == sizeof(int))
    {
        printf("%d ",G->Vertex[v0]);
    }
    else if(sizeof(VElemtype) == sizeof(char))
    {
        printf("%c ",G->Vertex[v0]);
    }
    
}
static int GetVexIndex(MyGragh *G,VElemtype v0)
{
    for(int i = 0;i < G->VexNum;i++)
    {
        if(G->Vertex[i] == v0)
        {
            return i;
        }
    }
    return -1;
}
MyGragh *CreateGraph()
{
    //先输入顶点集合 再输入关系集
    int i,j;
    VElemtype data;
    MyGragh *G = (MyGragh*)malloc(sizeof(MyGragh));
    G->VexNum = 0;
    for(i = 0;i < VMAX;i++)
    {
        G->Vertex[i] = 0;
    }
    for(i = 0;i < VMAX;i++)
    {
        for(j = 0;j < VMAX;j++)
        {
            G->A[i][j] = INT_MAX;
        }
    }
    //1.顶点集合
    printf("请输入顶点集合 以#号键结束\n");

    for(i = 0;1;i++)
    {
        scanf("%c",&data);
        if(data == '#' && G->VexNum < VMAX )//假设输入-1结束输入
        {
            break;
        }
        G->Vertex[i] = data;
        G->VexNum ++;
    }
    //打印出来 检查一下
    for(int i = 0;i < G->VexNum;i++)
    {
        printf("%c ",G->Vertex[i]);
    }
    printf("\n");
    // 2.关系集合
    // 输入边的关系 起点 终点 起点到终点的权值
    // 假设起点 输入 -1 结束
    printf("请输入关系集合: 起点 终点 起点到终点的权值\n");
    VElemtype startData,endData;
    int w;
    int StratIndex,endIndex;
    while(1)
    {
        getchar();//把回车读出来
        //从键盘读取一个关系
        scanf("%c %c %d",&startData,&endData,&w);
        if(startData == '#')
        {
            break;
        }
        //获取起点终点下标
        StratIndex = GetVexIndex(G,startData);
        endIndex = GetVexIndex(G,endData);
        if(StratIndex == -1 || endIndex == -1)
        {
            printf("你输入的起点或终点有错 请重新输入\n");
            continue;
        }
        //对相应位置的进行赋值 这里采用行表示起点 列表示终点
        G->A[StratIndex][endIndex] = w;
    }
    for(i = 0;i < G->VexNum;i++)
    {
        for(j = 0;j < G->VexNum;j++)
        {
            printf("%d\t",G->A[i][j]);
        }
        printf("\n");
    }
    return G;
}
char visited[VMAX] = {FALSE};//0表示未被访问 1表示被访问了
/*
    func:获取下一个邻接点
    G你从那个图的顶点集合搜索 vi你搜索谁的邻接点  V你这一次从第几列开始搜索
*/
int GetNextApp(MyGragh *G,int vi,int v)
{
    for(int i = v;i < G->VexNum;i++)
    {
        //如果vi到i顶点对应的权值不为无穷大  意味着这是它的邻接点
        if(G->A[vi][i] != INT_MAX)
        {
            return i;
        }
    }
    return -1;
}
void DFS(MyGragh *G,int vi)
{
    int v = 0;
    if(visited[vi] == FALSE)
    {
        myVisit(G,vi);
        visited[vi] = TRUE;
        for(v = GetNextApp(G,vi,v);v != -1;v = GetNextApp(G,vi,v+1))
        {
            if(visited[v] == FALSE)
            {
                myVisit(G,v);
                visited[v] = TRUE;
                DFS(G,v);
            }

        }
    }

}

//按照深度优先的规则访问图G
void DFSTravers(MyGragh *G)
{
    for(int i = 0;i < G->VexNum;i++)
    {
        if(visited[i] == FALSE)
        {
            //深度优先搜索的方式访问这个顶点
            DFS(G,i);
        }
    }
    printf("\n");
}

//---------------------
//---------------------
//main.c
#include <stdio.h>
#include "Gragh.h"

int main()
{ 
    MyGragh *G = CreateGraph();
    DFSTravers(G);
    //printf("%s %s %d\n",__FILE__,__FUNCTION__,__LINE__);
    return 0;
}


//---------------


    2.广度优先搜索(BFS; breadth First Search)
        类似与树的层级遍历,先访问节点本身,然后再访问节点周围的邻接点,
        访问完所有的邻接点后,再按照同样的规则访问邻接点的邻接点

        这种必然会用到队列
        char visited[NUM_MAX] = {0};//0表示未被访问 1表示被访问了
        BFSTravese(G)
        {
            //重置visited
            for(int i = 0;i <NUM_MAX;i++)
            {
                visited[i] = FALSE;
            }
            初始化一个队列
            for(int v0 = 0;v0 < G->vexNum;v0++)
            {
                if(这个顶点v0未被访问)
                {
                    1.访问V0
                    标记v0被访问;
                    2.v0入队
                    while(队列非空)
                    {
                        出队
                        //依次访问出队顶点的所有邻接点,并入队
                        for(v = Vi的第一个邻接点;v存在;v 等于 vi的下一个邻接点)
                        {
                            if(v未被访问)
                            {
                                myVisit(v);
                                标记v被访问;
                                入队
                            }
                        }
                    }
                    
                }
            }
        }

BFS具体代码:

/*
Gragh.h
Gragh.c
LinkedQueue.h
LinkedQueue.c
main.c
五个文件
*/

//--------------
//Gragh.h
#ifndef __GRAGH_H__
#define __GRAGH_H__
#define VMAX 100
typedef int VElemtype;//顶点元素的类型
typedef int adjType;    //边上权的类型

typedef struct MyGragh
{
    VElemtype Vertex[VMAX];//顶点集合V
    adjType A[VMAX][VMAX];//临界矩阵 "边"
    int VexNum;//图中有效的顶点数;
}MyGragh;

MyGragh *CreateGraph();
//依次按照深度优先的规则访问图G
void DFSTravers(MyGragh *G);
void BFSTravers(MyGragh *G);
void myVisit(MyGragh *G,int v0);
void Dijkstra(MyGragh *G,int v0);

#endif

//-------------------
//-------------------
//Gragh.c
#include <stdio.h>
#include <stdlib.h>
#include "LinkedQueue.h"
#include "Gragh.h"
#define INT_MAX 65535
#define TRUE    1
#define FALSE   0 

void myVisit(MyGragh *G,int v0)
{
    if(sizeof(VElemtype) == sizeof(int))
    {
        printf("%d ",G->Vertex[v0]);
    }
    else if(sizeof(VElemtype) == sizeof(char))
    {
        printf("%c ",G->Vertex[v0]);
    }
    
}
static int GetVexIndex(MyGragh *G,VElemtype v0)
{
    for(int i = 0;i < G->VexNum;i++)
    {
        if(G->Vertex[i] == v0)
        {
            return i;
        }
    }
    return -1;
}
MyGragh *CreateGraph()
{
    //先输入顶点集合 再输入关系集
    int i,j;
    VElemtype data;
    MyGragh *G = (MyGragh*)malloc(sizeof(MyGragh));
    G->VexNum = 0;
    for(i = 0;i < VMAX;i++)
    {
        G->Vertex[i] = 0;
    }
    for(i = 0;i < VMAX;i++)
    {
        for(j = 0;j < VMAX;j++)
        {
            G->A[i][j] = INT_MAX;
        }
    }
    //1.顶点集合
    printf("请输入顶点集合 以#号键结束\n");

    for(i = 0;1;i++)
    {
        scanf("%d",&data);
        if(data == -1 && G->VexNum < VMAX )//假设输入-1结束输入
        {
            break;
        }
        G->Vertex[i] = data;
        G->VexNum ++;
    }
    //打印出来 检查一下
    for(int i = 0;i < G->VexNum;i++)
    {
        printf("%d ",G->Vertex[i]);
    }
    printf("\n");
    // 2.关系集合
    // 输入边的关系 起点 终点 起点到终点的权值
    // 假设起点 输入 -1 结束
    printf("请输入关系集合: 起点 终点 起点到终点的权值\n");
    VElemtype startData,endData;
    int w;
    int StratIndex,endIndex;
    while(1)
    {
        getchar();//把回车读出来
        //从键盘读取一个关系
        scanf("%d %d %d",&startData,&endData,&w);
        if(startData == -1)
        {
            break;
        }
        //获取起点终点下标
        StratIndex = GetVexIndex(G,startData);
        endIndex = GetVexIndex(G,endData);
        if(StratIndex == -1 || endIndex == -1)
        {
            printf("你输入的起点或终点有错 请重新输入\n");
            continue;
        }
        //对相应位置的进行赋值 这里采用行表示起点 列表示终点
        G->A[StratIndex][endIndex] = w;
    }
    for(i = 0;i < G->VexNum;i++)
    {
        for(j = 0;j < G->VexNum;j++)
        {
            printf("%d\t",G->A[i][j]);
        }
        printf("\n");
    }
    return G;
}
char visited[VMAX] = {FALSE};//0表示未被访问 1表示被访问了
/*
    func:获取下一个邻接点
    G你从那个图的顶点集合搜索 vi你搜索谁的邻接点  V你这一次从第几列开始搜索
*/
int GetNextApp(MyGragh *G,int vi,int v)
{
    for(int i = v;i < G->VexNum;i++)
    {
        //如果vi到i顶点对应的权值不为无穷大  意味着这是它的邻接点
        if(G->A[vi][i] != INT_MAX)
        {
            return i;
        }
    }
    return -1;
}
void DFS(MyGragh *G,int vi)
{
    int v = 0;
    if(visited[vi] == FALSE)
    {
        myVisit(G,vi);
        visited[vi] = TRUE;
        for(v = GetNextApp(G,vi,v);v != -1;v = GetNextApp(G,vi,v+1))
        {
            if(visited[v] == FALSE)
            {
                myVisit(G,v);
                visited[v] = TRUE;
                DFS(G,v);
            }

        }
    }

}

//按照深度优先的规则访问图G
void DFSTravers(MyGragh *G)
{
    //重置visited
    for(int i = 0;i <VMAX;i++)
    {
        visited[i] = FALSE;
    }
    for(int i = 0;i < G->VexNum;i++)
    {
        if(visited[i] == FALSE)
        {
            //深度优先搜索的方式访问这个顶点
            DFS(G,i);
        }
    }
    printf("\n");
}

void BFSTravers(MyGragh *G)
{
    //重置visited
    for(int i = 0;i <VMAX;i++)
    {
        visited[i] = FALSE;
    }
    LinkedQueue *myQueue = InitQueue();
    for(int v0 = 0;v0 < G->VexNum;v0++)
    {
        if(visited[v0] == FALSE)
        {
            myVisit(G,v0);
            visited[v0] = TRUE;
            EnQueue(myQueue,v0);
            while(QueueIsEmpty(myQueue) == 0)
            {
                int vi = 0;
                int v = 0;;
                DeQueue(myQueue,&vi);
                //依次访问出队顶点的所有邻接点,并入队
                for(v = GetNextApp(G,vi,v);v != -1;v = GetNextApp(G,vi,v+1))
                {
                    if(visited[v] == FALSE)
                    {
                        myVisit(G,v);
                        visited[v] = TRUE;
                        EnQueue(myQueue,v);
                    }
                }
            }
            
        }
    }
}


//------------------
//------------------
//main.c
#include <stdio.h>
#include "Gragh.h"

int main()
{ 
    MyGragh *G = CreateGraph();
    //DFSTravers(G);
    BFSTravers(G);
    //printf("%s %s %d\n",__FILE__,__FUNCTION__,__LINE__);
    return 0;
}

//-----------------------
//被引用的队列相关代码
//-----------------------
//LinkedQueue.h 
#ifndef __LINKEDQUEUE_H__
#define __LINKEDQUEUE_H__

typedef int QElemType;

typedef struct QueueNode
{
    QElemType data;
    struct QueueNode *ptNext;
}QueueNode;


typedef struct LinkedQueue
{
    QueueNode *ptFront;
    QueueNode *ptRear;
    int dwCount;
    /*
        其他的看你需要什么了
    */
}LinkedQueue;

//初始化一个队列 返回值返回队列的指针
LinkedQueue *InitQueue();
//清空一个队列
//warning:清空队列会把队列保存地址的空间给释放掉!!
//void ClearQueue_Free(LinkedQueue * ptQueue);
//清空一个队列
//warning:清空队列不会把队列保存地址的空间给释放掉!!
void ClearQueue_NoFree(LinkedQueue * ptQueue);
//销毁一个队列
//warning:销毁队列会把队列保存地址的空间给释放掉!!
//void DestroyQueue_Free(LinkedQueue * ptQueue);
//销毁一个队列
//warning:销毁队列不会会把队列保存地址的空间给释放掉!!
void DestroyQueue_NoFree(LinkedQueue * ptQueue);
//判断一个队列是否为空 
//返回值 1 为空
//      0 非空
int QueueIsEmpty(LinkedQueue * ptQueue);
//判断队列中元素的个数 即队列的长度
//判断一个队列是否为空 
//返回值 -1 失败
//       >= 表示长度
int QueueLength(LinkedQueue * ptQueue);
/*
    入队
    data表示要入队的元素
    返回值   0 成功
            -1 失败
*/
int EnQueue(LinkedQueue * ptQueue,QElemType data);
/*
    出队
    data表示要出队的元素
    返回值   0 成功
            -1 失败
*/
int DeQueue(LinkedQueue * ptQueue,QElemType *data);
//获取队头元素但是不出队
/*
    获取队头元素但是不出队
    data表示要队头的元素
    返回值   0 成功
            -1 失败
*/
int GetHead(LinkedQueue * ptQueue,QElemType *data);



#endif


//-------------
//--------------
//LinkedQueue.c
#include <stdio.h>
#include <stdlib.h>
#include "LinkedQueue.h"


LinkedQueue *InitQueue(int dwQueueMaxLength)
{
    LinkedQueue *ptLinkedQueue = (LinkedQueue*)malloc(sizeof(LinkedQueue));
    ptLinkedQueue->dwCount = 0;
    ptLinkedQueue->ptFront = NULL;
    ptLinkedQueue->ptRear = NULL;
}
void ClearQueue_Free(LinkedQueue * ptQueue)
{
    // if(ptQueue == NULL)
    // {
    //     return ;
    // }
    // QElemType data;
    // while(!QueueIsEmpty(ptQueue))
    // {
    //     DeQueue(ptQueue,&data);
    //     //通用栈存的是一个地址,清空栈的时候需要释放
    //     free(data);
    // }
}
void ClearQueue_NoFree(LinkedQueue * ptQueue)
{
    if(ptQueue == NULL)
    {
        return ;
    }
    QElemType data;
    while(!QueueIsEmpty(ptQueue))
    {
        DeQueue(ptQueue,&data);
    }
}
void DestroyQueue_Free(LinkedQueue * ptQueue)
{
    if(ptQueue == NULL)
    {
        return ;
    }
    ClearQueue_Free(ptQueue);
    free(ptQueue);
}
void DestroyQueue_NoFree(LinkedQueue * ptQueue)
{
    if(ptQueue == NULL)
    {
        return ;
    }
    ClearQueue_NoFree(ptQueue);
    free(ptQueue);
}
int QueueIsEmpty(LinkedQueue * ptQueue)
{
    if(ptQueue == NULL)
    {
        return -1;
    }
    return (ptQueue->dwCount == 0)?1:0;
}
int QueueLength(LinkedQueue * ptQueue)
{
    if(ptQueue == NULL)
    {
        return -1;
    }
    return ptQueue->dwCount;
}
int EnQueue(LinkedQueue * ptQueue,QElemType data)
{
    if(ptQueue == NULL)
    {
        return -1;
    }
    //创建节点并保存
    QueueNode *p = (QueueNode *)malloc(sizeof(QueueNode));
    p->data = data;
    p->ptNext = NULL;

    //入队
    //队中没有元素
    if(ptQueue->ptFront == NULL)
    {
        ptQueue->ptFront = p;
    }
    else//有至少一个元素 尾插法
    {
        ptQueue->ptRear->ptNext = p;   
    }
    ptQueue->ptRear = p;
    ptQueue->dwCount ++;

    return 0;
}
int DeQueue(LinkedQueue * ptQueue,QElemType *data)
{
    //安全检查
    if(ptQueue == NULL || ptQueue->dwCount == 0)
    {
        return -1;
    } 
    //返回队头的值
    *data = ptQueue->ptFront->data;
    //删除队头
    QueueNode *p = ptQueue->ptFront;
    ptQueue->ptFront = p->ptNext;
    //队头已经为空 没有元素了 队尾也要为空
    if(ptQueue->ptFront == NULL)
    {
        ptQueue->ptRear = NULL;
    }
    ptQueue->dwCount--;
    p->ptNext = NULL;
    free(p);
    return 0;
}
int GetHead(LinkedQueue * ptQueue,QElemType *data)
{
    //安全检查
    if(ptQueue == NULL || ptQueue->dwCount == 0)
    {
        return -1;
    } 
    //返回队头的值
    *data = ptQueue->ptFront->data;
    return 0;
}


//-----------------------



    最短路径问题
        dijikstra 迪杰斯特拉
            单源最短路径算法 其目的是求解出从一个点出发到其他所有点的最短路径
            采用的是贪心策略 不能出现负权值
        Floyd 弗洛伊德算法
            多元最短路径算法 采用了动态规划的思想 求解的是图中所有点到任意点到最短路径

(可参考b站视频进行理解,图论最短距离(Shortest Path)算法动画演示-Dijkstra(迪杰斯特拉)和Floyd(弗洛伊德)_哔哩哔哩_bilibiliTo my litter sister and little brother!https://www.bilibili.com/video/BV1q4411M7r9?share_source=copy_web)

        迪杰斯特拉算法思路:
            1.更新 :更新distance数组和path数组 计算从起点出发经过第三步的添加的中转到各点的距离
                    如果距离更短,则更新为更短的距离和路径 否则保留原址
            2.扫描 找出未找到最短路径的点中距离最小的那个,这个点就是新的最短路径
            3.添加 将新的那个点作为搜索的中转点,将对应visit置为ture
            循环n遍

迪杰斯特拉具体代码:

//在前面BFS算法上面相应文件上面添加代码

//------------------
//Gragh.h
void Dijkstra(MyGragh *G,int v0);

//------------------
//------------------
//Gragh.c
void Dijkstra(MyGragh *G,int v0)
{
    //初始化
    char IsShortestPath[VMAX] = {FALSE};
    for(int i = 0;i < G->VexNum;i++)
    {
        IsShortestPath[i] = FALSE;
    }
    int distance[VMAX] = {INT_MAX};
    for(int i = 0;i < G->VexNum;i++)
    {
        distance[i] = INT_MAX;
    }
    char path[VMAX] = {-1};
    for(int i = 0;i < G->VexNum;i++)
    {
        path[i] = -1;
    }
    IsShortestPath[v0] = TRUE;
    distance[v0] = 0;
    path [v0] = v0;
    printf("\n");
    //寻找从v0出发到各点的最短路径
    int i = 0;
    int Intrm = v0;//中转点 从起点出发经过该点到各点
    int minDistance = INT_MAX;
    int v= 0;//表示邻接点
    while(i++ < G->VexNum)
    {
        //1.更新
        for(v = GetNextApp(G,Intrm,v);v != -1; v = GetNextApp(G,Intrm,v+1))
        {
            //如果经过该点到邻接点v距离更短,则更新新的路径
            if(distance[Intrm] + G->A[Intrm][v] < distance[v])
            {
                distance[v] = distance[Intrm] + G->A[Intrm][v];
                path[v] = Intrm;
            }
        }
        //2.扫描
        minDistance = INT_MAX;
        for(int i = 0;i < G->VexNum;i++)
        {
            if(IsShortestPath[i] == FALSE)
            {
                if(distance[i] < minDistance)
                {
                    minDistance = distance[i];
                    Intrm = i;
                }
            }
        }
        //3.添加
        IsShortestPath[Intrm] = TRUE;
    }
    //把结果打印出来
    int j = 0;
    for(int vi = 0; vi < G->VexNum;vi++)
    {
        if(vi == v0)
        {
            continue;
        }
        printf("%d -> %d 最短的距离是:%d\n",v0,vi,distance[vi]);
        j = vi;
        //起点的最短路径是它本身 所以j == path[j] 就表示已经找到起点了
        printf("路径为:");
        while(j != path[j])
        {
            printf("%d <- ",j);
            j = path[j];
        }
        printf("%d\n",j);
    }
}

//--------------------
//--------------------
//main.c
int main()
{ 
    MyGragh *G = CreateGraph();
    //DFSTravers(G);
    //BFSTravers(G);
    //printf("%s %s %d\n",__FILE__,__FUNCTION__,__LINE__);
    Dijkstra(G,0);
    return 0;
}


//-------------------




    

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值