Chapter 9 Graph (2)

Dijkstra算法實現

/*僞碼描述:
void Dijkstra(Graph G,Table T)
{
     Vertex V,W;
     
     for(; ;)
     {
         V = smallst unknown distance vertex;
	 if(V == NotAVertex)
	    break;
	  T[V].konwn = ture;
	  for each W adjancent to V;
	  if(!T[W}.konwn)
	     if(T[V].dis + Cvw < T[W].dis)
	     {
	        Decrease(T[W].dis to T[V}.dis + Cvw);
		T[W].path = V;
	      }
        }
}
*/
	 

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

#define MaxVertexNum 100
#define INFINITY 65535

typedef int DistType;
typedef int Vertex;
typedef int WeightType;     //邊的權值設爲整數
typedef char DataType;      //頂點的數據存儲
typedef int ElementType;
typedef struct QueueRecord
{
	int Front;
	int Rear;
	int Capacity;
	ElementType *Array;
}*Queue;

void InitQueue(Queue Q)
{
	Q->Front = 0;
	Q->Rear = 0;
}

Queue CreatQueue(int MaxSize)
{
	Queue Q = (QueueRecord*)malloc(sizeof(QueueRecord));
	Q->Capacity = MaxSize;
	Q->Array = (ElementType*)malloc(sizeof(ElementType) * MaxSize);
	InitQueue(Q);
	return Q;
}

int Enqueue(Queue Q, ElementType X)
{
	if ((Q->Rear + 1) % Q->Capacity == Q->Front)
		return -1;
	Q->Rear = (Q->Rear + 1) % Q->Capacity;
	Q->Array[Q->Rear] = X;
	return 0;
}

ElementType Dequeue(Queue Q)
{
	if (Q->Front == Q->Rear)
		return -1;
	Q->Front = (Q->Front + 1) % Q->Capacity;
	return Q->Array[Q->Front];
}

//邊的定義
typedef struct ENode
{
	Vertex V1, V2;       //邊的兩個頂點
	WeightType Weight;   //邊的權重
}*Edge;

//圖的結點定義
typedef struct GNode
{
	int Nv;         //頂點數
	int Ne;         //邊數
	WeightType Weight[MaxVertexNum][MaxVertexNum];   //鄰接矩陣
	DataType Data[MaxVertexNum];     //存頂點的數據
}*MGraph;

//初始化一個圖
MGraph CreateGraph(int VertexNum)
{
	//初始化一個有VertexNum個結點但沒有邊的圖
	Vertex V, W;
	MGraph Graph;

	Graph = (MGraph)malloc(sizeof(GNode));  //建立圖
	Graph->Nv = VertexNum;
	Graph->Ne = 0;

	//初始化鄰接矩陣,將權重置爲∞
	for (V = 0; V <= Graph->Nv; V++)
		for (W = 0; W <= Graph->Nv; W++)
			Graph->Weight[V][W] = INFINITY;

	return Graph;
}

//邊的插入
void InsertEdge(MGraph Graph, Edge E)
{
	Graph->Weight[E->V1][E->V2] = E->Weight;
}

//構建一個圖
MGraph BuildGraph()
{
	MGraph Graph;
	Edge E;
	Vertex V;
	int Nv, i;

	scanf("%d", &Nv);      //讀入頂點個數
	Graph = CreateGraph(Nv);  //初始化一個有VertexNum個結點但沒有邊的圖

	scanf("%d", &(Graph->Ne));  //讀入邊數
	if (Graph->Ne != 0)         //如果有邊
	{
		E = (Edge)malloc(sizeof(ENode));  //建立邊結點
										  //讀入邊,格式爲“起點”,“終點”,“權重”
		for (i = 0; i < Graph->Ne; i++)
		{
			scanf("%d %d %d", &E->V1, &E->V2, &E->Weight);
			InsertEdge(Graph, E);   //插入邊
		}
	}

	return Graph;
}

typedef struct TableNode
{
	int Known;
	DistType Distence;
	Vertex Path;
}Table;


void InitTable(Vertex Start, MGraph Graph, Table *T)
{
	int i;
	for (i = 0; i <= Graph->Nv; i++)
	{
		T[i].Distence = INFINITY;
		T[i].Known = 0;
		T[i].Path = 0;
	}
	T[Start].Distence = 0;
}

Vertex FindMinDist(MGraph Graph, Table *T)
{
	Vertex MinV, V;
	int MinDist = INFINITY;

	for (V = 0; V <= Graph->Nv; V++)
	{
		if (T[V].Known == 0 && T[V].Distence < MinDist)
		{
			MinDist = T[V].Distence;
			MinV = V;
		}
	}
	if (MinDist < INFINITY)
		return MinV;
	else
		return 0;
}

