草草实现的随机图产生器(邻接矩阵)和最短路径算法

来源:互联网 发布:2012sql安装包百度云 编辑:程序博客网 时间:2024/04/30 10:48

        好久没有实现数据结构算法方面的东西了,前天晚上心血来潮写了这个随机图产生函数并实现了最短路径算法Dijkstra怀念一下已经远去的大学生活!对于图的生成要注意几个方面1)没有自回路,也就是说邻接矩阵的主对角线元素要全部为0;2)本程序产生的都是有向图,如果是无向图那么这个矩阵是关于对角线对称的,可以通过生成上(下)三角阵然后对称拷贝的方式生成.
      比较凌乱,其中一些安全性判断代码可以放到一个函数里让程序看起来更简洁些。

/*********************************************
*   File:   DIJKSTRA.CPP                                               *
*   Author: Lute                 *
*   Date:   Jan, 23nd, 2005                                               *  
*   Desc:   We will provide a impliention                           *
*           of Random Graph Generator and                        *
*           the Dijkstra Algorithm                                         *
*********************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>     //for function memset()
#include <sys/time.h> //for function time(), as random seed. If you are using
                                      //VS6.0, replace it as #include<time.h>


#define INFINITE 1000000
#define ALLKNOWN -2
#define MIN(a, b)  (a>b?b:a)


//definition of the node of the graph
struct node{
    int  id;      //the id of the node
    int  data;    //the data store in node
    bool known;   //is known? reserve for some algorithm
};

typedef struct node Node;

//definition of the Graph structure
struct graph{
    int   num;    //the number of node
    Node* gnode;  //pointer to the graph node list
    int*  ajcent; //pointer to the ajacent matrix, and we will store n*n
                  //edges'infomation in one-dimension array    
};

typedef struct graph Graph;


Graph* GenRandGraph(int nodenum)
{
    int i;
    int adjcentnum = nodenum*nodenum;
   
    //initialize the graph
    Graph* graph = NULL;
    graph = (Graph*)malloc(sizeof(Graph));
   
    memset(graph, 0, sizeof(Graph));
   
    if(!graph)
    {
        printf("GenRandGraph 1:Not enough memory to allocate!/n");
        return NULL;
    }
   
   
    graph->num = nodenum;
    graph->gnode = (Node*)malloc(sizeof(Node)*nodenum);
    graph->ajcent = (int*)malloc(sizeof(int)*adjcentnum);
   
    if(!graph->gnode)
    {
        printf("GenRandGraph 2:Not enough memory to allocate!/n");
        free(graph); //before return we must to set what we have free!
        graph = NULL;
        return NULL;
    }
   
    if(!graph->ajcent)
    {
        printf("GenRandGraph 3:Not enough memory to allocate!/n");
       
        free(graph->gnode);
        graph->gnode = NULL;
       
        free(graph);
        graph = NULL;
       
        return NULL;
    }
   
    //Random Seed
   srand(time(NULL));
   
    for(i=0; i<nodenum; i++)
    {
        graph->gnode[i].id = i;
        graph->gnode[i].data = rand()%10;
        graph->gnode[i].known = false;
    }
   
    for(i=0; i<adjcentnum; i++)
        graph->ajcent[i] = (rand()%2)*(rand()%10);
       
    //And the graph shuld not contain the self-loop struct so...
    for(i=0; i<nodenum; i++)
        graph->ajcent[i*nodenum+i] = 0;
       
    return graph;
}

//Free all momory allocated for the graph, the
void DeleteGraph(Graph* graph)
{
    if(!graph)
        return;
       
    if(graph->gnode)
    {
       free(graph->gnode);
       graph->gnode = NULL;
    }
   
    if(graph->ajcent)
    {
       free(graph->ajcent);
       graph->ajcent = NULL;
    }
   
    free(graph);
    graph = NULL;
}

//Printing the content of the nodes and the Adjacent Matrix of the Graph
void PrintGraph(Graph* graph)
{
    int i, adjacentnum;
   
    if(!graph)
    {
        printf("PrintGraph 1:Graph is NULL/n");
        return;
    }
   
    //Print info of nodes/Vertice
    if(graph->gnode){
        printf("Graph Node:");
        for(i=0; i<graph->num; i++)
          printf("%d-%d ", graph->gnode[i].id, graph->gnode[i].data);  
    }
   
    //Print Adjacent Matrix
    if(graph->ajcent){
        adjacentnum = graph->num*graph->num;
        printf("/n/nAjacent Matrix:/n");
        for(i=0; i<adjacentnum; i++)
        {
          if(i%graph->num==0)
             printf("/n");
          printf("%d ", graph->ajcent[i]);
        }
       
        printf("/n");
    }
}

//Set the Weight from vertex i to vertex j
bool SetEdgeWeight(int i, int j, int weight, Graph* graph)
{
    //Graph is NULL?
    if(!graph)
    {
        printf("SetEdgeWeight 1: Graph is NULL!/n");
        return false;
    }
   
    //Graph have been initialized?
    if(graph->num == 0 || !graph->gnode || !graph->ajcent)
    {
        printf("SetEdgeWeight 2: Graph is not initialized!/n");
        return false;
    }
   
    //Parament invaild? and you notice that i==j is an condition in if(...)
    //since our graph should not contian self-loop
    if(i<0 || j<0 || i>=graph->num || j>=graph->num || i==j)
    {
        printf("SetEdgeWeight 3: Invalid verter number!/n");
        return false;
    }
   
    graph->ajcent[i*graph->num+j] = weight;
   
    return true;
}

//Get Weight from the edge (i j)
int GetEdgeWeight(int i, int j, Graph* graph)
{
    //Is graph NULL?
    if(!graph)
    {
        printf("GetEdgeWeight 1:Graph is NULL/n");
        return -1;
    }
   
    //Have graph been initialized?
    if(graph->num == 0 || !graph->gnode || !graph->ajcent)
    {
        printf("GetEdgeWeight 2:Graph is not initailized!/n");
        return -1;
    }
   
    //Is the parameters invaild?
    if(i<0 || j<0 || i>=graph->num || j>=graph->num)
    {
        printf("GetEdgeWeight 3:Invalid Parameters!/n");
        return -1;
    }
   
   
    return graph->ajcent[i*graph->num+j];
}

 

/*******Function Below for Dijkstra algorithm**********/

