zoukankan      html  css  js  c++  java
  • 有向无权图的最短路径算法

        对于一个有向无权的图,我们只需从起点开始,依次往后寻找即可,这还谈不上算法,只能说是一种思想,这种思想解释如下:

        首先对于一个有向无权的图:

        我们令v0为起点,v0到v0的路径为0,所有在v0下面标0,如下图所示:

         接着发现v0到v1和v2,v3都只需经过一条边,因此在v1和v2,v3下面标1,如下图所示:

      接着找v1和v2,v3相邻的点,发现是v2和v4,v6,就在这两个点下面标2.如下图所示:

       没有点剩下,整个过程完毕,如果还剩下点,就继续按照上面的思想执行,直到所有的点都遍历到。

       这样整个过程就完了,点下面标的数字就是所需要的最短的路径,把上述思想转换成代码就可以了。

       代码如下:

       

    #include <iostream>
    using namespace std;
     
    #define Inf 65535
    //////////////////////列队的相关定义//////////////////////
    typedef struct QueueRecord *Queue;
    #define MinQueueSize  10
    struct QueueRecord
    {
       int Capacity;    //队的容量
       int Front;       //队头
       int Rear;        //队尾
       int Size;        //队中元素的个数
       int *Array;       //数组
    };
    /////////////////////邻接表的相关定义//////////////////////
    typedef struct EdgeNode *position;
    typedef struct Led_table* Table; 
    
    
     struct EdgeNode     //边表结点  
    {  
        int adjvex;    // 邻接点域,存储该顶点对应的下标  
        int weight;     // 对应边的权值 
        position next; // 链域,指向下一个邻接点
    }; 
    
    struct Led_table       // 邻接表结构  
    {  
        int data;                //邻接表的大小
        position *firstedge;       //边表头指针,可以理解为数组
    };  
    
    ///////////////////列队相关函数声明////////////////////////
    int IsEmpty(Queue Q);    //判断队列是否为空
    int IsFull(Queue Q);     //判断队列是否满了
    void MakeEmpty(Queue Q);   //构造一个空列队
    Queue CreateQueue(int MaxElements);  //创建一个列队
    void DisposeQueue(Queue Q);      //释放一个列队
    void Enqueue(int x, Queue Q);    //入队
    int Dequeue(Queue Q);      //出队
    int Front(Queue Q);     //返回队首值,不出队
     
     
    ///////////////////列队相关函数定义////////////////////////
    int IsEmpty(Queue Q)
    {
       return Q->Size == 0;
    }
     
    int IsFull(Queue Q)
    {
        if(Q->Size > Q->Capacity )
        {
           cout << "queue full" << endl;
           return -1;
        }
        else
        {
           return 0;
        }
    }
     
    void MakeEmpty(Queue Q)
    {
       Q->Size = 0;
       Q->Front = 1;
       Q->Rear = 0;
    }
     
    Queue CreateQueue(int MaxElements)
    {
       Queue Q;
       if (MaxElements < MinQueueSize)
       {
          cout << "queue size is too small" << endl;
       }
       Q = static_cast<Queue> (malloc(sizeof(struct QueueRecord)));
       if(Q == NULL)
       {
          cout << "out of space!!!";
       }
       Q->Array =static_cast<int*>(malloc(sizeof(int)*MaxElements));
       if(Q->Array == NULL)
       {
         cout << "out of space!!!";
       }
       Q->Capacity = MaxElements;
       MakeEmpty(Q);
       return Q;
    }
     
    void DisposeQueue(Queue Q)
    {
        if (Q != NULL)
       {
          free(Q->Array );
          free(Q);
       }
    }
     
     
    static int Succ(int Value, Queue Q)  //循环数组,用于回绕
    {
       if(++Value == Q->Capacity )
           Value = 0;
       return Value;
    }
    void Enqueue(int x, Queue Q)
    {
        if(IsFull(Q))
        {
           cout << "Full queue" << endl;
        }
        else
        {
           Q->Size ++;
           Q->Rear = Succ(Q->Rear, Q);
           Q->Array [Q->Rear] = x;
        }
    }
     
     
    int Dequeue(Queue Q)
    {
        if(IsEmpty(Q))
        {
           cout << "Empty Queue" << endl;
           return false;    //仅表示错误
        }
        else
        {
           Q->Size --;
           Q->Front = Succ(Q->Front, Q);
           return Q->Array[(Q->Front)-1];
        }
    }
     
    int Front(Queue Q)
    {
        if(IsEmpty(Q))
        {
           cout << "Empty Queue" << endl;
           return false;    //仅表示错误
        }
        else
        return Q->Array[Q->Front];
    }
     
    
    //////////////////////////邻接表相关函数定义///////////////
    Table Creat_Lable (int MaxElements)    //MaxElements参数为希望创建的节点数
    {
    	
    	Table table1 = static_cast<Table> (malloc(sizeof(struct Led_table)));
    	table1->data = MaxElements;
    	if (table1 == NULL)
    	{
    	   cout << "out of space!!!";
    	}
    
    	table1->firstedge  = static_cast<position*>(malloc(sizeof(position)*(table1->data))); 
    	if (table1->firstedge  == NULL)
    	{
    	   cout << "out of space!!!";
    	}
    
    	//给每个表头赋值,从0开始
    	for (int i = 0; i <= table1->data - 1; ++i)
    	{
    	    table1->firstedge [i] = static_cast<position>(malloc(sizeof(position)));   //申请一个节点
    		if (table1->firstedge [i]  == NULL)
    			{
    			   cout << "out of space!!!";
    			}
    		table1->firstedge [i]->adjvex = 0;   //表头这个参数存储入度
    		table1->firstedge [i]->weight = 0;   //此参数在此时没有意义
    		table1->firstedge [i]->next = NULL;
    
    	}
    	return table1;
    
    }
    
    
    void Insert (Table table1, int v, int w, int weig)   //表示存在一条边为<v,w>,且权重为weig
    {
        position p = static_cast<position>(malloc(sizeof(position)));   //申请一个节点
    	if(p == NULL)
    	{
    	   cout << "out of space!!!";
    	}
    	p->adjvex = w;
        p->weight = weig;
    	p->next = table1->firstedge [v]->next;
    	table1->firstedge [v]->next = p;
    		
    }
    
    void CountIndegree(Table table1)      //计算顶点的入度,存在头结点中
    {
       for(int i = 0; i <= table1->data - 1; ++i)
       {
           position p = table1->firstedge [i]->next;
            while (p != NULL) 
    		{
               ++(table1->firstedge [p->adjvex]->adjvex) ;
                p = p->next;
            }
       }
    }
    
    int* Topsort(Table table1)          //拓扑排序
    {
       Queue queue_1 = CreateQueue(15);   //创建一个列队
       int Counter = 0;
       int *TopNum = static_cast<int*>( malloc (sizeof(int)*(table1->data )));  //此数组用来存储结果
       int v;
       for(int i = 0; i != table1->data; ++i)
       {
          if(table1->firstedge[i]->adjvex == 0)
    	  {
    	     Enqueue(i,queue_1);  //如果顶点i的入度为0,就入队
    	  }
       }
    
       while(!IsEmpty(queue_1))
       {
           v = Dequeue(queue_1);
    	   TopNum[v] = ++Counter;   //若TopNum[5] = 3, 则排第三的为v5
    
    	    position p = table1->firstedge [v]->next;
    
    		while (p != NULL)   //把这个节点删除后,更新入度
    		{
    		  --(table1->firstedge [p->adjvex]->adjvex);
    		  if(table1->firstedge [p->adjvex]->adjvex == 0) Enqueue(p->adjvex,queue_1);
    		   p = p->next;
    		}
    	   
       }
       if(Counter != table1->data )
       {
           cout << "the graph has a cycle" << endl;
       }
       DisposeQueue(queue_1);
       return TopNum;
    }
    
    void print_Topsort_result(int *TopNum,Table table1)   //打印拓扑排序结果
    {
       for(int i = 1; i != table1->data+1 ; ++i)
       {
          for (int j = 0; j != table1->data ; ++j)
    	  {
    	     if (TopNum[j] == i)
    		 {
    			 if(i == table1->data)
    			 {
    			    cout << "v" << j;
    			 }
    			 else
    			 {
    			    cout << "v" << j << "->";
    			 }
    		    
    		 }
    	  }
       }
       cout << endl;
    }
    /////////////////////单源无权算法相关定义/////////////////////////
    typedef struct unweight_path *unweight_node ;
    
    
    
     struct unweight_path     // 
    {  
    	bool know;
        int dist;    // 邻接点域,存储该顶点对应的下标  
        int path;     // 对应边的权值 
    };
    
    unweight_node unweight_init(Table table1, int start)     //节点初始化
    {
    	unweight_node Node  = static_cast<unweight_node>(malloc(sizeof(unweight_path)*(table1->data))); 
    	if (Node  == NULL)
    	{
    	   cout << "out of space!!!";
    	}
    	for(int i = 0; i != table1->data; ++i)
    	{
    	    Node[i].know = false;
    		Node[i].dist = Inf;
    		Node[i].path = 0;
    	}
    	Node[start].dist = 0;
    	return Node;
    }
    
    ////////////////////////单源无权最短路径一般算法,时间复杂度较高////////////////////////////////
    void Unweighted(Table table1,unweight_node Node)
    {
    	int currDist;
    	int v;
    	for(currDist = 0;currDist != table1->data; ++currDist)
    	{
    	   for(v = 0; v != table1->data; ++v )
    	   {
    	      if(!Node[v].know && Node[v].dist == currDist )
    		  {
    		     Node[v].know = true;
    			 position p = table1->firstedge [v]->next;
    			while (p != NULL)   //与这个节点有连接的距离+1
    			{
    			   if(Node[p->adjvex].dist  == Inf)
    			   {
    			      Node[p->adjvex].dist = currDist+1;
    				  Node[p->adjvex].path = v;
    			   }
    			   p = p->next;
    			}
    		  }
    	   }
    	}
      
    }
    ////////////////////////单源无权最短路径改进算法/////////////////////////////
     void Unweighted_change (Table table1,unweight_node Node)
     {
    	 int v;
         Queue queue_1 = CreateQueue(15);   //创建一个列队
    	 for(int i = 0; i != table1->data; ++i)
    	 {
    	     if(Node[i].dist == 0)
    		 {
    		     Enqueue(i,queue_1);
    		 }
    	 }
    	 while(!IsEmpty(queue_1))
    	 {
    	     v = Dequeue(queue_1);
    		 Node[v].know = true;
    		 position p = table1->firstedge [v]->next;
    		while (p != NULL)   //与这个节点有连接的距离+1
    		{
    			if(Node[p->adjvex].dist  == Inf)
    			{
    			    Node[p->adjvex].dist = Node[v].dist +1;
    				Node[p->adjvex].path = v;
    				Enqueue(p->adjvex,queue_1);
    			}
    			p = p->next;
    		}
    	 }
    	 DisposeQueue(queue_1);
    
     }
    int main ()
    {
      Table table_1 = Creat_Lable (7);    //创建一个大小为7的邻接表
    
      //根据图来为邻接表插入数据
      
      Insert (table_1, 0, 1, 2);Insert (table_1, 0, 2, 4);Insert (table_1, 0, 3, 1);
      Insert (table_1, 1, 3, 3);Insert (table_1, 1, 4, 10);
      Insert (table_1, 2, 5, 5);
      Insert (table_1, 3, 2, 2);Insert (table_1, 3, 5, 8);Insert (table_1, 3, 6, 4);
      Insert (table_1, 4, 3, 2);Insert (table_1, 4, 6, 6);
      Insert (table_1, 6, 5, 1);
      
      /////////////////////////测试////////////////////////////////
      unweight_node Node_1 = unweight_init(table_1, 0);
      Unweighted(table_1, Node_1);
      for (int i = 0; i != table_1->data; ++i)
      {
         cout << Node_1[i].dist << '	';
      }
      cout << endl;
      Unweighted_change (table_1, Node_1);
       for (int i = 0; i != table_1->data; ++i)
      {
         cout << Node_1[i].dist << '	';
      }
      cout << endl;
       while(1);
       return 0;
    }
    

      图放在邻接表中。

       上述代码提出了两种方法,区别在于一种用了两次for循环,时间复杂度比较高,另一种采用了列队数据结构,时间复杂度要低,但是两次的结果都一样,如下图所示:

        这种方法还是不错的,主要是要善于使用数据结构。

        夜深了,,,要下雨了。

  • 相关阅读:
    JQ购物车+1-1
    [转载]DATEDIFF() 函数返回两个日期之间的时间
    [转载]js获取当前页面url网址信息
    [转载]Request获取文件路径
    JQ页面跳转
    [转载]Sql Server 日期格式化函数
    [转载]jQuery的attr()与prop()的区别
    [转载]获取验证码60秒倒计时
    [转载]JQ键盘事件
    [转载]SQL常用语句
  • 原文地址:https://www.cnblogs.com/1242118789lr/p/6748075.html
Copyright © 2011-2022 走看看