void PrintPath(Vertex V, Table *T)
{
	if (T[V].Path != 0)
	{
		PrintPath(T[V].Path, T);
		printf("to ");       //遞歸出口
	}
	printf("V%d ", V);
}

void Dijkstra(MGraph Graph, Table *T)
{
	Vertex V, W;
	for (;;)
	{
		V = FindMinDist(Graph, T);
		if (V == 0)
			break;
		T[V].Known = 1;
   		for (W = 0; W <= Graph->Nv; W++)
		{
			if(Graph->Weight[V][W] != INFINITY && T[W].Known == 0)
				if (T[V].Distence + Graph->Weight[V][W] < T[W].Distence)
				{
					T[W].Distence = T[V].Distence + Graph->Weight[V][W];
					T[W].Path = V;
				}
		}
	}
}

int main()
{
	MGraph Graph = BuildGraph();
	Table T[MaxVertexNum];
	InitTable(1,Graph,T);
	Dijkstra(Graph, T);
	Vertex V;
	for (V = 1; V <= Graph->Nv; V++)
	{
		printf("The distence of V%d is %d,and the path is ", V,T[V].Distence);
		PrintPath(V, T);
		printf("\n");
	}
	
}
/*
7 12
3 1 4
1 2 2
2 5 10
5 7 6
7 6 1
3 6 5
4 3 2
1 4 1
2 4 3
4 5 2
4 7 4
4 6 8
*/

無權圖的最短路徑

#include <stdio.h>
#include <stdlib.h>
#define MaxVertexNum 100
#define INFINITY 65535

typedef int DistType;
typedef int Vertex;
typedef int WeightType;     //邊的權值設爲整數
typedef char DataType;      //頂點的數據存儲
typedef int ElementType;
typedef struct QueueRecord
{
	int Front;
	int Rear;
	int Capacity;
	ElementType *Array;
}*Queue;

void InitQueue(Queue Q)
{
	Q->Front = 0;
	Q->Rear = 0;
}

Queue CreatQueue(int MaxSize)
{
	Queue Q = (QueueRecord*)malloc(sizeof(QueueRecord));
	Q->Capacity = MaxSize;
	Q->Array = (ElementType*)malloc(sizeof(ElementType) * MaxSize);
	InitQueue(Q);
	return Q;
}

int Enqueue(Queue Q, ElementType X)
{
	if ((Q->Rear + 1) % Q->Capacity == Q->Front)
		return -1;
	Q->Rear = (Q->Rear + 1) % Q->Capacity;
	Q->Array[Q->Rear] = X;
	return 0;
}

ElementType Dequeue(Queue Q)
{
	if (Q->Front == Q->Rear)
		return -1;
	Q->Front = (Q->Front + 1) % Q->Capacity;
	return Q->Array[Q->Front];
}

//邊的定義
typedef struct ENode
{
	Vertex V1, V2;        //有向邊<V1,V2>
}*Edge;

//鄰接點的定義
typedef struct AdjVNode
{
	Vertex AdjV;           //鄰接點下標
	struct AdjVNode *Next; //指向下一鄰接點的指針
}*PtrToAdjVNode;

//頂點表頭結點的定義
typedef struct VNode
{
	PtrToAdjVNode FirstEdge;   //邊表頭指針
	DataType Data;             //存頂點的數據
}AdjList[MaxVertexNum];        //AdjList是鄰接表類型

							   //圖結點的定義
typedef struct GNode
{
	int Nv;     //頂點數
	int Ne;     //邊數
	AdjList G;  //鄰接表
}*LGraph;       //以鄰接表方式存儲圖類型

				//初始化鄰接表圖
LGraph CreateGraph(int VertexNum)
{
	Vertex V;
	LGraph Graph;

	Graph = (LGraph)malloc(sizeof(GNode));
	Graph->Nv = VertexNum;
	Graph->Ne = 0;

	//初始化鄰接表表頭
	for (V = 0; V <= Graph->Nv; V++)    //注意等號
		Graph->G[V].FirstEdge = NULL;

	return Graph;
}

//插入邊
void InsertEdge(LGraph Graph, Edge E)
{
	PtrToAdjVNode NewNode;

	//插入邊<V1,V2>
	//爲V2建立新的鄰接點
	NewNode = (PtrToAdjVNode)malloc(sizeof(AdjVNode));
	NewNode->AdjV = E->V2;
	//將V2插入V1的表頭
	NewNode->Next = Graph->G[E->V1].FirstEdge;
	Graph->G[E->V1].FirstEdge = NewNode;
}