//Have this node been known?
bool IsKnown(int i, Graph* graph)
{
    //Is graph NULL?
    if(!graph)
    {
        printf("IsKnown 1:Graph is NULL/n");
        return -1;
    }
   
    //Have graph been initialized?
    if(graph->num == 0 || !graph->gnode || !graph->ajcent)
    {
        printf("IsKnown 2:Graph is not initailized!/n");
        return -1;
    }
   
    //Is the parameters invaild?
    if(i<0 || i>=graph->num)
    {
        printf("IsKnown 3:Invalid Parameters!/n");
        return -1;
    }
   
    return graph->gnode[i].known;
   
}

//Set graph node as known
bool SetKnown(int i, Graph* graph)
{
    //Is graph NULL?
    if(!graph)
    {
        printf("SetKnown 1:Graph is NULL/n");
        return false;
    }
   
    //Have graph been initialized?
    if(graph->num == 0 || !graph->gnode || !graph->ajcent)
    {
        printf("SetKnown 2:Graph is not initailized!/n");
        return false;
    }
   
    //Is the parameters invaild?
    if(i<0 || i>=graph->num)
    {
        printf("SetKnown 3:Invalid Parameters!/n");
        return false;
    }
   
    graph->gnode[i].known = true;
   
    return true;
}

//Get a node which is not know and have the minimum path weight
int GetMinUnkown(int *path, Graph* graph)
{
    int i;
    int min=INFINITE, minnode=ALLKNOWN;
   
    //Is graph NULL?
    if(!graph)
    {
        printf("GetMinUnkown 1:Graph is NULL/n");
        return -1;
    }
   
    //Have graph been initialized?
    if(graph->num == 0 || !graph->gnode || !graph->ajcent)
    {
        printf("GetMinUnkown 2:Graph is not initailized!/n");
        return -1;
    }
   
    if(!path)
    {
        printf("GetMinUnkown 3:path is NULL/n");
        return -1;
    }
   
    for(i=0; i<graph->num; i++)
         if(!IsKnown(i, graph) && path[i]<min)
         {
                  min = path[i];
                  minnode = i;
         } 
   
    return minnode;
}

//Dijkstra Algorithm for single node shortest-path finding
bool Dijkstra(int i, Graph* graph)
{
    int *path = NULL;
    int j, temp, minnode=i, k;
   
    //Is graph NULL?
    if(!graph)
    {
        printf("Dijkstra 1:Graph is NULL/n");
        return false;
    }
   
    //Have graph been initialized?
    if(graph->num == 0 || !graph->gnode || !graph->ajcent)
    {
        printf("Dijkstra 2:Graph is not initailized!/n");
        return false;
    }
   
       //Is the parameters invaild?
    if(i<0 || i>=graph->num)
    {
        printf("Dijkstra 3:Invalid Parameters!/n");
        return false;
    }
   
    path = (int*)malloc(sizeof(int)*graph->num);
   
    if(!path)
    {
        printf("Dijkstra 4:Not enough memory to allocate!/n");
        return false;
    }
   
    //Initial
    for(j=0; j<graph->num; j++)
    {
        temp = GetEdgeWeight(i, j, graph);
        if(temp)
             path[j] = temp;
        else
             path[j] = INFINITE;
    }
   
   
    path[i] = 0;
    SetKnown(i, graph);
   
    for(j=0; j<graph->num; j++)
    {
        minnode = GetMinUnkown(path, graph);

        if(minnode != ALLKNOWN && minnode !=-1)
        {
       
          SetKnown(minnode, graph);
          for(k=0; k<graph->num; k++)
          {
                temp = GetEdgeWeight(minnode, k, graph);
               
                if(temp!=0 && temp!=-1 && k!=minnode )
                  path[k] = MIN(path[k], path[minnode]+temp);
           }
        }
    }
   
    printf("/n/nShortest path:/n");
   
    for(j=0; j<graph->num; j++)
    {
        if(j%4==0)
           printf("/n");
        printf("%3d-%-3d:%d ", i, j, path[j]);
        graph->gnode[j].known = false;
    }
   
    printf("/n");
       
    return true;
}


int main()
{
    Graph* pgraph = GenRandGraph(36);
   
    if(!pgraph)
    {
        printf("Can not Generate random graph!/n");
        return -1;
    }
   
    PrintGraph(pgraph);

    Dijkstra(10, pgraph);
      
    DeleteGraph(pgraph);
   
   
    system("pause");
    return 0;
}