//創建一個鄰接表圖
LGraph BuildGraph()
{
	LGraph Graph;
	Edge E;
	Vertex V;
	int Nv, i;

	scanf("%d", &Nv);          //讀入頂點個數
	Graph = CreateGraph(Nv);   //初始化有Nv個頂點但沒有邊的圖

	scanf("%d", &Graph->Ne);   //讀入邊數
	if (Graph->Ne != 0)        //如果有邊
	{
		E = (Edge)malloc(sizeof(ENode)); //建立邊結點
		for (i = 0; i < Graph->Ne; i++)
		{
			//讀入邊,格式爲“起點”,“終點”,“權重”
			scanf("%d %d", &E->V1, &E->V2);
			InsertEdge(Graph, E);
		}
	}

	return Graph;
}
typedef struct TableNode
{
	int Known;
	DistType Distence;
	Vertex Path;
}Table;


void InitTable(Vertex Start, LGraph Graph, Table *T)
{
	int i;
	for (i = 0; i <= Graph->Nv; i++)
	{
		T[i].Distence = INFINITY;
		T[i].Known = 0;
		T[i].Path = 0;
	}
	T[Start].Distence = 0;
}

void Unweighted(Table *T, LGraph Graph, Vertex S)
{
	Queue Q;
	Q = CreatQueue(Graph->Nv);
	InitQueue(Q);
	Vertex V;

	Enqueue(Q, S);   //將初始點S入隊

	while (Q->Front != Q->Rear)    //隊列非空
	{
		V = Dequeue(Q);        //將一個結點出隊
		T[V].Known = 1;        //標記該結點

		PtrToAdjVNode W;
		//遍歷當前結點的所有鄰接點
		for (W = Graph->G[V].FirstEdge; W; W = W->Next)
		{
			if (T[W->AdjV].Distence == INFINITY)
			{
				T[W->AdjV].Distence = T[V].Distence + 1;
				T[W->AdjV].Path = V;
				Enqueue(Q, W->AdjV);
			}
		}
	}
}

//測試函數
int main()
{
	LGraph Graph = BuildGraph();
	Table  T[MaxVertexNum];
	InitTable(3, Graph, T);

	Unweighted(T, Graph, 3);

	Vertex V;
	for (V = 1; V <= Graph->Nv; V++)
		printf("%d ", T[V].Distence);
}

拓撲排序

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

#define MaxVertexNum 100    //最大頂點數設爲100
typedef int Vertex;         //用頂點下標表示頂點
typedef int WeightType;     //邊的權值設爲整數
typedef char DataType;      //頂點的數據存儲

							//邊的定義
typedef struct ENode
{
	Vertex V1, V2;        //有向邊<V1,V2>
	WeightType Weight;    //權重
}*Edge;

//鄰接點的定義
typedef struct AdjVNode
{
	Vertex AdjV;           //鄰接點下標
	WeightType Weight;     //邊權重
	struct AdjVNode *Next; //指向下一鄰接點的指針
}*PtrToAdjVNode;

//頂點表頭結點的定義
typedef struct VNode
{
	PtrToAdjVNode FirstEdge;   //邊表頭指針
	DataType Data;             //存頂點的數據
}AdjList[MaxVertexNum];        //AdjList是鄰接表類型

							   //圖結點的定義
typedef struct GNode
{
	int Nv;     //頂點數
	int Ne;     //邊數
	AdjList G;  //鄰接表
}*LGraph;       //以鄰接表方式存儲圖類型

				//初始化鄰接表圖
LGraph CreateGraph(int VertexNum)
{
	Vertex V;
	LGraph Graph;

	Graph = (LGraph)malloc(sizeof(GNode));
	Graph->Nv = VertexNum;
	Graph->Ne = 0;

	//初始化鄰接表表頭
	for (V = 0; V < Graph->Nv; V++)
		Graph->G[V].FirstEdge = NULL;

	return Graph;
}

//插入邊
void InsertEdge(LGraph Graph, Edge E)
{
	PtrToAdjVNode NewNode;

	//插入邊<V1,V2>
	//爲V2建立新的鄰接點
	NewNode = (PtrToAdjVNode)malloc(sizeof(AdjVNode));
	NewNode->AdjV = E->V2;
	NewNode->Weight = E->Weight;
	//將V2插入V1的表頭
	NewNode->Next = Graph->G[E->V1].FirstEdge;
	Graph->G[E->V1].FirstEdge = NewNode;

	//若是無向圖,還要插入邊<V2,V1>
	//爲V1建立新的鄰接點
	/*NewNode = (PtrToAdjVNode)malloc(sizeof(AdjVNode));
	NewNode->AdjV = E->V1;
	NewNode->Weight = E->Weight;
	//將V1插入V2的表頭
	NewNode->Next = Graph->G[E->V2].FirstEdge;
	Graph->G[E->V2].FirstEdge = NewNode;*/
}

//創建一個鄰接表圖
LGraph BuildGraph()
{
	LGraph Graph;
	Edge E;
	Vertex V;
	int Nv, i;

	scanf("%d", &Nv);          //讀入頂點個數
	Graph = CreateGraph(Nv);   //初始化有Nv個頂點但沒有邊的圖

	scanf("%d", &Graph->Ne);   //讀入邊數
	if (Graph->Ne != 0)        //如果有邊
	{
		E = (Edge)malloc(sizeof(ENode)); //建立邊結點
		for (i = 0; i < Graph->Ne; i++)
		{
			//讀入邊,格式爲“起點”,“終點”,“權重”
			scanf("%d %d %d", &E->V1, &E->V2, &E->Weight);
			InsertEdge(Graph, E);
		}
	}

	//如果頂點有數據的話,讀入數據
	/*for (V = 0; V < Graph->Nv; V++)
		scanf("%c", &Graph->G[V].Data);
		*/

	return Graph;
}

typedef int ElementType;
typedef struct QueueRecord
{
	int Front;
	int Rear;
	int Capacity;
	ElementType *Array;
}*Queue;

void InitQueue(Queue Q)
{
	Q->Front = 0;
	Q->Rear = 0;
}

Queue CreatQueue(int MaxSize)
{
	Queue Q = (QueueRecord*)malloc(sizeof(QueueRecord));
	Q->Capacity = MaxSize;
	Q->Array = (ElementType*)malloc(sizeof(ElementType) * MaxSize);
	InitQueue(Q);
	return Q;
}

int Enqueue(Queue Q, ElementType X)
{
	if ((Q->Rear + 1) % Q->Capacity == Q->Front)
		return -1;
	Q->Rear = (Q->Rear + 1) % Q->Capacity;
	Q->Array[Q->Rear] = X;
	return 0;
}

ElementType Dequeue(Queue Q)
{
	if (Q->Front == Q->Rear)
		return -1;
	Q->Front = (Q->Front + 1) % Q->Capacity;
	return Q->Array[Q->Front];
}

// 對Graph進行拓撲排序,  TopOrder[]順序存儲排序後的頂點下標
bool TopSort( LGraph Graph, Vertex TopOrder[] )
{  
    int Indegree[MaxVertexNum], Index;
    Vertex V;
    PtrToAdjVNode W;
       Queue Q = CreatQueue( Graph->Nv );
  
    // 初始化Indegree[]
    for (V=0; V<Graph->Nv; V++)
        Indegree[V] = 0;
         
    // 遍歷圖,得到Indegree[]
    for (V=0; V<Graph->Nv; V++)
        for (W=Graph->G[V].FirstEdge; W; W=W->Next)
            Indegree[W->AdjV]++; // 對有向邊<V, W->AdjV>累計終點的入度
             
    // 將所有入度爲0的頂點入列
    for (V=0; V<Graph->Nv; V++)
        if ( Indegree[V]==0 )
            Enqueue(Q, V);
             
    // 下面進入拓撲排序 
    Index = 0; 
    while( Q->Front != Q->Rear){
        V = Dequeue(Q);       // 彈出一個入度爲0的頂點
        TopOrder[Index++] = V; // 將之存爲結果序列的下一個元素
        // 對V的每個鄰接點W->AdjV
        for ( W=Graph->G[V].FirstEdge; W; W=W->Next )
            if ( --Indegree[W->AdjV] == 0 )   // 若刪除V使得W->AdjV入度爲0 
                Enqueue(Q, W->AdjV);          // 則該頂點入列 
    } 
     
    if ( Index != Graph->Nv )
        return false; // 說明圖中有迴路, 返回不成功標誌 
    else
        return true;
}

//測試函數
int main()
{
	LGraph Graph = BuildGraph();
	Vertex Top[MaxVertexNum];
	TopSort(Graph, Top);
	for (Vertex V = 0; V < Graph->Nv; V++)
		printf("%d ", Top[V]);
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章