数据结构笔记之图(ADT)

来源:互联网 发布:java实现会议管理系统 编辑:程序博客网 时间:2024/06/06 00:13

// graph.h#ifndef GRAPH_H#define GRAPH_H// 当前平台#define WINDOWS_VISUALSTUDIO// #define LINUX_GCC// #define MACOS_XCODE#ifdef WINDOWS_VISUALSTUDIO#include <conio.h>#define EXTEND ".txt"#endif#include <stdio.h>#include <stdlib.h>#include <string.h>#define MAX_WEIGHT '\017' // 边的无穷大值#define LEN ((short)256) // Windows、 MacOS、 Linux文件名长度上限255个字符再加串尾'\0' 故长度为256#define KIND_ERROR "图类型输入非法\n"#define VERTEX_ERROR "第%d个顶点输入非法\n"#define EDGE_ERROR "第%d条边的顶点域输入非法\n"#define WEIGHT_ERROR "第%d条边的权值输入非法 或与图类型不匹配\n"#define START_EGUL_END "第%d条边的起点与终点为同一顶点\n"#define SOURCE_EQUL_DEST "起点与终点为同一顶点\n"typedef enum { false, true } bool;typedef short VertexSize; // 顶点数量类型 不可设为有符号数typedef char EdgeSize; // 边数量类型typedef short weight; // 边的权值typedef short square; // square用于邻接矩阵数量单位typedef struct{VertexSize KeyValue; // 顶点名// 此处可添加其他数据类型}VertexValue;typedef struct{VertexValue start, end; // 有向边<start, end>weight Weight; // 权重}EdgeValue;// 边表结点typedef struct enode{VertexValue adjvex; // 邻接点域weight Weight; // 权值struct enode *next; // 链域}EdgeNode;// 顶点表结点typedef struct{VertexValue vexs; // 顶点域EdgeNode *FirstEdge; // 边表头结点}VertexNode;/************** 邻接矩阵 **************/typedef struct{weight *matrix; // 邻接矩阵char FileName[LEN]; // 向文件输出元素的文件名}MGraph;/************** 邻接表 **************/typedef struct{VertexNode *adjlist; // 邻接表char FileName[LEN]; // 向文件输出元素的文件名}ALGraph;/***************** 标准图结构 *****************/typedef struct{VertexValue *base; // 顶点数组地址VertexSize size; // 顶点数量当前值VertexSize MaxSize; // 顶点数量最大值char FileName[LEN]; // 向文件输出元素的文件名}ArrayVertexValue;typedef struct EdgeNode{EdgeValue item;struct EdgeNode *next;}NodeOfEdge;typedef struct{NodeOfEdge *head;NodeOfEdge *tail;EdgeSize size;// 边数量当前值EdgeSize MaxSize; // 边数量最大值char FileName[LEN]; // 向文件输出元素的文件名}LinkEdgeValue;typedef struct{ArrayVertexValue VertexArray; // 顶点数组LinkEdgeValue EdgeLink; // 边链表char kind; // 1无向图 2有向图 3无向网络 4有向网络char FileName[LEN]; // 向文件输出的文件名}Graph;void CreateGraph(Graph * const G, const char kind, char * const FileName);void CreateMGraph(Graph * const G, MGraph * const MG);void CreateALGraph(Graph * const G, ALGraph * const ALG);void DistoryGraph(Graph * const G);void DistoryMGraph(MGraph * const MG);void DistoryALGraph(const Graph * const G, ALGraph * const ALG);void MakeMGraph(const Graph * const G, MGraph * const MG);void MakeALGraph(const Graph * const G, ALGraph * const ALG);void AddVertexOfGraph(Graph * const G, const VertexValue * const NewVertex);void AddEdgeOfGraph(Graph * const G, const EdgeValue * const NewEdge);void DelVertexOfGraph(Graph * const G, const VertexValue * const DelVertex);void DelEdgeOfGraph(Graph * const G, const EdgeValue * const DelEdge);void InputGraphFromFile(Graph * const G);void InputGraphFromKeyboard(Graph * const G);void OutputGraphToFile(const Graph * const G);void OutputMGraphToFile(const Graph * const G, MGraph * const MG);void OutputALGraphToFile(const Graph * const G, ALGraph * const ALG);void OutputGraphToMonitor(const Graph * const G);void OutputMGraphToMonitor(const Graph * const G, MGraph * const MG, FILE * const stream);void OutputALGraphToMonitor(const Graph * const G, ALGraph * const ALG, FILE * const stream);void DfsTraverseByMGraph(const Graph * const G, const MGraph * const MG, const VertexValue * const entrance, FILE * const stream);void BfsTraverseByMGraph(const Graph * const G, const MGraph * const MG, const VertexValue * const entrance, FILE * const stream);void DfsTraverseByALGraph(const Graph * const G, const ALGraph * const ALG, const VertexValue * const entrance, FILE * const stream);void BfsTraverseByALGraph(const Graph * const G, const ALGraph * const ALG, const VertexValue * const entrance, FILE * const stream);void UnweightedByMGraph(const Graph * const G, const MGraph * const MG, const VertexValue * const source, const VertexValue * const dest, FILE * const stream);void UnweightedByALGraph(const Graph * const G, const ALGraph * const ALG, const VertexValue * const source, const VertexValue * const dest, FILE * const stream);void DijkstraByMGraph(const Graph * const G, const MGraph * const MG, const VertexValue * const source, const VertexValue * const dest, FILE * const stream);void DijkstraByALGraph(const Graph * const G, const ALGraph * const ALG, const VertexValue * const source, const VertexValue * const dest, FILE * const stream);void FloydByMGraph(const Graph * const G, const MGraph * const MG, const VertexValue * const source, const VertexValue * const dest, FILE * const stream);void FloydByALGraph(const Graph * const G, const ALGraph * const ALG, const VertexValue * const source, const VertexValue * const dest, FILE * const stream);void PrimByMGraph(const Graph * const G, const MGraph * const MG, const VertexValue * const root); void PrimByALGraph(const Graph * const G, const ALGraph * const ALG, const VertexValue * const root);void KruskalMGraph(const Graph * const G, const MGraph * const MG);void KruskalALGraph(const Graph * const G, const ALGraph * const ALG);void UnusualToExit(const char * const str, const char * const FileName);#endif

// graph.c// 图的顶点必须以0起始#include "graph.h"#include "StackOfGraph.h"#include "QueueOfGraph.h"#include "VertexArrayOfGraph.h"#include "EdgeArrayOfGraph.h"#include "EdgeLinkOfGraph.h"#include "Heap.h"const char * const EofOperation = "\nPlease enter:\tPress Ctrl + %c in new line to end\n";const char * const ReadOperation = "r";const char * const WriteOperation = "w";const char * const MemoryError = "Memory is not enough !\n";const char * const OpenFileError = "can not open %s !\n";const char * const CloseFileError = "Error in closing file %s\n";const char * const EmptyArray = "空数组\n";const char * const FullArray = "满数组\n";const char * const NullPointer = "空指针\n";const char * const NameTooLong = "FileName too long\n";const char ImpossibleValue = -1;// ( ( 2 ^ ( sizeof ( VertexSize ) * 8 - 1 ) ) - 1 )const VertexSize VertexMax = (1 << ((sizeof(VertexSize) << 3) - 1)) - 1;// ( ( 2 ^ ( sizeof ( EdgeSize ) * 8 - 1 ) ) - 1 )const EdgeSize EdgeMax = (1 << ((sizeof(EdgeSize) << 3) - 1)) - 1;// ( ( 2 ^ ( sizeof ( weight ) * 8 - 1 ) ) - 1 )const weight WeightMax = (1 << ((sizeof(weight) << 3) - 1)) - 1;static const char * const MgString =  "MG Of ";static const char * const AlgString = "ALG Of ";static const char * const CanNotToDest = "顶点%d至顶点%d不连通\n\n";static const char * const FullWeight =  "请扩充weight数据单位\n";static const char * const MstFailure = "无法建立最小生成树\n";static const char * const EmptyGraph = "空图\n";static const char * const KindOfGraph[4] ={"无向图","有向图","无向网络图","有向网络图"};static void MakeVertexOfMGraph(const Graph * const G, MGraph * const MG);static void MakeEdgeOfMGraph(const Graph * const G, MGraph * const MG);static void MakeVertexOfALGraph(const Graph * const G, ALGraph * const ALG);static void MakeEdgeOfALGraph(const Graph * const G, ALGraph * const ALG);static void DfsByMGraph(const Graph * const G, const MGraph * const MG, bool * const visited, const VertexSize i, FILE * const stream);static void DfsByALGraph(const ALGraph * const ALG, bool * const visited, const VertexSize i, FILE * const stream);static void ShowPath(const Graph * const G, const VertexSize * const path, const VertexValue * const source, const VertexValue * const dest, FILE * const stream);static VertexSize FindMinDistWithDijkstra(const Graph * const G, const weight * const dist, const bool * const collected);static void ShowAllPathWithFloyd(const Graph * const G, const VertexSize * const path, const VertexValue * const source, const VertexValue * const dest, FILE * const stream);static void ShowPathWithFloyd(const Graph * const G, const VertexSize * const path, const VertexSize s, const VertexSize d, FILE * const stream);static VertexSize FindMinDistWithPrim(const Graph * const G, const weight * const dist);static void AddVertexOfMSTGraph(Graph * const G, const VertexValue * const NewVertex);static void AddEdgeOfMSTGraph(Graph * const G, const EdgeValue * const NewEdge);static void CreateializeVSet(VertexSize * const VSet, const VertexSize size);static void GetEdge(EdgeArrayList * const H);static bool CheckCycle(VertexSize * const VSet, const EdgeValue * const Edge);static VertexSize Find(VertexSize * const VSet, const VertexSize n);static void Union(VertexSize * const VSet, const VertexSize * const Root1, const VertexSize * const Root2);void CreateGraph(Graph * const G, const char kind, char * const FileName){// if (G != NULL)if (G){#ifdef WINDOWS_VISUALSTUDIOstrncpy_s(G->FileName, _countof(G->FileName), FileName, strlen(FileName) + 1);#endif#ifndef WINDOWS_VISUALSTUDIOstrncpy(G->FileName, FileName, strlen(FileName) + 1);#endifCreateListByVertexArray(&(G->VertexArray), VertexMax, G->FileName);CreateListByEdgeLink(&(G->EdgeLink), EdgeMax, G->FileName);if ((kind < 5) && (kind > 0))G->kind = kind;elseUnusualToExit(KIND_ERROR, NULL);}// if (G == NULL)elseUnusualToExit(NullPointer, NULL);}void CreateMGraph(Graph * const G, MGraph * const MG){// if (G != NULL && MG != NULL)if (G && MG){MG->matrix = NULL;#ifdef WINDOWS_VISUALSTUDIOstrncpy_s(MG->FileName, _countof(MG->FileName), MgString, strlen(MgString) + 1);strncat_s(MG->FileName, _countof(MG->FileName), G->FileName, strlen(G->FileName) + 1);if (strlen(MG->FileName) + strlen(EXTEND) <= LEN - 1)strncat_s(MG->FileName, _countof(MG->FileName), EXTEND, strlen(EXTEND) + 1);// if (strlen(MG->FileName) + strlen(EXTEND) > LEN - 1)else#endif#ifndef WINDOWS_VISUALSTUDIOstrncpy(MG->FileName, MgString, strlen(MgString) + 1);strncat(MG->FileName, G->FileName, strlen(G->FileName) + 1);if (strlen(MG->FileName) > LEN - 1)#endifUnusualToExit(NameTooLong, NULL);}// if (G == NULL || MG == NULL)elseUnusualToExit(NullPointer, NULL);}void CreateALGraph(Graph * const G, ALGraph * const ALG){// if (G != NULL && ALG != NULL)if (G && ALG){ALG->adjlist = NULL;#ifdef WINDOWS_VISUALSTUDIOstrncpy_s(ALG->FileName, _countof(ALG->FileName), AlgString, strlen(AlgString) + 1);strncat_s(ALG->FileName, _countof(ALG->FileName), G->FileName, strlen(G->FileName) + 1);if (strlen(ALG->FileName) + strlen(EXTEND) <= LEN - 1)strncat_s(ALG->FileName, _countof(ALG->FileName), EXTEND, strlen(EXTEND) + 1);// if (strlen(ALG->FileName) + strlen(EXTEND) > LEN - 1)else#endif#ifndef WINDOWS_VISUALSTUDIOstrncpy(ALG->FileName, AlgString, strlen(AlgString) + 1);strncat(ALG->FileName, G->FileName, strlen(G->FileName) + 1);if (strlen(ALG->FileName) > LEN - 1)#endifUnusualToExit(NameTooLong, NULL);}// if (G == NULL || ALG == NULL)elseUnusualToExit(NullPointer, NULL);}void DistoryGraph(Graph * const G){// if (G != NULL)if (G){DestroyListByVertexArray(&(G->VertexArray));DestoryListByEdgeLink(&(G->EdgeLink));G->kind = 0;}// if (G == NULL)elseUnusualToExit(NullPointer, NULL);}void DistoryMGraph(MGraph * const MG){// if (MG != NULL)if (MG){free(MG->matrix);}// if (MG == NULL)elseUnusualToExit(NullPointer, NULL);}void DistoryALGraph(const Graph * const G, ALGraph * const ALG){// if (G != NULL && ALG != NULL)if (G && ALG){VertexSize i;EdgeNode *ptr, *save;for (i = 0; i < G->VertexArray.size; ++i){ptr = ALG->adjlist[i].FirstEdge;// while (ptr != NULL)while (ptr){save = ptr->next;free(ptr);ptr = save;}}free(ALG->adjlist);}// if (G == NULL || ALG == NULL)elseUnusualToExit(NullPointer, NULL);}void MakeMGraph(const Graph * const G, MGraph * const MG){// if (G != NULL && MG != NULL)if (G && MG){MakeVertexOfMGraph(G, MG);MakeEdgeOfMGraph(G, MG);}// if (G == NULL && MG == NULL)elseUnusualToExit(NullPointer, NULL);}void MakeALGraph(const Graph * const G, ALGraph * const ALG){// if (G != NULL && ALG != NULL)if (G && ALG){MakeVertexOfALGraph(G, ALG);MakeEdgeOfALGraph(G, ALG);}// if (G == NULL && ALG == NULL)elseUnusualToExit(NullPointer, NULL);}void AddVertexOfGraph(Graph * const G, const VertexValue * const NewVertex){// if (G != NULL && NewVertex != NULL)if (G && NewVertex){if (NewVertex->KeyValue == G->VertexArray.size) // 必须以0 1 2 3的递增顺序输入顶点AddTailListByVertexArray(&(G->VertexArray), NewVertex);else{fprintf(stderr, VERTEX_ERROR, NewVertex->KeyValue);#ifdef WINDOWS_VISUALSTUDIO_getch();#endifexit(EXIT_FAILURE); // exit (1);}}// if (G == NULL || NewVertex == NULL)elseUnusualToExit(NullPointer, NULL);}void AddEdgeOfGraph(Graph * const G, const EdgeValue * const NewEdge){// if (G != NULL && NewEdge != NULL)if (G && NewEdge){if ((NewEdge->start.KeyValue >= 0) && (NewEdge->start.KeyValue < G->VertexArray.size) && (NewEdge->end.KeyValue >= 0) && (NewEdge->end.KeyValue < G->VertexArray.size)){// if (((G->kind < 3) && (NewEdge->Weight == 0)) || ((G->kind > 2) && (NewEdge->Weight > 0) && (NewEdge->Weight < WeightMax)))if (((G->kind < 3) && (!NewEdge->Weight)) || ((G->kind > 2) && (NewEdge->Weight > 0) && (NewEdge->Weight < WeightMax))){if (NewEdge->start.KeyValue != NewEdge->end.KeyValue)AddTailListByEdgeLink(&(G->EdgeLink), NewEdge);// if (NewEdge->start.KeyValue == NewEdge->end.KeyValue)else{fprintf(stderr, START_EGUL_END, G->EdgeLink.size + 1);#ifdef WINDOWS_VISUALSTUDIO_getch();#endifexit(EXIT_FAILURE); // exit (1);}}else if ((G->kind > 2) && (NewEdge->Weight == WeightMax)) // 若无需Dijkstra及Prim功能可删除此条件UnusualToExit(FullWeight, NULL);else{fprintf(stderr, WEIGHT_ERROR, G->EdgeLink.size + 1);#ifdef WINDOWS_VISUALSTUDIO_getch();#endifexit(EXIT_FAILURE); // exit (1);}}else{fprintf(stderr, EDGE_ERROR, G->EdgeLink.size + 1);#ifdef WINDOWS_VISUALSTUDIO_getch();#endifexit(EXIT_FAILURE); // exit (1);}}// if (G == NULL || NewEdge == NULL)elseUnusualToExit(NullPointer, NULL);}void DelVertexOfGraph(Graph * const G, const VertexValue * const DelVertex){// if (G != NULL && DelVertex != NULL)if (G && DelVertex){if (DelVertex->KeyValue < G->VertexArray.size){// 删除指定边 若指定边的点为最末点改为指定点DelStartOrEndOfTheEdgeByLink(&(G->EdgeLink), &(DelVertex->KeyValue), G->VertexArray.size - 1);// 删除指定点 并将最末点改为指定点DelSearchListByArray(&(G->VertexArray), DelVertex);}}// if (G == NULL || DelVertex == NULL)elseUnusualToExit(NullPointer, NULL);}void DelEdgeOfGraph(Graph * const G, const EdgeValue * const DelEdge){// if (G != NULL && DelEdge != NULL)if (G && DelEdge){DelSearchListByLink(&(G->EdgeLink), DelEdge);}// if (G == NULL || DelEdge == NULL)elseUnusualToExit(NullPointer, NULL);}void InputGraphFromFile(Graph * const G){// if (G != NULL)if (G){InputListByArrayFromFile(G);// if (G->VertexArray.size != 0)if (G->VertexArray.size) // 若顶点数非0InputListByLinkFromFile(G);}// if (G == NULL)elseUnusualToExit(NullPointer, NULL);}void InputGraphFromKeyboard(Graph * const G){// if (G != NULL)if (G){InputListByArrayFromKeyboard(G, stdin);// if (G->VertexArray.size != 0)if (G->VertexArray.size) // 若顶点数非0InputListByLinkFromKeyboard(G, stdin);}// if (G == NULL)elseUnusualToExit(NullPointer, NULL);}void OutputGraphToFile(const Graph * const G){// if (G != NULL)if (G){OutputListByVertexArrayToFile(&G->VertexArray);OutputListByEdgeLinkToFile(&G->EdgeLink);}// if (G == NULL)elseUnusualToExit(NullPointer, NULL);}void OutputMGraphToFile(const Graph * const G, MGraph * const MG){// if (G != NULL && MG != NULL && WriteOperation != NULL)if (G && MG && WriteOperation){#ifdef WINDOWS_VISUALSTUDIOFILE *fp;errno_t err = fopen_s(&fp, MG->FileName, WriteOperation);// if (err == 0)if (!err)OutputMGraphToMonitor(G, MG, fp);// if (err == 1)elseUnusualToExit(OpenFileError, MG->FileName);// if (fp != NULL)if (fp){// if (fclose(fp) != 0)if (fclose(fp))UnusualToExit(CloseFileError, MG->FileName);}#endif#ifndef WINDOWS_VISUALSTUDIOFILE * const fp = fopen(MG->FileName, WriteOperation);// if (fp != NULL)if (fp)OutputMGraphToMonitor(G, MG, fp);// if (fp == NULL)elseUnusualToExit(OpenFileError, MG->FileName);// if (fclose(fp) != 0)if (fclose(fp))UnusualToExit(CloseFileError, MG->FileName);#endif}// if (G == NULL || MG == NULL || WriteOperation == NULL)elseUnusualToExit(NullPointer, NULL);}void OutputALGraphToFile(const Graph * const G, ALGraph * const ALG){// if (G != NULL && ALG != NULL && WriteOperation != NULL)if (G && ALG && WriteOperation){#ifdef WINDOWS_VISUALSTUDIOFILE *fp;errno_t err = fopen_s(&fp, ALG->FileName, WriteOperation);// if (err == 0)if (!err)OutputALGraphToMonitor(G, ALG, fp);// if (err == 1)elseUnusualToExit(OpenFileError, ALG->FileName);// if (fp != NULL)if (fp){// if (fclose(fp) != 0)if (fclose(fp))UnusualToExit(CloseFileError, ALG->FileName);}#endif#ifndef WINDOWS_VISUALSTUDIOFILE * const fp = fopen(ALG->FileName, WriteOperation);// if (fp != NULL)if (fp)OutputALGraphToMonitor(G, ALG, fp);// if (fp == NULL)elseUnusualToExit(OpenFileError, ALG->FileName);// if (fclose(fp) != 0)if (fclose(fp))UnusualToExit(CloseFileError, ALG->FileName);#endif}// if (G == NULL || ALG == NULL || WriteOperation == NULL)elseUnusualToExit(NullPointer, NULL);}void OutputGraphToMonitor(const Graph * const G){// if (G != NULL)if (G){OutputListByVertexArrayToMonitor(&(G->VertexArray), stdout);OutputListByEdgeLinkToMonitor(&(G->EdgeLink), stdout);}// if (G == NULL)elseUnusualToExit(NullPointer, NULL);}void OutputMGraphToMonitor(const Graph * const G, MGraph * const MG, FILE * const stream){// if (G != NULL && MG != NULL && stream != NULL)if (G && MG && stream){fprintf(stream, "%d个顶点\t\t%d条边\t\t%s\t", G->VertexArray.size, G->EdgeLink.size, KindOfGraph[(G->kind) - 1]);// if (G->VertexArray.size != 0)if (G->VertexArray.size){// if (G->kind == 3 || G->kind == 4)if (G->kind > 2) // 无向网络 或 有向网络{weight TotalWeight = 0;const NodeOfEdge *pointer = G->EdgeLink.head;// while (pointer != NULL)while (pointer){TotalWeight += pointer->item.Weight;pointer = pointer->next;}if (TotalWeight > 0 && TotalWeight <= WeightMax)fprintf(stream, "权值和: %d", TotalWeight);elseUnusualToExit(FullWeight, NULL);}fprintf(stream, "\n\n");VertexSize line;fprintf(stream, "邻接矩阵:\n");fprintf(stream, "      ");for (line = 0; line < G->VertexArray.size; ++line)fprintf(stream, "(%3hu) ", G->VertexArray.base[line].KeyValue);putc('\n', stream);for (line = 0; line < G->VertexArray.size; ++line){fprintf(stream, "(%3hu) ", G->VertexArray.base[line].KeyValue);VertexSize column;for (column = 0; column < G->VertexArray.size; ++column){if (G->kind > 2) // 无向网络图 或 有向网络图{if (MG->matrix[line * G->VertexArray.size + column] == ImpossibleValue)fprintf(stream, "%5c ", MAX_WEIGHT);elsefprintf(stream, "%5hu ", MG->matrix[line * G->VertexArray.size + column]);}// if (G->kind <= 2)else // 无向图 或 有向图fprintf(stream, "%5hu ", MG->matrix[line * G->VertexArray.size + column]);}fprintf(stream, "(%3hu)\n", G->VertexArray.base[line].KeyValue);}fprintf(stream, "      ");for (line = 0; line < G->VertexArray.size; ++line)fprintf(stream, "(%3hu) ", G->VertexArray.base[line].KeyValue);putc('\n', stream);DfsTraverseByMGraph(G, MG, &(G->VertexArray.base[0]), stream);BfsTraverseByMGraph(G, MG, &(G->VertexArray.base[0]), stream);}}// if (G == NULL || MG == NULL || stream == NULL)elseUnusualToExit(NullPointer, NULL);}void OutputALGraphToMonitor(const Graph * const G, ALGraph * const ALG, FILE * const stream){// if (G != NULL && ALG != NULL && stream != NULL)if (G && ALG && stream){fprintf(stream, "%d个顶点\t\t%d条边\t\t%s\t", G->VertexArray.size, G->EdgeLink.size, KindOfGraph[(G->kind) - 1]);// if (G->VertexArray.size != 0)if (G->VertexArray.size){// if (G->kind == 3 || G->kind == 4)if (G->kind > 2) // 无向网络 或 有向网络{weight TotalWeight = 0;const NodeOfEdge *pointer = G->EdgeLink.head;// while (pointer != NULL)while (pointer){TotalWeight += pointer->item.Weight;pointer = pointer->next;}if (TotalWeight > 0 && TotalWeight <= WeightMax)fprintf(stream, "权值和: %d", TotalWeight);elseUnusualToExit(FullWeight, NULL);}fprintf(stream, "\n\n");fprintf(stream, "\n邻接表:\n");VertexSize i;for (i = 0; i < G->VertexArray.size; ++i){fprintf(stream, "(%hu)\t", ALG->adjlist[i].vexs.KeyValue);const EdgeNode *p = ALG->adjlist[i].FirstEdge;// if (p == NULL)if (!p)putc('\n', stream);// while (p != NULL)while (p){fprintf(stream, "%3hu", p->adjvex.KeyValue);if (G->kind > 2)fprintf(stream, "[%2d]", p->Weight);p->next ? putc(' ', stream) : putc('\n', stream);p = p->next;}}DfsTraverseByALGraph(G, ALG, &(G->VertexArray.base[0]), stream);BfsTraverseByALGraph(G, ALG, &(G->VertexArray.base[0]), stream);}}// if (G == NULL || ALG == NULL || stream == NULL)elseUnusualToExit(NullPointer, NULL);}// 邻接矩阵的深度优先搜索遍历void DfsTraverseByMGraph(const Graph * const G, const MGraph * const MG, const VertexValue * const entrance, FILE * const stream){// if (G != NULL && MG != NULL && entrance != NULL && stream != NULL)if (G && MG && entrance && stream){// if (G->VertexArray.size != 0)if (G->VertexArray.size){// 邻接矩阵bool * const visited = (bool *)malloc(G->VertexArray.size * sizeof(bool));// if (visited != NULL)if (visited){fputs("\n邻接矩阵的深度优先搜索:\n", stream);VertexSize i;for (i = 0; i < G->VertexArray.size; ++i)visited[i] = false; // 全部顶点未访问DfsByMGraph(G, MG, visited, entrance->KeyValue, stream);free(visited);}// if (visited == NULL)elseUnusualToExit(MemoryError, NULL);}// if (G->VertexArray.size == 0)elseUnusualToExit(EmptyGraph, NULL);}// if (G == NULL || MG == NULL || entrance == NULL || stream == NULL)elseUnusualToExit(NullPointer, NULL);}// 邻接矩阵的广度优先搜索遍历void BfsTraverseByMGraph(const Graph * const G, const MGraph * const MG, const VertexValue * const entrance, FILE * const stream){// if (G != NULL && MG != NULL && entrance != NULL && stream != NULL)if (G && MG && entrance && stream){// if (G->VertexArray.size != 0)if (G->VertexArray.size){VertexSize i, j;LinkList Q;bool * const visited = (bool *)malloc(G->VertexArray.size * sizeof(bool));// if (visited != NULL)if (visited){fputs("\n邻接矩阵的广度优先搜索:\n", stream);for (i = 0; i < G->VertexArray.size; ++i)visited[i] = false; // 全部顶点未访问CreateListByLink(&Q, G->VertexArray.size, NULL);fprintf(stream, "访问 顶点:%hu\n", entrance->KeyValue);visited[entrance->KeyValue] = true;EnQueueByLink(&Q, entrance->KeyValue); // 入队// while (Q.size != 0)while (Q.size) // 队列为空则循环终止{DeQueueByLink(&Q, &i); // 队列不空则出队// 将顶点G->VertexArray.base[i]的直接邻接顶点入队for (j = 0; j < G->VertexArray.size; ++j)// if (MG->matrix[i * G->VertexArray.size + j] != 0 && MG->matrix[i * G->VertexArray.size + j] != ImpossibleValue && visited[j] == false)if (MG->matrix[i * G->VertexArray.size + j] && MG->matrix[i * G->VertexArray.size + j] != ImpossibleValue && !visited[j]){fprintf(stream, "访问 顶点:%hu\n", j);visited[j] = true;EnQueueByLink(&Q, j); // 入队}}fprintf(stream, "\n\n");DestoryListByLink(&Q);free(visited);}// if (visited == NULL)elseUnusualToExit(MemoryError, NULL);}// if (G->VertexArray.size == 0)elseUnusualToExit(EmptyGraph, NULL);}// if (G == NULL || MG == NULL || entrance == NULL || stream == NULL)elseUnusualToExit(NullPointer, NULL);}// 邻接表的深度优先搜索遍历void DfsTraverseByALGraph(const Graph * const G, const ALGraph * const ALG, const VertexValue * const entrance, FILE * const stream){// if (G != NULL && ALG != NULL && entrance != NULL && stream != NULL)if (G && ALG && entrance && stream){// if (G->VertexArray.size != 0)if (G->VertexArray.size){// 邻接表bool * const visited = (bool *)malloc(G->VertexArray.size * sizeof(bool));// if (visited != NULL)if (visited){fputs("\n邻接表的深度优先搜索:\n", stream);VertexSize i;for (i = 0; i < G->VertexArray.size; ++i)visited[i] = false; // 全部顶点未访问DfsByALGraph(ALG, visited, entrance->KeyValue, stream);free(visited);}// if (visited == NULL)elseUnusualToExit(MemoryError, NULL);}// if (G->VertexArray.size == 0)elseUnusualToExit(EmptyGraph, NULL);}// if (G == NULL || ALG == NULL || entrance == NULL || stream == NULL)elseUnusualToExit(NullPointer, NULL);}// 邻接表的广度优先搜索遍历void BfsTraverseByALGraph(const Graph * const G, const ALGraph * const ALG, const VertexValue * const entrance, FILE * const stream){// if (G != NULL && ALG != NULL && entrance != NULL && stream != NULL)if (G && ALG && entrance && stream){// if (G->VertexArray.size != 0)if (G->VertexArray.size){VertexSize i;LinkList Q;const EdgeNode *p;bool * const visited = (bool *)malloc(G->VertexArray.size * sizeof(bool));// if (visited != NULL)if (visited){for (i = 0; i < G->VertexArray.size; ++i)visited[i] = false; // 全部顶点未访问CreateListByLink(&Q, G->VertexArray.size, NULL);fputs("\n邻接表的广度优先搜索:\n", stream);fprintf(stream, "访问 顶点:%hu\n", entrance->KeyValue);visited[entrance->KeyValue] = true;EnQueueByLink(&Q, entrance->KeyValue); // 访问顶点entrance后,将其入队   // while (Q.size != 0)while (Q.size) // 队列为空则循环终止{DeQueueByLink(&Q, &i); // 队列不空则出队列p = ALG->adjlist[i].FirstEdge; // 取顶点的首个邻接顶点   // while (p != NULL)while (p) // 若邻接顶点p存在{// if (visited[p->adjvex.KeyValue] == false)if (!visited[p->adjvex.KeyValue]){fprintf(stream, "访问 顶点:%hu\n", p->adjvex.KeyValue); // 访问visited[p->adjvex.KeyValue] = true;EnQueueByLink(&Q, p->adjvex.KeyValue); // 入队}p = p->next;}}fprintf(stream, "\n\n");DestoryListByLink(&Q);free(visited);}// if (visited == NULL)elseUnusualToExit(MemoryError, NULL);}// if (G->VertexArray.size == 0)elsefputs(EmptyGraph, stderr);}// if (G == NULL || ALG == NULL || entrance == NULL || stream == NULL)elseUnusualToExit(NullPointer, NULL);}// 邻接矩阵存储 - 无向图 或 有向图的单源最短路径算法void UnweightedByMGraph(const Graph * const G, const MGraph * const MG, const VertexValue * const source, const VertexValue * const dest, FILE * const stream){// if (G != NULL && MG != NULL && source != NULL && dest != NULL && stream != NULL)if (G && MG && source && dest && stream){// if (G->kind == 1 || G->kind == 2)if (G->kind < 3) // 无向图 或 有向图{// if (G->VertexArray.size !=0)if (G->VertexArray.size){if (source->KeyValue != dest->KeyValue) // 起点与终点不一致{// dist[dest] 为 顶点source->KeyValue至顶点dest->KeyValue的最少顶点数VertexSize * const dist = (VertexSize *)malloc(G->VertexArray.size * sizeof(VertexSize));// path[dest] 为 顶点source->KeyValue至顶点dest->KeyValue的路径上顶点dest->KeyValue的前一个顶点值VertexSize * const path = (VertexSize *)malloc(G->VertexArray.size * sizeof(VertexSize));// if (dist != NULL && path != NULL)if (dist && path){VertexSize i, from;LinkList Q;CreateListByLink(&Q, G->VertexArray.size, NULL);for (i = 0; i < G->VertexArray.size; ++i)dist[i] = ImpossibleValue; // dist数组初始化为不可能的值dist[source->KeyValue] = 0; // 起始点至起始点的顶点数为0path[source->KeyValue] = source->KeyValue;EnQueueByLink(&Q, source->KeyValue); // 将起始点入队 // while (Q.size != 0) while (Q.size) // 队空搜索结束{DeQueueByLink(&Q, &from); // 出队for (i = 0; i < G->VertexArray.size; ++i){// if (MG->matrix[from * G->VertexArray.size + i] != 0 && (dist[i] == ImpossibleValue))if (MG->matrix[from * G->VertexArray.size + i] && (dist[i] == ImpossibleValue)) // 若顶点i为顶点from的直接邻接点{dist[i] = dist[from] + 1;path[i] = from;EnQueueByLink(&Q, i); // 入队}}}if (dist[dest->KeyValue] != ImpossibleValue){ShowPath(G, path, source, dest, stream);fprintf(stream, "经过%d个顶点\n\n", dist[dest->KeyValue]);}// if (dist[dest->KeyValue] == ImpossibleValue)elsefprintf(stream, CanNotToDest, source->KeyValue, dest->KeyValue);free(dist);free(path);DestoryListByLink(&Q);}// if (dist == NULL || path == NULL)elseUnusualToExit(MemoryError, NULL);}// if (source->KeyValue == dest->KeyValue)elseUnusualToExit(SOURCE_EQUL_DEST, NULL);}// if (G->VertexArray.size == 0)elseUnusualToExit(EmptyGraph, NULL);}}// if (G == NULL || MG == NULL || source == NULL || dest == NULL || stream == NULL)elseUnusualToExit(NullPointer, NULL);}// 邻接表存储 - 无向图 或 有向图的单源最短路径算法void UnweightedByALGraph(const Graph * const G, const ALGraph * const ALG, const VertexValue * const source, const VertexValue * const dest, FILE * const stream){// if (G != NULL && ALG != NULL && source != NULL && dest != NULL && stream != NULL)if (G && ALG && source && dest && stream){// if (G->kind == 1 || G->kind == 2) if (G->kind < 3) // 无向图 或 有向图{// if (G->VertexArrayu.size != 0)if (G->VertexArray.size){if (source->KeyValue != dest->KeyValue) // 起点与终点不一致{// dist[dest] 为 顶点source至顶点dest的最少顶点数VertexSize * const dist = (VertexSize *)malloc(G->VertexArray.size * sizeof(VertexSize));// path[dest] 为 顶点source至顶点dest的路径上顶点dest的前一个顶点值VertexSize * const path = (VertexSize *)malloc(G->VertexArray.size * sizeof(VertexSize));// if (dist != NULL && path != NULL)if (dist && path){VertexSize i, from;LinkList Q;const EdgeNode *P;CreateListByLink(&Q, G->VertexArray.size, NULL);for (i = 0; i < G->VertexArray.size; ++i)dist[i] = ImpossibleValue; // dist数组初始化为不可能的值dist[source->KeyValue] = 0; // 起始点至起始点的距离为0path[source->KeyValue] = source->KeyValue;EnQueueByLink(&Q, source->KeyValue); // 将起始点入队 // while (Q.size != 0)while (Q.size){DeQueueByLink(&Q, &from); // 出队P = ALG->adjlist[from].FirstEdge;// while (P != NULL)while (P){if (dist[P->adjvex.KeyValue] == ImpossibleValue) // 若顶点P->adjvex.KeyValue尚未被访问{dist[P->adjvex.KeyValue] = dist[from] + 1; // source到P->adjvex.KeyValue的距离更新 path[P->adjvex.KeyValue] = from; // 将from记录在source到P->adjvex.KeyValue的路径上EnQueueByLink(&Q, P->adjvex.KeyValue); // 入队}P = P->next;}}if (dist[dest->KeyValue] != ImpossibleValue){ShowPath(G, path, source, dest, stream);fprintf(stream, "经过%d个顶点\n\n", dist[dest->KeyValue]);}// if (dist[dest->KeyValue] == ImpossibleValue)elsefprintf(stream, CanNotToDest, source->KeyValue, dest->KeyValue);free(dist);free(path);DestoryListByLink(&Q);}// if (dist == NULL || path == NULL)elseUnusualToExit(MemoryError, NULL);}// if (source->KeyValue == dest->KeyValue)else // 起点与终点一致UnusualToExit(SOURCE_EQUL_DEST, NULL);}// if (G->VertexArray.size == 0)elseUnusualToExit(EmptyGraph, NULL);}}// if (G == NULL || ALG == NULL || source == NULL || dest == NULL || stream == NULL)elseUnusualToExit(NullPointer, NULL);}// 邻接矩阵存储 - 无向网络图 或 有向网络图的单源最短路径算法void DijkstraByMGraph(const Graph * const G, const MGraph * const MG, const VertexValue * const source, const VertexValue * const dest, FILE * const stream){// if (G != NULL && MG != NULL && source != NULL && dest != NULL && stream != NULL)if (G && MG && source && dest && stream){// if (G->kind == 3 || G->kind == 4) if (G->kind > 2) // 无向网络 或 有向网络{// if (G->VertexArray.size != 0)if (G->VertexArray.size){if (source->KeyValue != dest->KeyValue){// dist[dest] 为 顶点source至顶点dest的最小权重值weight * const dist = (weight *)malloc(G->VertexArray.size * sizeof(weight));// path[dest] 为 顶点source至顶点dest的路径上顶点dest的前一个顶点值VertexSize * const path = (VertexSize *)malloc(G->VertexArray.size * sizeof(VertexSize));// collected[i] == true顶点i已被收录// collected[i] == false顶点i未被收录bool * const collected = (bool *)malloc(G->VertexArray.size * sizeof(bool));// if (dist != NULL && path != NULL && collected != NULL)if (dist && path && collected){VertexSize i, j;// 初始化for (i = 0; i < G->VertexArray.size; ++i){if (MG->matrix[(source->KeyValue) * G->VertexArray.size + i] != ImpossibleValue){dist[i] = MG->matrix[(source->KeyValue) * G->VertexArray.size + i]; // 为起始点有邻接的顶点i赋权重值path[i] = source->KeyValue;}// if (MG->matrix[(source->KeyValue) * G->VertexArray.size + i] == ImpossibleValue)else{dist[i] = WeightMax;path[i] = ImpossibleValue;}collected[i] = false;}dist[source->KeyValue] = 0; // 起始点至起始点的权值为0collected[source->KeyValue] = true; // 收录起始顶点weight temp;while (true){i = FindMinDistWithDijkstra(G, dist, collected); // i为未被收录顶点中dist最小值的顶点号if (i != ImpossibleValue) // 若找到未被收录顶点中dist最小值的顶点号{collected[i] = true; // 收录顶点ifor (j = 0; j < G->VertexArray.size; ++j)// if (collected[j] == false && MG->matrix[i * G->VertexArray.size + j] != ImpossibleValue)if (!collected[j] && MG->matrix[i * G->VertexArray.size + j] != ImpossibleValue) // 对顶点i的每个直接邻接点j且j未被收录{temp = dist[i] + MG->matrix[i * G->VertexArray.size + j];if (temp > 0 && temp < WeightMax) // 预防权值过大导致溢出{if (temp < dist[j]) // 若收录i使得dist[j]变小{dist[j] = temp; // 更新dist[j]path[j] = i; // 更新source到j的路径}}else // 若temp值大于WeightMax数值UnusualToExit(FullWeight, NULL);}}// if (i == ImpossibleValue)else // 若这样的i不存在break; // 算法结束}// if (collected[dest->KeyValue] == true)if (collected[dest->KeyValue]){ShowPath(G, path, source, dest, stream);fprintf(stream, "weight: %d\n\n", dist[dest->KeyValue]);}// if (collected[dest->KeyValue] == false)elsefprintf(stream, CanNotToDest, source->KeyValue, dest->KeyValue);free(dist);free(path);free(collected);}// if (dist == NULL || path == NULL || collected == NULL)elseUnusualToExit(MemoryError, NULL);}// if (source->KeyValue == dest->KeyValue)elseUnusualToExit(SOURCE_EQUL_DEST, NULL);}// if (G->VerextArray.size == 0)elseUnusualToExit(EmptyGraph, NULL);}}// if (G == NULL || MG == NULL || source == NULL || dest == NULL || stream == NULL)elseUnusualToExit(NullPointer, NULL);}// 邻接矩阵表 - 无向网络图 或 有向网络图的单源最短路径算法void DijkstraByALGraph(const Graph * const G, const ALGraph * const ALG, const VertexValue * const source, const VertexValue * const dest, FILE * const stream){// if (G != NULL && ALG != NULL && source != NULL && dest != NULL && stream != NULL)if (G && ALG && source && dest && stream){// if (G->kind == 3 || G->kind == 4)if (G->kind > 2) // 无向网络 或 有向网络{// if (G->VertexArray.size != 0)if (G->VertexArray.size){if (source->KeyValue != dest->KeyValue){// dist[dest] 为 顶点source至顶点dest的最小权重值weight * const dist = (weight *)malloc(G->VertexArray.size * sizeof(weight));// path[dest] 为 顶点source至顶点dest的路径上顶点dest的前一个顶点值VertexSize * const path = (VertexSize *)malloc(G->VertexArray.size * sizeof(VertexSize));// collected[i] == true顶点i已被收录// collected[i] == false顶点i未被收录bool * const collected = (bool *)malloc(G->VertexArray.size * sizeof(bool));// if (dist != NULL && path != NULL && collected != NULL)if (dist && path && collected){VertexSize i;const EdgeNode *P;// 初始化for (i = 0; i < G->VertexArray.size; ++i){dist[i] = WeightMax;path[i] = ImpossibleValue;collected[i] = false;}P = ALG->adjlist[source->KeyValue].FirstEdge;// while (P != NULL)while (P){dist[P->adjvex.KeyValue] = P->Weight; // 覆盖dist数组path[P->adjvex.KeyValue] = source->KeyValue;P = P->next;}// 先将起点收入集合dist[source->KeyValue] = 0; // 起始点至起始点的权值为0path[source->KeyValue] = source->KeyValue;collected[source->KeyValue] = true; // 收录起始顶点weight temp;while (true){// i = 未被收录顶点中dist最小值的顶点号i = FindMinDistWithDijkstra(G, dist, collected);if (i != ImpossibleValue) // 若找到最小权重值{collected[i] = true; // 收录顶点iP = ALG->adjlist[i].FirstEdge;// while (P != NULL)while (P){// if (collected[P->adjvex.KeyValue] == false)if (!collected[P->adjvex.KeyValue]){temp = dist[i] + (P->Weight);if (temp > 0 && temp < WeightMax){if (temp < dist[P->adjvex.KeyValue]){dist[P->adjvex.KeyValue] = temp;path[P->adjvex.KeyValue] = i;}}else // 若temp值大于WeightMax数值UnusualToExit(FullWeight, NULL);}P = P->next;}}// if (i == ImpossibleValue)else // 若这样的i不存在break; // 算法结束}// if (collected[dest->KeyValue] == true)if (collected[dest->KeyValue]){ShowPath(G, path, source, dest, stream);fprintf(stream, "weight: %d\n\n", dist[dest->KeyValue]);}// if (collected[dest->KeyValue] == false)elsefprintf(stream, CanNotToDest, source->KeyValue, dest->KeyValue);free(dist);free(path);free(collected);}// if (dist == NULL || path == NULL || collected == NULL)elseUnusualToExit(MemoryError, NULL);}// if (source->KeyValue == dest->KeyValue)elseUnusualToExit(SOURCE_EQUL_DEST, NULL);}// if (G->VertexArray.size == 0)elseUnusualToExit(EmptyGraph, NULL);}}// if (G == NULL || ALG == NULL || source == NULL || dest == NULL || stream == NULL)elseUnusualToExit(NullPointer, NULL);}// 邻接矩阵存储 - 无向网络图 或 有向网络图的多源最短路径算法void FloydByMGraph(const Graph * const G, const MGraph * const MG, const VertexValue * const source, const VertexValue * const dest, FILE * const stream){// if (G != NULL && MG != NULL && source != NULL && dest != NULL && stream != NULL)if (G && MG && source && dest && stream){// if (G->kind == 3 || G->kind == 4)if (G->kind > 2) // 无向网络 或 有向网络{// if (G->VertexArray.size != 0)if (G->VertexArray.size){if (source->KeyValue != dest->KeyValue){square p = G->VertexArray.size * G->VertexArray.size;// dist[dest] 为 顶点source至顶点dest的权重值weight * const dist = (weight *)malloc(p * sizeof(weight));// path[dest] 为 顶点source至顶点dest的路径上顶点dest的前一个顶点值VertexSize * const path = (VertexSize *)malloc(p * sizeof(VertexSize));// if (dist != NULL && path != NULL)if (dist && path){VertexSize i, j;// 初始化for (i = 0; i < G->VertexArray.size; ++i)for (j = 0; j < G->VertexArray.size; ++j){dist[i * G->VertexArray.size + j] = MG->matrix[i * G->VertexArray.size + j];if (i != j && MG->matrix[i * G->VertexArray.size + j] != ImpossibleValue)path[i * G->VertexArray.size + j] = i;else if (i == j)path[i * G->VertexArray.size + j] = 0;else if (MG->matrix[i * G->VertexArray.size + j] == ImpossibleValue)path[i * G->VertexArray.size + j] = ImpossibleValue;}VertexSize k;weight temp;for (k = 0; k < G->VertexArray.size; ++k)for (i = 0; i < G->VertexArray.size; ++i)for (j = 0; j < G->VertexArray.size; ++j){if (i != j){if (dist[i * G->VertexArray.size + k] != ImpossibleValue && dist[k * G->VertexArray.size + j] != ImpossibleValue){temp = dist[i * G->VertexArray.size + k] + dist[k * G->VertexArray.size + j];if (temp > 0 && temp <= WeightMax) // 预防权值过大导致溢出{if (dist[i * G->VertexArray.size + j] == ImpossibleValue)dist[i * G->VertexArray.size + j] = WeightMax;if (temp < dist[i * G->VertexArray.size + j]){dist[i * G->VertexArray.size + j] = temp;path[i * G->VertexArray.size + j] = path[k * G->VertexArray.size + j];}}else // 若temp值大于WeightMax数值UnusualToExit(FullWeight, NULL);}}}if (dist[(source->KeyValue) * G->VertexArray.size + (dest->KeyValue)] != ImpossibleValue){ShowAllPathWithFloyd(G, path, source, dest, stream);fprintf(stream, "weight: %d\n\n", dist[(source->KeyValue) * G->VertexArray.size + (dest->KeyValue)]);}// if (dist[(source->KeyValue) * G->VertexArray.size + (dest->KeyValue)] == ImpossibleValue)elsefprintf(stream, CanNotToDest, source->KeyValue, dest->KeyValue);free(dist);free(path);}// if (dist == NULL || path == NULL)elseUnusualToExit(MemoryError, NULL);}// if (source->KeyValue == dest->KeyValue)elseUnusualToExit(SOURCE_EQUL_DEST, NULL);}// if (G->VertexArray.size == 0)elseUnusualToExit(EmptyGraph, NULL);}}// if (G == NULL || MG == NULL || source == NULL || dest == NULL || stream == NULL)elseUnusualToExit(NullPointer, NULL);}// 邻接表存储 - 无向网络图 或 有向网络图的多源最短路径算法void FloydByALGraph(const Graph * const G, const ALGraph * const ALG, const VertexValue * const source, const VertexValue * const dest, FILE * const stream){// if (G != NULL && ALG != NULL && source != NULL && dest != NULL && stream != NULL)if (G && ALG && source && dest && stream){// if (G->kind == 3 || G->kind == 4)if (G->kind > 2) // 无向网络 或 有向网络{// if (G->VertexArray.size != 0)if (G->VertexArray.size){if (source->KeyValue != dest->KeyValue){square p = G->VertexArray.size * G->VertexArray.size;// dist[dest] 为 顶点source至顶点dest的最少顶点数weight * const dist = (weight *)malloc(p * sizeof(weight));// path[dest] 为 顶点source至顶点dest的路径上顶点dest的前一个顶点值VertexSize * const path = (VertexSize *)malloc(p * sizeof(VertexSize));// if (dist != NULL && path != NULL)if (dist && path){VertexSize i, j;// 初始化for (i = 0; i < G->VertexArray.size; ++i){for (j = 0; j < G->VertexArray.size; ++j){if (i != j)dist[i * G->VertexArray.size + j] = path[i * G->VertexArray.size + j] = ImpossibleValue;// if (i == j)elsedist[i * G->VertexArray.size + j] = path[i * G->VertexArray.size + j] = 0;}const EdgeNode *ptr = ALG->adjlist[i].FirstEdge;// while (ptr != NULL)while (ptr){dist[i * G->VertexArray.size + (ptr->adjvex.KeyValue)] = ptr->Weight;path[i * G->VertexArray.size + (ptr->adjvex.KeyValue)] = i;ptr = ptr->next;}}VertexSize k;weight temp;for (k = 0; k < G->VertexArray.size; ++k)for (i = 0; i < G->VertexArray.size; ++i)for (j = 0; j < G->VertexArray.size; ++j){if (i != j){if (dist[i * G->VertexArray.size + k] != ImpossibleValue && dist[k * G->VertexArray.size + j] != ImpossibleValue){temp = dist[i * G->VertexArray.size + k] + dist[k * G->VertexArray.size + j];if (temp > 0 && temp <= WeightMax) // 预防权值过大导致溢出{if (dist[i * G->VertexArray.size + j] == ImpossibleValue)dist[i * G->VertexArray.size + j] = WeightMax;if (temp < dist[i * G->VertexArray.size + j]){dist[i * G->VertexArray.size + j] = temp;path[i * G->VertexArray.size + j] = path[k * G->VertexArray.size + j];}}else // 若temp值大于WeightMax数值UnusualToExit(FullWeight, NULL);}}}if (dist[(source->KeyValue) * G->VertexArray.size + (dest->KeyValue)] != ImpossibleValue){ShowAllPathWithFloyd(G, path, source, dest, stream);fprintf(stream, "weight: %d\n\n", dist[(source->KeyValue) * G->VertexArray.size + (dest->KeyValue)]);}// if (dist[(source->KeyValue) * G->VertexArray.size + (dest->KeyValue)] == ImpossibleValue)elsefprintf(stream, CanNotToDest, source->KeyValue, dest->KeyValue);}// if (dist == NULL || path == NULL)elseUnusualToExit(MemoryError, NULL);}// if (source->KeyValue == dest->KeyValue)elseUnusualToExit(SOURCE_EQUL_DEST, NULL);}// if (G->VertexArray.size == 0)elseUnusualToExit(EmptyGraph, NULL);}}// if (G == NULL || ALG == NULL || source == NULL || dest == NULL || stream == NULL)elseUnusualToExit(NullPointer, NULL);}// 邻接表存储 - 最小生成树之Prim算法// 将最小生成树保存为邻接表存储的图MSTvoid PrimByMGraph(const Graph * const G, const MGraph * const MG, const VertexValue * const root){// if (G != NULL && MG != NULL && root != NULL)if (G && MG && root){// if (G->kind == 3 || G->kind == 4)if (G->kind > 2) // 无向网络 或 有向网络{// if (G->VertexArray.size != 0)if (G->VertexArray.size){// dist[V] == 0已收录// dist[V] != 0未收录weight * const dist = (weight *)malloc(G->VertexArray.size * sizeof(weight));// parent[V] = ImpossibleValue 则顶点V为图的根节点VertexSize * const parent = (VertexSize *)malloc(G->VertexArray.size * sizeof(VertexSize));// 建立空边EdgeValue * const E = (EdgeValue *)malloc(sizeof(EdgeValue));// if (dist != NULL && parent != NULL && E != NULL)if (dist && parent && E){const char * const TempFileName = " To MST With MG By Prim";char MSTFileName[LEN];#ifdef WINDOWS_VISUALSTUDIOstrncpy_s(MSTFileName, _countof(MSTFileName), G->FileName, strlen(G->FileName) + 1);strncat_s(MSTFileName, _countof(MSTFileName), TempFileName, strlen(TempFileName) + 1);#endif#ifndef WINDOWS_VISUALSTUDIOstrncpy(MSTFileName, G->FileName, strlen(G->FileName) + 1);strncat(MSTFileName, TempFileName, strlen(TempFileName) + 1);#endifGraph MST;CreateGraph(&MST, G->kind, MSTFileName);VertexSize V;for (V = 0; V < G->VertexArray.size; ++V){// dist[V]为从顶点root至顶点V的边权值 若无直接边相连则为ImpossibleValueif (MG->matrix[root->KeyValue * G->VertexArray.size + V] != ImpossibleValue)dist[V] = MG->matrix[root->KeyValue * G->VertexArray.size + V];// if (MG->matrix[root->KeyValue * G->VertexArray.size + V] == ImpossibleValue)elsedist[V] = WeightMax;parent[V] = root->KeyValue; // 所有顶点的父结点均为初始点}VertexSize VCount = 0; // 初始化收录的顶点数AddVertexOfMSTGraph(&MST, root); // 在最小生成二叉树MST中插入顶点rootdist[root->KeyValue] = 0; // 将初始点收录进最小生成二叉树MST++VCount;VertexSize W;while (true){V = FindMinDistWithPrim(G, dist); // V = 未被收录顶点中dist最小顶点号if (V != ImpossibleValue){// 将V及相应的边<parent[V], V>收录进MSTE->start.KeyValue = parent[V];E->end.KeyValue = V;E->Weight = dist[V];AddVertexOfMSTGraph(&MST, &(E->end));AddEdgeOfMSTGraph(&MST, E); // 在MST中插入边Edist[V] = 0;++VCount;for (W = 0; W < G->VertexArray.size; ++W) // 对图中的每个顶点W  // if (dist[W] != 0 && MG->matrix[V * G->VertexArray.size + W] != ImpossibleValue)if (dist[W] && MG->matrix[V * G->VertexArray.size + W] != ImpossibleValue) // 若W是V的邻接点并且未被收录{if (MG->matrix[V * G->VertexArray.size + W] < dist[W]) // 若收录V使得dist[W]变小{dist[W] = MG->matrix[V * G->VertexArray.size + W]; // 更新dist[W]parent[W] = V; // 更新树}}}// if (V == ImpossibleValue)else // 若这样的V不存在 break;}parent[root->KeyValue] = ImpossibleValue; // 当前树根为rootif (VCount == G->VertexArray.size){// 创建包含所有顶点但没有边的图MGraph MstMg;ALGraph MstAlg;CreateMGraph(&MST, &MstMg);CreateALGraph(&MST, &MstAlg);MakeMGraph(&MST, &MstMg);MakeALGraph(&MST, &MstAlg);OutputListByVertexArrayToFile(&(MST.VertexArray));OutputListByEdgeLinkToFile(&(MST.EdgeLink));OutputMGraphToFile(&MST, &MstMg);OutputALGraphToFile(&MST, &MstAlg);OutputMGraphToMonitor(&MST, &MstMg, stdout);OutputALGraphToMonitor(&MST, &MstAlg, stdout);DistoryMGraph(&MstMg);DistoryALGraph(&MST, &MstAlg);}// if (VCount < G->VertexSize) else // MST中收的顶点不足G->VertexSize个puts(MstFailure);DistoryGraph(&MST);free(dist);free(parent);free(E);}// if (dist == NULL || parent == NULL || E == NULL)elseUnusualToExit(MemoryError, NULL);}// if (G->VertexArray.size == 0)elseUnusualToExit(EmptyGraph, NULL);}}// if (G == NULL || MG == NULL || root == NULL)elseUnusualToExit(NullPointer, NULL);}// 邻接表存储 - 最小生成树之Prim算法// 将最小生成树保存为邻接表存储的图MSTvoid PrimByALGraph(const Graph * const G, const ALGraph * const ALG, const VertexValue * const root){// if (G != NULL && ALG != NULL && root != NULL)if (G && ALG && root){// if (G->kind == 3 || G->kind == 4)if (G->kind > 2) // 无向网络 或 有向网络{// if (G->VertexArray.size != 0)if (G->VertexArray.size){// dist[V] = 0已收录dist[V] != 0未收录weight * const dist = (weight *)malloc(G->VertexArray.size * sizeof(weight));// parent[V] = ImpossibleValue 则顶点V为图的根节点VertexSize * const parent = (VertexSize *)malloc(G->VertexArray.size * sizeof(VertexSize));// 建立空边EdgeValue * const E = (EdgeValue *)malloc(sizeof(EdgeValue));// if (dist != NULL && parent != NULL && E != NULL)if (dist && parent && E){const char * const TempFileName = " To MST With ALG By Prim";char MSTFileName[LEN];#ifdef WINDOWS_VISUALSTUDIOstrncpy_s(MSTFileName, _countof(MSTFileName), G->FileName, strlen(G->FileName) + 1);strncat_s(MSTFileName, _countof(MSTFileName), TempFileName, strlen(TempFileName) + 1);#endif#ifndef WINDOWS_VISUALSTUDIOstrncpy(MSTFileName, G->FileName, strlen(G->FileName) + 1);strncat(MSTFileName, TempFileName, strlen(TempFileName) + 1);#endifGraph MST;CreateGraph(&MST, G->kind, MSTFileName);VertexSize V;for (V = 0; V < G->VertexArray.size; ++V){dist[V] = WeightMax;parent[V] = root->KeyValue; // 所有顶点的父结点均为初始点}const EdgeNode *pointer = ALG->adjlist[root->KeyValue].FirstEdge;// while (pointer != NULL)while (pointer){dist[pointer->adjvex.KeyValue] = pointer->Weight;pointer = pointer->next;}VertexSize VCount = 0; // 初始化收录的顶点数AddVertexOfMSTGraph(&MST, root); // 在最小生成二叉树MST中插入顶点rootdist[root->KeyValue] = 0; // 将初始点收录进最小生成二叉树MST++VCount;while (true){V = FindMinDistWithPrim(G, dist); // V = 未被收录顶点中dist最小顶点号if (V != ImpossibleValue){// 将V及相应的边<parent[V], V>收录进MSTE->start.KeyValue = parent[V];E->end.KeyValue = V;E->Weight = dist[V];AddVertexOfMSTGraph(&MST, &(E->end));AddEdgeOfMSTGraph(&MST, E); // 在MST中插入边Edist[V] = 0;++VCount;pointer = ALG->adjlist[V].FirstEdge;// while (pointer != NULL)while (pointer){// if (dist[pointer->adjvex.KeyValue] != 0)if (dist[pointer->adjvex.KeyValue]){if (pointer->Weight < dist[pointer->adjvex.KeyValue]){dist[pointer->adjvex.KeyValue] = pointer->Weight;parent[pointer->adjvex.KeyValue] = V; // 更新树}}pointer = pointer->next;}}// if (V == ImpossibleValue)else // 若这样的V不存在 break;}parent[root->KeyValue] = ImpossibleValue; // 当前树根为rootif (VCount == G->VertexArray.size){// 创建包含所有顶点但没有边的图MGraph MstMg;ALGraph MstAlg;CreateMGraph(&MST, &MstMg);CreateALGraph(&MST, &MstAlg);MakeMGraph(&MST, &MstMg);MakeALGraph(&MST, &MstAlg);OutputListByVertexArrayToFile(&(MST.VertexArray));OutputListByEdgeLinkToFile(&(MST.EdgeLink));OutputMGraphToFile(&MST, &MstMg);OutputALGraphToFile(&MST, &MstAlg);OutputMGraphToMonitor(&MST, &MstMg, stdout);OutputALGraphToMonitor(&MST, &MstAlg, stdout);DistoryMGraph(&MstMg);DistoryALGraph(&MST, &MstAlg);}// if (VCount < G->VertexSize) else // MST中收的顶点不足G->VertexSize个puts(MstFailure);DistoryGraph(&MST);free(dist);free(parent);free(E);}// if (dist == NULL || parent == NULL || E == NULL)elseUnusualToExit(MemoryError, NULL);}// if (G->VertexArray.size == 0)elseUnusualToExit(EmptyGraph, NULL);}}// if (G == NULL || ALG == NULL || root == NULL)elseUnusualToExit(NullPointer, NULL);}void KruskalMGraph(const Graph * const G, const MGraph * const MG){// if (G != NULL && MG != NULL)if (G && MG){// if (G->kind == 3 || G->kind == 4)if (G->kind > 2) // 无向网络 或 有向网络{// if (G->VertexArray.size != 0)if (G->VertexArray.size){VertexSize * const VSet = (VertexSize *)malloc(G->VertexArray.size * sizeof(VertexSize)); // 顶点数组// if (VSet != NULL)if (VSet){const char * const TempFileName = " To MST With MG By Kruskal";char MSTFileName[LEN];#ifdef WINDOWS_VISUALSTUDIOstrncpy_s(MSTFileName, _countof(MSTFileName), G->FileName, strlen(G->FileName) + 1);strncat_s(MSTFileName, _countof(MSTFileName), TempFileName, strlen(TempFileName) + 1);#endif#ifndef WINDOWS_VISUALSTUDIOstrncpy(MSTFileName, G->FileName, strlen(G->FileName) + 1);strncat(MSTFileName, TempFileName, strlen(TempFileName) + 1);#endifVertexSize i, j;EdgeSize ECount = 0; // 初始化收录的边数CreateializeVSet(VSet, G->VertexArray.size); // 初始化顶点并查集Graph MST;CreateGraph(&MST, G->kind, MSTFileName);for (i = 0; i < G->VertexArray.size; ++i)AddVertexOfGraph(&MST, &G->VertexArray.base[i]);EdgeArrayList H;CreateListByEdgeArray(&H, G->EdgeLink.size, 0, NULL); // 参数30为最小堆 1为最大堆EdgeValue temp;for (i = 0; i < G->VertexArray.size; ++i)for (j = 0; j < G->VertexArray.size; ++j)if (MG->matrix[i * G->VertexArray.size + j] > 0){temp.start.KeyValue = i;temp.end.KeyValue = j;temp.Weight = MG->matrix[i * G->VertexArray.size + j];AddTailListByEdgeArray(&H, &temp);}AdjustHeap(&H); // 添加堆元素后必须调用AdjustHeap调整堆元素while (ECount < G->VertexArray.size - 1) // 当收集的边不足以构成树时{GetEdge(&H); // 从边集中得到最小边的位置if (H.size >= 0){// if (CheckCycle(VSet, &H.base[H.size]) == true)if (CheckCycle(VSet, &H.base[H.size])) // 如果该边的加入不构成回路,即两端结点不属于同一连通集{AddEdgeOfGraph(&MST, &(H.base[H.size])); // 将该条边插入MST++ECount; // 生成树中边数加1}}// if (H.size < 0)else // 边集已空break;}if (ECount == G->VertexArray.size - 1){MGraph MstMg;ALGraph MstAlg;CreateMGraph(&MST, &MstMg);CreateALGraph(&MST, &MstAlg);MakeMGraph(&MST, &MstMg);MakeALGraph(&MST, &MstAlg);OutputListByVertexArrayToFile(&(MST.VertexArray));OutputListByEdgeLinkToFile(&(MST.EdgeLink));OutputMGraphToFile(&MST, &MstMg);OutputALGraphToFile(&MST, &MstAlg);OutputMGraphToMonitor(&MST, &MstMg, stdout);OutputALGraphToMonitor(&MST, &MstAlg, stdout);DistoryMGraph(&MstMg);DistoryALGraph(&MST, &MstAlg);}// if (ECount < G->VertexArray.size - 1)elseputs(MstFailure);free(VSet);DestroyListByEdgeArray(&H);DistoryGraph(&MST);}// if (VSet == NULL || ESet == NULL)elseUnusualToExit(MemoryError, NULL);}// if (G->VertexArray.size == 0)elseUnusualToExit(EmptyGraph, NULL);}}// if (G == NULL || MG == NULL)elseUnusualToExit(NullPointer, NULL);}void KruskalALGraph(const Graph * const G, const ALGraph * const ALG){// if (G != NULL && ALG != NULL)if (G && ALG){// if (G->kind == 3 || G->kind == 4)if (G->kind > 2) // 无向网络 或 有向网络{// if (G->VertexArray.size != 0)if (G->VertexArray.size){VertexSize * const VSet = (VertexSize *)malloc(G->VertexArray.size * sizeof(VertexSize)); // 顶点数组// if (VSet != NULL)if (VSet){const char * const TempFileName = " To MST With ALG By Kruskal";char MSTFileName[LEN];#ifdef WINDOWS_VISUALSTUDIOstrncpy_s(MSTFileName, _countof(MSTFileName), G->FileName, strlen(G->FileName) + 1);strncat_s(MSTFileName, _countof(MSTFileName), TempFileName, strlen(TempFileName) + 1);#endif#ifndef WINDOWS_VISUALSTUDIOstrncpy(MSTFileName, G->FileName, strlen(G->FileName) + 1);strncat(MSTFileName, TempFileName, strlen(TempFileName) + 1);#endifVertexSize i;EdgeSize ECount = 0; // 初始化收录的边数CreateializeVSet(VSet, G->VertexArray.size); // 初始化顶点并查集Graph MST;CreateGraph(&MST, G->kind, MSTFileName);for (i = 0; i < G->VertexArray.size; ++i)AddVertexOfGraph(&MST, &G->VertexArray.base[i]);EdgeArrayList H;CreateListByEdgeArray(&H, G->EdgeLink.size, 0, NULL); // 参数30为最小堆 1为最大堆EdgeValue temp;const EdgeNode *ptr;for (i = 0; i < G->VertexArray.size; ++i){ptr = ALG->adjlist[i].FirstEdge;// while (ptr != NULL)while (ptr){temp.start.KeyValue = i;temp.end.KeyValue = ptr->adjvex.KeyValue;temp.Weight = ptr->Weight;AddTailListByEdgeArray(&H, &temp);ptr = ptr->next;}}AdjustHeap(&H); // 添加堆元素后必须调用AdjustHeap调整堆元素while (ECount < G->VertexArray.size - 1) // 当收集的边不足以构成树时{GetEdge(&H); // 从边集中得到最小边的位置if (H.size >= 0){// if (CheckCycle(VSet, &H.base[H.size]) == true)if (CheckCycle(VSet, &H.base[H.size])) // 如果该边的加入不构成回路,即两端结点不属于同一连通集{AddEdgeOfGraph(&MST, &(H.base[H.size])); // 将该条边插入MST++ECount; // 生成树中边数加1}}// if (H.size < 0)else // 边集已空break;}if (ECount == G->VertexArray.size - 1){MGraph MstMg;ALGraph MstAlg;CreateMGraph(&MST, &MstMg);CreateALGraph(&MST, &MstAlg);MakeMGraph(&MST, &MstMg);MakeALGraph(&MST, &MstAlg);OutputListByVertexArrayToFile(&(MST.VertexArray));OutputListByEdgeLinkToFile(&(MST.EdgeLink));OutputMGraphToFile(&MST, &MstMg);OutputALGraphToFile(&MST, &MstAlg);OutputMGraphToMonitor(&MST, &MstMg, stdout);OutputALGraphToMonitor(&MST, &MstAlg, stdout);DistoryMGraph(&MstMg);DistoryALGraph(&MST, &MstAlg);}// if (ECount < G->VertexArray.size - 1)elseputs(MstFailure);free(VSet);DestroyListByEdgeArray(&H);DistoryGraph(&MST);}// if (VSet == NULL || ESet == NULL)elseUnusualToExit(MemoryError, NULL);}// if (G->VertexArray.size == 0)elseUnusualToExit(EmptyGraph, NULL);}}// if (G == NULL || ALG == NULL)elseUnusualToExit(NullPointer, NULL);}void UnusualToExit(const char * const str, const char * const FileName){fprintf(stderr, str, FileName);#ifdef WINDOWS_VISUALSTUDIO_getch();#endifexit(EXIT_FAILURE); // exit (1);}/**************************** 私有函数 ****************************/static void MakeVertexOfMGraph(const Graph * const G, MGraph * const MG){// if (G != NULL && MG != NULL)if (G && MG){// 生成顶点square i = G->VertexArray.size * G->VertexArray.size;MG->matrix = (weight *)malloc(i * sizeof(weight));// if (MG->matrix != NULL)if (MG->matrix){// 矩阵全清0square k;for (k = 0; k < i; ++k)MG->matrix[k] = 0;}// if (MG->matrix == NULL)elseUnusualToExit(MemoryError, NULL);}// if (G == NULL || MG == NULL)elseUnusualToExit(NullPointer, NULL);}static void MakeEdgeOfMGraph(const Graph * const G, MGraph * const MG){// if (G != NULL && MG != NULL)if (G && MG){// 生成边VertexSize j, k;const NodeOfEdge *EdgePtr = G->EdgeLink.head;// 邻接矩阵// while (EdgePtr != NULL)while (EdgePtr){switch (G->kind){case 1: // 无向图MG->matrix[EdgePtr->item.end.KeyValue * G->VertexArray.size + EdgePtr->item.start.KeyValue] = 1;case 2: // 有向图MG->matrix[EdgePtr->item.start.KeyValue * G->VertexArray.size + EdgePtr->item.end.KeyValue] = 1;break;case 3: // 无向网络图MG->matrix[EdgePtr->item.end.KeyValue * G->VertexArray.size + EdgePtr->item.start.KeyValue] = EdgePtr->item.Weight;case 4: // 有向网络图MG->matrix[EdgePtr->item.start.KeyValue * G->VertexArray.size + EdgePtr->item.end.KeyValue] = EdgePtr->item.Weight;break;}EdgePtr = EdgePtr->next;}// if (G->kind == 3 || G->kind == 4)if (G->kind > 2) // 无向网络 或 有向网络{for (j = 0; j < G->VertexArray.size; ++j){for (k = 0; k < G->VertexArray.size; ++k){// if ((MG->matrix[j * G->VertexArray.size + k] == 0) && (j != k))if ((!MG->matrix[j * G->VertexArray.size + k]) && (j != k))MG->matrix[j * G->VertexArray.size + k] = ImpossibleValue;}}}}// if (G == NULL || MG == NULL)elseUnusualToExit(NullPointer, NULL);}static void MakeVertexOfALGraph(const Graph * const G, ALGraph * const ALG){// if (G != NULL && ALG != NULL)if (G && ALG){// 生成顶点ALG->adjlist = (VertexNode *)malloc(G->VertexArray.size * sizeof(VertexNode));// if (ALG->adjlist != NULL)if (ALG->adjlist){VertexSize i;for (i = 0; i < G->VertexArray.size; ++i){ALG->adjlist[i].vexs.KeyValue = i;ALG->adjlist[i].FirstEdge = NULL;}}// if (ALG->adjlist == NULL)elseUnusualToExit(MemoryError, NULL);}// if (G == NULL || ALG == NULL)elseUnusualToExit(NullPointer, NULL);}static void MakeEdgeOfALGraph(const Graph * const G, ALGraph * const ALG){// if (G != NULL && ALG != NULL)if (G && ALG){// 生成边const NodeOfEdge *EdgePtr = G->EdgeLink.head;VertexSize order;// 邻接表// while (EdgePtr != NULL)while (EdgePtr){EdgeNode *NewNode = (EdgeNode *)malloc(sizeof(EdgeNode));// if (NewNode != NULL)if (NewNode){NewNode->adjvex.KeyValue = EdgePtr->item.end.KeyValue;NewNode->Weight = EdgePtr->item.Weight;order = EdgePtr->item.start.KeyValue;NewNode->next = ALG->adjlist[order].FirstEdge;ALG->adjlist[order].FirstEdge = NewNode;}// if (NewNode == NULL)elseUnusualToExit(MemoryError, NULL);// 为无向图或无向网络创建反向边// if (G->kind == 1 || G->kind == 3)if (G->kind & 1) // 为无向图 或 无向网络{NewNode = (EdgeNode *)malloc(sizeof(EdgeNode));// if (NewNode != NULL)if (NewNode){NewNode->adjvex.KeyValue = EdgePtr->item.start.KeyValue;NewNode->Weight = EdgePtr->item.Weight;order = EdgePtr->item.end.KeyValue;NewNode->next = ALG->adjlist[order].FirstEdge;ALG->adjlist[order].FirstEdge = NewNode;}// if (NewNode == NULL)elseUnusualToExit(MemoryError, NULL);}EdgePtr = EdgePtr->next;}}// if (G == NULL || ALG == NULL)elseUnusualToExit(NullPointer, NULL);}// 从顶点i出发,对邻接矩阵表示的图G作深度优先搜索static void DfsByMGraph(const Graph * const G, const MGraph * const MG, bool * const visited, const VertexSize i, FILE * const stream){// if (G != NULL && MG != NULL && visited != NULL && stream != NULL)if (G && MG && visited && stream){fprintf(stream, "访问 顶点:%hu\n", i);visited[i] = true; // 标记visited已访问VertexSize j;for (j = 0; j < G->VertexArray.size; ++j)// if (MG->matrix[i * G->VertexArray.size + j] != 0 && MG->matrix[i * G->VertexArray.size + j] != ImpossibleValue && visited[j] == false)if (MG->matrix[i * G->VertexArray.size + j] && MG->matrix[i * G->VertexArray.size + j] != ImpossibleValue && !visited[j]) // 若矩阵顶点非0且非不可能的值且尚未访问DfsByMGraph(G, MG, visited, j, stream); // 递归访问顶点i的直接领接点j}// if (G == NULL || MG == NULL || visited == NULL || stream == NULL)elseUnusualToExit(NullPointer, NULL);}// 从顶点i出发,对邻接表表示的图G作深度优先搜索static void DfsByALGraph(const ALGraph * const ALG, bool * const visited, const VertexSize i, FILE * const stream){// if (ALG != NULL && visited != NULL && stream != NULL)if (ALG && visited && stream){fprintf(stream, "访问 顶点:%hu\n", i);visited[i] = true; // 标记visited已访问const EdgeNode *p = ALG->adjlist[i].FirstEdge; // 取visited边表的头指针// while (p != NULL)while (p){// if (visited[p->adjvex.KeyValue] == false)if (!visited[p->adjvex.KeyValue])DfsByALGraph(ALG, visited, p->adjvex.KeyValue, stream); // 递归访问顶点i的直接邻接点jp = p->next;}}// if (ALG == NULL || visited == NULL || stream == NULL)elseUnusualToExit(NullPointer, NULL);}static void ShowPath(const Graph * const G, const VertexSize * const path, const VertexValue * const source, const VertexValue * const dest, FILE * const stream){// if (G != NULL && path != NULL && source != NULL && dest != NULL && stream != NULL)if (G && path && source && dest && stream){VertexSize i = dest->KeyValue;ArrayList AntiPath;CreateListByArray(&AntiPath, G->VertexArray.size, NULL);PushByArray(&AntiPath, dest->KeyValue); // 进栈while (path[i] != source->KeyValue){PushByArray(&AntiPath, path[i]); // 进栈i = path[i];}fprintf(stream, "%d : \t", source->KeyValue);// while (AntiPath.size != 0)while (AntiPath.size){PopByArray(&AntiPath, &i); // 出栈fprintf(stream, "%d\t", i);}putc('\n', stream);DestroyListByArray(&AntiPath);}// if (G == NULL || path == NULL || source == NULL || dest == NULL || stream == NULL)elseUnusualToExit(NullPointer, NULL);}// 返回未被收录顶点中dist最小值的顶点号static VertexSize FindMinDistWithDijkstra(const Graph * const G, const weight * const dist, const bool * const collected){// if (G != NULL && dist != NULL && collected != NULL)if (G && dist && collected){VertexSize V, MinV = ImpossibleValue; // MinV初始为错误标记;weight MinDist = WeightMax;for (V = 0; V < G->VertexArray.size; ++V){// if ((collected[V] == false) && (dist[V] < MinDist))if ((!collected[V]) && (dist[V] < MinDist)) // 若顶点V未被收录且从起始点至顶点V的权重值更小{MinDist = dist[V]; // 更新最小距离MinV = V; // 更新对应顶点}}return MinV; // 若找到最小dist返回对应的顶点下标 若这样的顶点不存在返回错误标记}// if (G == NULL || dist == NULL || collected == NULL)else{fprintf(stderr, NullPointer);#ifdef WINDOWS_VISUALSTUDIO_getch();#endifexit(EXIT_FAILURE); // exit (1);}}static void ShowAllPathWithFloyd(const Graph * const G, const VertexSize * const path, const VertexValue * const source, const VertexValue * const dest, FILE * const stream){// if (G != NULL && path != NULL && source != NULL && dest != NULL && stream != NULL)if (G && path && source && dest && stream){fprintf(stream, "%d : \t", G->VertexArray.base[source->KeyValue].KeyValue);ShowPathWithFloyd(G, path, source->KeyValue, dest->KeyValue, stream);fprintf(stream, "%d\n", G->VertexArray.base[dest->KeyValue].KeyValue);}// if (G == NULL || path == NULL || source == NULL || dest == NULL || stream == NULL)elseUnusualToExit(NullPointer, NULL);}static void ShowPathWithFloyd(const Graph * const G, const VertexSize * const path, const VertexSize s, const VertexSize d, FILE * const stream){// if (G != NULL && path != NULL && stream != NULL)if (G && path && stream){VertexSize k = path[s * G->VertexArray.size + d]; // 输出i到j路径的中间顶点if (k == ImpossibleValue)return;if (k == s || k == d)return;ShowPathWithFloyd(G, path, s, k, stream);fprintf(stream, "%d\t", G->VertexArray.base[k].KeyValue);ShowPathWithFloyd(G, path, k, d, stream);}// if (G == NULL || path == NULL || stream == NULL)elseUnusualToExit(NullPointer, NULL);}// 返回未被收录顶点中dist最小值的顶点号static VertexSize FindMinDistWithPrim(const Graph * const G, const weight * const dist){// if (G != NULL && dist != NULL)if (G && dist){VertexSize V, MinV = ImpossibleValue; // MinV初始为错误标记weight MinDist = WeightMax;for (V = 0; V < G->VertexArray.size; ++V){// if (dist[V] != 0 && dist[V] < MinDist)if (dist[V] && dist[V] < MinDist) // 若V未被收录,且dist[V]更小{MinDist = dist[V]; // 更新最小距离MinV = V; // 更新对应顶点}}return MinV; // 若找到最小dist返回对应的顶点下标 若这样的顶点不存在返回错误标记}// if (G == NULL || dist == NULL)else{fprintf(stderr, NullPointer);#ifdef WINDOWS_VISUALSTUDIO_getch();#endifexit(EXIT_FAILURE); // exit (1);}}// 初始化并查集static void CreateializeVSet(VertexSize * const VSet, const VertexSize size){// if (VSet != NULL)if (VSet){VertexSize n;for (n = 0; n < size; ++n)VSet[n] = -1;}// if (VSet == NULL)elseUnusualToExit(NullPointer, NULL);}// 将当前最小边位置弹出并调整堆static void GetEdge(EdgeArrayList * const H){// if (H != NULL)if (H){// 将最小边与当前堆的最后一个位置的边交换EdgeValue temp = H->base[0];H->base[0] = H->base[H->size - 1];H->base[H->size - 1] = temp;--(H->size);AdjustHeap(H); // 将剩下的边继续调整成最小堆}// if (H == NULL)elseUnusualToExit(NullPointer, NULL);}// 检查连接Edge->start.KeyValue和Edge->start.KeyValue的边是否在现有的最小生成树子集中构成回环// 构成回环返回 false// 不构成回环返回 truestatic bool CheckCycle(VertexSize * const VSet, const EdgeValue * const Edge){// if (VSet != NULL && Edge != NULL)if (VSet && Edge){VertexSize Root1 = Find(VSet, Edge->start.KeyValue); // 取得Edge->start.KeyValue所属的连通集名称VertexSize Root2 = Find(VSet, Edge->end.KeyValue); // 取得Edge->start.KeyValue所属的连通集名称if (Root1 == Root2) // 若Edge->start.KeyValue和Edge->start.KeyValue已连通则该边不能要return false;// if (Root1 != Root2)else // 否则该边可以被收集,同时将Edge->start.KeyValue和Edge->start.KeyValue并入同一连通集{Union(VSet, &Root1, &Root2);return true;}}// if (VSet == NULL || Edge == NULL)else{fprintf(stderr, NullPointer);#ifdef WINDOWS_VISUALSTUDIO_getch();#endifexit(EXIT_FAILURE); // exit (1);}}static VertexSize Find(VertexSize * const VSet, const VertexSize n){// if (VSet != NULL)if (VSet){if (VSet[n] >= 0)return VSet[n] = Find(VSet, VSet[n]); // 路径压缩// if (VSet[n] < 0)else // 找到集合的根return n;}// if (VSet == NULL)else{fprintf(stderr, NullPointer);#ifdef WINDOWS_VISUALSTUDIO_getch();#endifexit(EXIT_FAILURE); // exit (1);}}// 此处默认Root1和Root2是不同集合的根结点static void Union(VertexSize * const VSet, const VertexSize * const Root1, const VertexSize * const Root2){// if (VSet != NULL)if (VSet){// 保证小集合并入大集合 if (VSet[*Root2] < VSet[*Root1]) // 若集合2比较大{VSet[*Root2] += VSet[*Root1]; // 集合1并入集合2VSet[*Root1] = *Root2;}// if (VSet[*Root2] >= VSet[*Root1])else // 若集合1比较大{VSet[*Root1] += VSet[*Root2]; // 集合2并入集合1VSet[*Root2] = *Root1;}}// if (VSet == NULL)elseUnusualToExit(NullPointer, NULL);}static void AddVertexOfMSTGraph(Graph * const G, const VertexValue * const NewVertex){AddTailListByVertexArray(&(G->VertexArray), NewVertex);}static void AddEdgeOfMSTGraph(Graph * const G, const EdgeValue * const NewEdge){AddTailListByEdgeLink(&(G->EdgeLink), NewEdge);}

// heap.h#ifndef HEAP_H#define HEAP_H#include "graph.h"typedef struct{EdgeValue *base; // 数组地址EdgeSize size;// 数组当前长度EdgeSize MaxSize; // 数组最大长度bool kind; // 堆类型 0为最小堆 1为最大堆const char * FileName; // 向文件输出元素的文件名}EdgeArrayList;void AdjustHeap(EdgeArrayList * const H);#endif

// heap.c#include "Heap.h"#include "EdgeArrayOfGraph.h"extern const char * const NullPointer;static void ShiftDown(EdgeArrayList * const H, EdgeSize k);// 将堆调整成最小堆void AdjustHeap(EdgeArrayList * const H){// if (H != NULL)if (H){if (H->size > 1){EdgeSize i;// for (i = ((H->size) / 2) - 1; ; --i)for (i = (((H->size) >> 1) - 1); ; --i){// 将H->base[i]插入H->base[i + 1] 至 H->base[H->size - 1]的最小堆中ShiftDown(H, i);// if (i == 0)if (!i)break;}}}// if (H == NULL)elseUnusualToExit(NullPointer, NULL);}/*************************** 私有函数 **************************/// 将H->base[k]插入H->base[k + 1] 至 H->base[(H->size) - 1]的最小堆中static void ShiftDown(EdgeArrayList * const H, EdgeSize k){// if (H != NULL)if (H){EdgeSize j;EdgeValue temp = H->base[k];// 连续交换用循环传递实现// for (j = 2 * k + 1; j < H->size; k = j, j = 2 * k + 1)for (j = (k << 1) + 1; j < H->size; k = j, j = (k << 1) + 1){if ((j < (H->size) - 1) && (H->base[j].Weight > H->base[j + 1].Weight))++j;if (temp.Weight <= H->base[j].Weight)break;H->base[k] = H->base[j]; // 循环传递中}H->base[k] = temp; // 循环传递结束}// if (H == NULL)elseUnusualToExit(NullPointer, NULL);}

// EdgeArrayOfGraph.h#ifndef EDGE_ARRAY_OF_GRAPH_H#define EDGE_ARRAY_OF_GRAPH_H#include "Heap.h"#include "graph.h"void CreateListByEdgeArray(EdgeArrayList * const Array, const EdgeSize Max, const bool kind, const char * const FileName);void DestroyListByEdgeArray(EdgeArrayList * const Array);bool ListByEdgeArrayIsEmpty(const EdgeArrayList * const Array);bool ListByEdgeArrayIsFull(const EdgeArrayList * const Array);void OutputListByEdgeArrayToFile(const EdgeArrayList * const Array);void OutputListByEdgeArrayToMonitor(const EdgeArrayList * const Array, FILE * const stream);void AddTailListByEdgeArray(EdgeArrayList * const Array, const EdgeValue * const NewItem);void DelTailListByEdgeArray(EdgeArrayList * const Array, EdgeValue * const DelItem);#endif

// EdgeArrayOfGraph.c#include "EdgeArrayOfGraph.h"extern const char * const NullPointer;extern const char * const WriteOperation;extern const char * const MemoryError;extern const char * const OpenFileError;extern const char * const CloseFileError;extern const char * const EmptyArray;extern const char * const FullArray;extern const char ImpossibleValue;// 创建空顺序表Arrayvoid CreateListByEdgeArray(EdgeArrayList * const Array, const EdgeSize Max, const bool kind, const char * const FileName){if (Array != NULL){Array->base = (EdgeValue *)malloc(Max * sizeof(EdgeValue));// if (Array->base != NULL)if (Array->base){Array->size = 0; // 空表长度置0Array->MaxSize = Max;Array->kind = kind;Array->FileName = FileName;}// if (Array->base == NULL)elseUnusualToExit(MemoryError, NULL);}// if (Array == NULL)elseUnusualToExit(NullPointer, NULL);}void DestroyListByEdgeArray(EdgeArrayList * const Array){// if (Array != NULL)if (Array){free(Array->base);Array->base = NULL;Array->size = Array->MaxSize = 0;Array->FileName = NULL;}// if (Array == NULL)elseUnusualToExit(NullPointer, NULL);}bool ListByEdgeArrayIsEmpty(const EdgeArrayList * const Array){// if (Array != NULL)if (Array)return Array->size == 0;// if (Array == NULL)else{fprintf(stderr, "%s", NullPointer);#ifdef WINDOWS_VISUALSTUDIO_getch();#endifexit(EXIT_FAILURE); // exit (1);}}bool ListByEdgeArrayIsFull(const EdgeArrayList * const Array){// if (Array != NULL)if (Array)return Array->size == Array->MaxSize;// if (Array == NULL)else{fprintf(stderr, "%s", NullPointer);#ifdef WINDOWS_VISUALSTUDIO_getch();#endifexit(EXIT_FAILURE); // exit (1);}}// 文件输出void OutputListByEdgeArrayToFile(const EdgeArrayList * const Array){// if (Array != NULL && WriteOperation != NULL)if (Array && WriteOperation){#ifdef WINDOWS_VISUALSTUDIOFILE *fp;errno_t err = fopen_s(&fp, Array->FileName, WriteOperation);// if (err == 0)if (!err)OutputListByEdgeArrayToMonitor(Array, fp);// if (err == 1)elseUnusualToExit(OpenFileError, Array->FileName);// if (fp != NULL)if (fp){// if (fclose(fp) != 0)if (fclose(fp))UnusualToExit(CloseFileError, Array->FileName);}#endif#ifndef WINDOWS_VISUALSTUDIOFILE * const fp = fopen(Array->FileName, WriteOperation);// if (fp != NULL)if (fp)OutputListByEdgeArrayToMonitor(Array, fp);// if (fp == NULL)elseUnusualToExit(OpenFileError, Array->FileName);// if (fclose(fp) != 0)if (fclose(fp))UnusualToExit(CloseFileError, Array->FileName);#endif}// if (Array == NULL || WriteOperation == NULL)elseUnusualToExit(NullPointer, NULL);}// 输出顺序表List的所有元素void OutputListByEdgeArrayToMonitor(const EdgeArrayList * const Array, FILE * const stream){// if (Array != NULL && stream != NULL)if (Array && stream){EdgeSize index;for (index = 0; index < Array->size; ++index)fprintf(stream, "%d\t%d\t%d\n", Array->base[index].start.KeyValue, Array->base[index].end.KeyValue, Array->base[index].Weight); // 此处随元素属性而改变}// if (Array == NULL || stream == NULL)elseUnusualToExit(NullPointer, NULL);}void AddTailListByEdgeArray(EdgeArrayList * const Array, const EdgeValue * const NewItem){// if (Array != NULL && NewItem != NULL)if (Array && NewItem){EdgeSize order = Array->size;if (Array->size != Array->MaxSize) // 元素数量未至数据类型极限值{(Array->base)[order] = *NewItem;++(Array->size); // 表长增1}// if (Array->size == Array->MaxSize)else // 元素数量已至数据类型极限值UnusualToExit(FullArray, NULL);}// if (Array == NULL || NewItem == NULL)elseUnusualToExit(NullPointer, NULL);}void DelTailListByEdgeArray(EdgeArrayList * const Array, EdgeValue * const DelItem){// if (Array != NULL && DelItem != NULL)if (Array && DelItem){EdgeSize order = Array->size - 1;// if (Array->size != 0)if (Array->size) // 顺序表非空{*DelItem = Array->base[order];--(Array->size); // 表长减1}// if (Array->size == 0)else // 顺序表为空UnusualToExit(EmptyArray, NULL);}// if (Array == NULL || DelItem == NULL)elseUnusualToExit(NullPointer, NULL);}

// 以链表作为图的队列// QueueOfGraph.h #ifndef QUEUE_OF_GRAPH_H#define QUEUE_OF_GRAPH_H#include "graph.h"#define EMPTY_QUEUE "空队列\n"#define FULL_QUEUE "满队列\n"/********************************属性********************************/// 一般类型定义typedef VertexSize LinkItem;typedef struct node{LinkItem item;struct node *next;}LinkNode;typedef struct{LinkNode *head;LinkNode *tail;VertexSize size; // 链表结点数量VertexSize MaxSize; // 链表结点数上限const char *FileName; // 向文件输出元素的文件名}LinkList;/********************************操作********************************/// 函数原型// 操作:初始化一个列表// 操作前:Link指向一个列表// 操作后:该列表被初始化为空列表void CreateListByLink(LinkList * const Link, const VertexSize Max, const char * const FileName);// 操作:释放已分配的内存(如果有)// 操作前:Link指向一个已初始化的列表// 操作后:为该列表分配的内存已被释放// 并且该列表被置为空列表void DestoryListByLink(LinkList * const Link);bool ListByLinkIsEmpty(const LinkList * const Link);bool ListByLinkIsFull(const LinkList * const Link);void EnQueueByLink(LinkList * const Link, const LinkItem NewItem);void DeQueueByLink(LinkList * const Link, LinkItem * const DelItem);#endif

// QueueOfGraph.c#include "QueueOfGraph.h"extern const char * const MemoryError;extern const char * const NullPointer;// 接口函数// 把链表设为空列表// 参数Link为链表指针 Max为链表结点数最大值 FileName为欲输出链表元素的文件名void CreateListByLink(LinkList * const Link, const VertexSize Max, const char * const FileName){// if (Link != NULL)if (Link){Link->head = Link->tail = NULL;Link->size = 0;Link->MaxSize = Max;Link->FileName = FileName;}// if (Link == NULL)elseUnusualToExit(NullPointer, NULL);}// 释放由malloc ( )分配的内存// 把列表指针设置为NULLvoid DestoryListByLink(LinkList * const Link){// if (Link != NULL)if (Link){LinkNode *psave = Link->head;// while (psave != NULL)while (psave){psave = Link->head->next; // 保存下一个结点的地址free(Link->head); // 释放当前结点Link->head = psave; // 前进到下一个结点}Link->head = Link->tail = NULL;Link->size = Link->MaxSize = 0;Link->FileName = NULL;}// if (Link == NULL)elseUnusualToExit(NullPointer, NULL);}bool ListByLinkIsEmpty(const LinkList * const Link){// if (Link != NULL)if (Link)return Link->size == 0;// if (Link == NULL)else{fprintf(stderr, "%s", NullPointer);#ifdef WINDOWS_VISUALSTUDIO_getch();#endifexit(EXIT_FAILURE); // exit (1);}}bool ListByLinkIsFull(const LinkList * const Link){// if (Link != NULL)if (Link)return Link->size == Link->MaxSize;// if (Link == NULL)else{fprintf(stderr, "%s", NullPointer);#ifdef WINDOWS_VISUALSTUDIO_getch();#endifexit(EXIT_FAILURE); // exit (1);}}// 创建存放项目的结点,并把它添加到由Link指向的列表尾部void EnQueueByLink(LinkList * const Link, const LinkItem NewItem){// if (Link != NULL)if (Link){if (Link->size != Link->MaxSize){LinkNode * const NewNode = (LinkNode *)malloc(sizeof(LinkNode));// if (NewNode != NULL)if (NewNode){// if (Link->size != 0) if (Link->size) // 链表有结点Link->tail->next = NewNode;// if (Link->size == 0)else // 链表无结点{Link->head = NewNode;}Link->tail = NewNode;NewNode->next = NULL;NewNode->item = NewItem;++(Link->size);}// if (NewNode == NULL)elseUnusualToExit(MemoryError, NULL);}// if (Link->size == Link->MaxSize)elseUnusualToExit(FULL_QUEUE, NULL);}// if (Link == NULL)elseUnusualToExit(NullPointer, NULL);}void DeQueueByLink(LinkList * const Link, LinkItem * const DelItem){// if (Link != NULL && DelItem != NULL)if (Link && DelItem){// if (Link->size != 0)if (Link->size) // 链表中有结点{LinkNode *pnode;pnode = Link->head;Link->head = Link->head->next;// if (Link->head == NULL)if (!(Link->head))Link->tail = NULL;*DelItem = pnode->item;free(pnode);--(Link->size);}// if (Link->size == 0)else // 链表中无结点UnusualToExit(EMPTY_QUEUE, NULL);}// if (Link == NULL || DelItem == NULL)elseUnusualToExit(NullPointer, NULL);}

// 以数组作为图的堆栈// StackOfGraph.h#ifndef STACK_OF_GRAPH_H#define STACK_OF_GRAPH_H#include "graph.h"#define EMPTY_STACK "空堆栈\n"#define FULL_STACK "满堆栈\n"typedef VertexSize ArrayItem;typedef struct{ArrayItem *base; // 数组地址VertexSize size;// 数组当前长度VertexSize MaxSize; // 数组最大长度const char *FileName; // 向文件输出元素的文件名}ArrayList;void CreateListByArray(ArrayList * const Array, const VertexSize Max, const char * const FileName);void DestroyListByArray(ArrayList * const Array);bool ListByArrayIsEmpty(const ArrayList * const Array);bool ListByArrayIsFull(const ArrayList * const Array);void PushByArray(ArrayList * const Array, const ArrayItem NewItem);void PopByArray(ArrayList * const Array, ArrayItem * const DelItem);#endif

// StackOfGraph.c#include "StackOfGraph.h"extern const char * const MemoryError;extern const char * const NullPointer;// 创建空顺序表Arrayvoid CreateListByArray(ArrayList * const Array, const VertexSize Max, const char * const FileName){// if (Array != NULL)if (Array){Array->base = (ArrayItem *)malloc(Max * sizeof(ArrayItem));// if (Array->base != NULL)if (Array->base){Array->size = 0; // 空表长度置0Array->MaxSize = Max;Array->FileName = FileName;}// if (Array->base == NULL)elseUnusualToExit(MemoryError, NULL);}// if (Array == NULL)elseUnusualToExit(NullPointer, NULL);}void DestroyListByArray(ArrayList * const Array){// if (Array != NULL)if (Array){free(Array->base);Array->base = NULL;Array->size = Array->MaxSize = 0;Array->FileName = NULL;}// if (Array == NULL)elseUnusualToExit(NullPointer, NULL);}bool ListByArrayIsEmpty(const ArrayList * const Array){// if (Array != NULL)if (Array)return Array->size == 0;// if (Array == NULL)else{fprintf(stderr, "%s", NullPointer);#ifdef WINDOWS_VISUALSTUDIO_getch();#endifexit(EXIT_FAILURE); // exit (1);}}bool ListByArrayIsFull(const ArrayList * const Array){// if (Array != NULL)if (Array)return Array->size == Array->MaxSize;// if (Array == NULL)else{fprintf(stderr, "%s", NullPointer);#ifdef WINDOWS_VISUALSTUDIO_getch();#endifexit(EXIT_FAILURE); // exit (1);}}void PushByArray(ArrayList * const Array, const ArrayItem NewItem){// if (Array != NULL)if (Array){VertexSize order = Array->size;if (Array->size != Array->MaxSize) // 元素数量未至数据类型极限值{(Array->base)[order] = NewItem;++(Array->size); // 表长增1}// if (Array->size == Array->MaxSize)else // 元素数量已至数据类型极限值UnusualToExit(FULL_STACK, NULL);}// if (Array == NULL)elseUnusualToExit(NullPointer, NULL);}void PopByArray(ArrayList * const Array, ArrayItem * const DelItem){// if (Array != NULL && DelItem != NULL)if (Array && DelItem){VertexSize order = Array->size - 1;// if (Array->size != 0)if (Array->size) // 顺序表非空{*DelItem = Array->base[order];--(Array->size); // 表长减1}// if (Array->size == 0)else // 顺序表为空UnusualToExit(EMPTY_STACK, NULL);}// if (Array == NULL || DelItem == NULL)elseUnusualToExit(NullPointer, NULL);}

// 将标准图结构的顶点以数组存放// VertexArrayOfGraph.h#ifndef VERTEX_ARRAY_OF_GRAPH_H#define VERTEX_ARRAY_OF_GRAPH_H#include "graph.h"#define VERTEX_STRING "Vertex Of "void CreateListByVertexArray(ArrayVertexValue * const Array, const VertexSize Max, const char * const FileName);void DestroyListByVertexArray(ArrayVertexValue * const Array);void InputListByArrayFromFile(Graph * const G);void InputListByArrayFromKeyboard(Graph * const G, FILE * const stream);void OutputListByVertexArrayToFile(const ArrayVertexValue * const Array);void OutputListByVertexArrayToMonitor(const ArrayVertexValue * const Array, FILE * const stream);void AddTailListByVertexArray(ArrayVertexValue * const Array, const VertexValue * const NewItem);void DelSearchListByArray(ArrayVertexValue * const Array, const VertexValue * const DelVertex);#endif

// VertexArrayOfGraph.c#include "VertexArrayOfGraph.h"extern const char * const EofOperation;extern const char * const ReadOperation;extern const char * const WriteOperation;extern const char * const MemoryError;extern const char * const OpenFileError;extern const char * const CloseFileError;extern const char * const EmptyArray;extern const char * const FullArray;extern const char * const NameTooLong;extern const char * const NullPointer;// 创建空顺序表Arrayvoid CreateListByVertexArray(ArrayVertexValue * const Array, const VertexSize Max, const char * const FileName){// if (Array != NULL)if (Array){Array->base = (VertexValue *)malloc(Max * sizeof(VertexValue));// if (Array->base != NULL)if (Array->base){Array->size = 0; // 空表长度置0Array->MaxSize = Max;#ifdef WINDOWS_VISUALSTUDIOstrncpy_s(Array->FileName, _countof(Array->FileName), VERTEX_STRING, strlen(VERTEX_STRING) + 2);strncat_s(Array->FileName, _countof(Array->FileName), FileName, strlen(FileName) + 1);if (strlen(Array->FileName) + strlen(EXTEND) <= LEN - 1)strncat_s(Array->FileName, _countof(Array->FileName), EXTEND, strlen(EXTEND) + 1);// if (strlen(Array->FileName) + strlen(EXTEND) > LEN - 1)else#endif#ifndef WINDOWS_VISUALSTUDIOstrncpy(Array->FileName, VERTEX_STRING, strlen(VERTEX_STRING) + 2);strncat(Array->FileName, FileName, strlen(FileName) + 1);if (strlen(Array->FileName) > LEN - 1)#endifUnusualToExit(NameTooLong, NULL);}// if (Array->base == NULL)elseUnusualToExit(MemoryError, NULL);}// if (Array == NULL)elseUnusualToExit(NullPointer, NULL);}void DestroyListByVertexArray(ArrayVertexValue * const Array){// if (Array != NULL)if (Array){free(Array->base);Array->base = NULL;Array->size = Array->MaxSize = 0;}// if (Array == NULL)elseUnusualToExit(NullPointer, NULL);}// 文件输入void InputListByArrayFromFile(Graph * const G){// if (G != NULL && ReadOperation != NULL)if (G && ReadOperation){#ifdef WINDOWS_VISUALSTUDIOFILE *fp;errno_t err = fopen_s(&fp, G->VertexArray.FileName, ReadOperation);// if (err == 0)if (!err)InputListByArrayFromKeyboard(G, fp);// if (err == 1)elseUnusualToExit(OpenFileError, G->VertexArray.FileName);// if (fp != NULL)if (fp){// if (fclose(fp) != 0)if (fclose(fp))UnusualToExit(CloseFileError, G->VertexArray.FileName);}#endif#ifndef WINDOWS_VISUALSTUDIOFILE * const fp = fopen(G->VertexArray.FileName, ReadOperation);// if (fp != NULL)if (fp)InputListByArrayFromKeyboard(G, fp);// if (fp == NULL)elseUnusualToExit(OpenFileError, G->VertexArray.FileName);// if (fclose(fp) != 0)if (fclose(fp))UnusualToExit(CloseFileError, G->VertexArray.FileName);#endif}// if (G == NULL || ReadOperation == NULL)elseUnusualToExit(NullPointer, NULL);}void InputListByArrayFromKeyboard(Graph * const G, FILE * const stream){// if (G != NULL && stream != NULL)if (G && stream){if (stream == stdin){#ifdef WINDOWS_VISUALSTUDIOprintf(EofOperation, 'z');#endif#ifndef WINDOWS_VISUALSTUDIOprintf(EofOperation, 'd');#endif}VertexValue temp;// while (feof(stream) == 0)while (!feof(stream)){#ifdef WINDOWS_VISUALSTUDIOif (fscanf_s(stream, "%hd\n", &temp.KeyValue) != EOF) // 此处随元素属性而改变#endif#ifndef WINDOWS_VISUALSTUDIOif (fscanf(stream, "%hd\n", &temp.KeyValue) != EOF) // 此处随元素属性而改变#endifAddVertexOfGraph(G, &temp);}}// if (G == NULL || stream == NULL)elseUnusualToExit(NullPointer, NULL);}// 文件输出void OutputListByVertexArrayToFile(const ArrayVertexValue * const Array){// if (Array != NULL && WriteOperation != NULL)if (Array && WriteOperation){#ifdef WINDOWS_VISUALSTUDIOFILE *fp;errno_t err = fopen_s(&fp, Array->FileName, WriteOperation);// if (err == 0)if (!err)OutputListByVertexArrayToMonitor(Array, fp);// if (err == 1)elseUnusualToExit(OpenFileError, Array->FileName);// if (fp != NULL)if (fp){// if (fclose(fp) != 0)if (fclose(fp))UnusualToExit(CloseFileError, Array->FileName);}#endif#ifndef WINDOWS_VISUALSTUDIOFILE * const fp = fopen(Array->FileName, WriteOperation);// if (fp != NULL)if (fp)OutputListByVertexArrayToMonitor(Array, fp);// if (fp == NULL)elseUnusualToExit(OpenFileError, Array->FileName);// if (fclose(fp) != 0)if (fclose(fp))UnusualToExit(CloseFileError, Array->FileName);#endif}// if (Array == NULL || WriteOperation == NULL)elseUnusualToExit(NullPointer, NULL);}// 输出顺序表List的所有元素void OutputListByVertexArrayToMonitor(const ArrayVertexValue * const Array, FILE * const stream){// if (Array != NULL && stream != NULL)if (Array && stream){VertexSize index;for (index = 0; index < Array->size; ++index)fprintf(stream, "%d\n", Array->base[index].KeyValue); // 此处随元素属性而改变}// if (Array == NULL || stream == NULL)elseUnusualToExit(NullPointer, NULL);}void AddTailListByVertexArray(ArrayVertexValue * const Array, const VertexValue * const NewItem){// if (Array != NULL && NewItem != NULL)if (Array && NewItem){VertexSize order = Array->size;if (Array->size != Array->MaxSize) // 元素数量未至数据类型极限值{(Array->base)[order] = *NewItem;++(Array->size); // 表长增1}// if (Array->size == Array->MaxSize)else // 元素数量已至数据类型极限值UnusualToExit(FullArray, NULL);}// if (Array == NULL || NewItem == NULL)elseUnusualToExit(NullPointer, NULL);}void DelSearchListByArray(ArrayVertexValue * const Array, const VertexValue * const DelVertex){// if (Array != NULL && DelVertex != NULL)if (Array && DelVertex){// if (Array->size != 0)if (Array->size){if (DelVertex->KeyValue != Array->size - 1){VertexSize BuckUp = DelVertex->KeyValue;Array->base[DelVertex->KeyValue] = Array->base[Array->size - 1];Array->base[DelVertex->KeyValue].KeyValue = BuckUp;}--(Array->size); // 表长减1}// if (Array->size == 0)elseUnusualToExit(EmptyArray, NULL);}// if (Array == NULL || DelVertex == NULL)elseUnusualToExit(NullPointer, NULL);}

// 将标准图结构的边以链表存放// EdgeLinkOfGraph.h#ifndef EDGE_LINK_OF_GRAPH_H#define EDGE_LINK_OF_GRAPH_H#include "graph.h"#define EDGE_STRING "Edge Of "void CreateListByEdgeLink(LinkEdgeValue * const Link, const EdgeSize Max, const char * const FileName);void DestoryListByEdgeLink(LinkEdgeValue * const Link);void InputListByLinkFromFile(Graph * const G);void InputListByLinkFromKeyboard(Graph * const G, FILE * const stream);void OutputListByEdgeLinkToFile(const LinkEdgeValue * const Link);void OutputListByEdgeLinkToMonitor(const LinkEdgeValue * const Link, FILE * const stream);void AddTailListByEdgeLink(LinkEdgeValue * const Link, const EdgeValue * const NewItem);void DelSearchListByLink(LinkEdgeValue * const Link, const EdgeValue * const DelEdge);void DelStartOrEndOfTheEdgeByLink(LinkEdgeValue * const Link, const VertexSize * const DelEdge, const VertexSize Change);#endif

// EdgeLinkOfGraph.c#include "EdgeLinkOfGraph.h"extern const char * const EofOperation;extern const char * const ReadOperation;extern const char * const WriteOperation;extern const char * const MemoryError;extern const char * const OpenFileError;extern const char * const CloseFileError;extern const char * const NameTooLong;extern const char * const NullPointer;static const char * const EMPTY_LINK = "空链表\n";static const char * const FULL_LINK = "满链表\n";void CreateListByEdgeLink(LinkEdgeValue * const Link, const EdgeSize Max, const char * const FileName){// if (Link != NULL)if (Link){Link->head = Link->tail = NULL;Link->size = 0;Link->MaxSize = Max;#ifdef WINDOWS_VISUALSTUDIOstrncpy_s(Link->FileName, _countof(Link->FileName), EDGE_STRING, strlen(EDGE_STRING) + 1);strncat_s(Link->FileName, _countof(Link->FileName), FileName, strlen(FileName) + 1);if (strlen(Link->FileName) + strlen(EXTEND) <= LEN - 1)strncat_s(Link->FileName, _countof(Link->FileName), EXTEND, strlen(EXTEND) + 1);// if (strlen(Link->FileName) + strlen(EXTEND) > LEN - 1)else#endif#ifndef WINDOWS_VISUALSTUDIOstrncpy(Link->FileName, EDGE_STRING, strlen(EDGE_STRING) + 1);strncat(Link->FileName, FileName, strlen(FileName) + 1);if (strlen(Link->FileName) > LEN - 1)#endifUnusualToExit(NameTooLong, NULL);}// if (Link == NULL)elseUnusualToExit(NullPointer, NULL);}void DestoryListByEdgeLink(LinkEdgeValue * const Link){// if (Link != NULL)if (Link){NodeOfEdge *psave = Link->head;// while (psave != NULL)while (psave){psave = Link->head->next; // 保存下一个结点的地址free(Link->head); // 释放当前结点Link->head = psave; // 前进到下一个结点}Link->head = Link->tail = NULL;Link->size = Link->MaxSize = 0;}// if (Link == NULL)elseUnusualToExit(NullPointer, NULL);}// 文件输入void InputListByLinkFromFile(Graph * const G){// if (G != NULL && ReadOperation != NULL)if (G && ReadOperation){#ifdef WINDOWS_VISUALSTUDIOFILE *fp;errno_t err = fopen_s(&fp, G->EdgeLink.FileName, ReadOperation);// if (err == 0)if (!err)InputListByLinkFromKeyboard(G, fp);// if (err == 1)elseUnusualToExit(OpenFileError, G->EdgeLink.FileName);// if (fp != NULL)if (fp){// if (fclose(fp) != 0)if (fclose(fp))UnusualToExit(CloseFileError, G->EdgeLink.FileName);}#endif#ifndef WINDOWS_VISUALSTUDIOFILE * const fp = fopen(G->EdgeLink.FileName, ReadOperation);// if (fp != NULL)if (fp)InputListByLinkFromKeyboard(G, fp);// if (fp == NULL)elseUnusualToExit(OpenFileError, G->EdgeLink.FileName);// if (fclose(fp) != 0)if (fclose(fp))UnusualToExit(CloseFileError, G->EdgeLink.FileName);#endif}// if (G == NULL || ReadOperation == NULL)elseUnusualToExit(NullPointer, NULL);}void InputListByLinkFromKeyboard(Graph * const G, FILE * const stream){// if (G != NULL && stream != NULL)if (G && stream){if (stream == stdin){#ifdef WINDOWS_VISUALSTUDIOprintf(EofOperation, 'z');#endif#ifndef WINDOWS_VISUALSTUDIOprintf(EofOperation, 'd');#endif}EdgeValue temp;// while (feof(stream) == 0)while (!feof(stream)){#ifdef WINDOWS_VISUALSTUDIOif (fscanf_s(stream, "%hd\t%hd\t%hd\n", &temp.start.KeyValue, &temp.end.KeyValue, &temp.Weight) != EOF) // 此处随元素属性而改变#endif#ifndef WINDOWS_VISUALSTUDIOif (fscanf(stream, "%hd\t%hd\t%hd\n", &temp.start.KeyValue, &temp.end.KeyValue, &temp.Weight) != EOF) // 此处随元素属性而改变#endifAddEdgeOfGraph(G, &temp);}}// if (G == NULL || stream == NULL)elseUnusualToExit(NullPointer, NULL);}// 文件输出void OutputListByEdgeLinkToFile(const LinkEdgeValue * const Link){// if (Link != NULL && WriteOperation != NULL)if (Link && WriteOperation){#ifdef WINDOWS_VISUALSTUDIOFILE *fp;errno_t err = fopen_s(&fp, Link->FileName, WriteOperation);// if (err == 0)if (!err)OutputListByEdgeLinkToMonitor(Link, fp);// if (err == 1)elseUnusualToExit(OpenFileError, Link->FileName);// if (fp != NULL)if (fp){// if (fclose(fp) != 0)if (fclose(fp))UnusualToExit(CloseFileError, Link->FileName);}#endif#ifndef WINDOWS_VISUALSTUDIOFILE * const fp = fopen(Link->FileName, WriteOperation);// if (fp != NULL)if (fp)OutputListByEdgeLinkToMonitor(Link, fp);// if (fp == NULL)elseUnusualToExit(OpenFileError, Link->FileName);// if (fclose(fp) != 0)if (fclose(fp))UnusualToExit(CloseFileError, Link->FileName);#endif}// if (Link == NULL || WriteOperation == NULL)elseUnusualToExit(NullPointer, NULL);}void OutputListByEdgeLinkToMonitor(const LinkEdgeValue * const Link, FILE * const stream){// if (Link != NULL && stream != NULL)if (Link && stream){const NodeOfEdge *current = Link->head;// while (current != NULL)while (current){fprintf(stream, "%d\t%d\t%d\n", current->item.start.KeyValue, current->item.end.KeyValue, current->item.Weight); // 此处随元素属性而改变current = current->next;}}// if (Link == NULL || stream == NULL)elseUnusualToExit(NullPointer, NULL);}// 创建存放项目的结点,并把它添加到由Link指向的列表尾部void AddTailListByEdgeLink(LinkEdgeValue * const Link, const EdgeValue * const NewItem){// if (Link != NULL && NewItem != NULL)if (Link && NewItem){if (Link->size != Link->MaxSize){NodeOfEdge * const NewNode = (NodeOfEdge *)malloc(sizeof(NodeOfEdge));// if (NewNode != NULL)if (NewNode){// if (Link->size != 0) if (Link->size) // 链表有结点Link->tail->next = NewNode;// if (Link->size == 0)else // 链表无结点Link->head = NewNode;Link->tail = NewNode;NewNode->next = NULL;NewNode->item = *NewItem;++(Link->size);}// if (NewNode == NULL)elseUnusualToExit(MemoryError, NULL);}// if (Link->size == Link->MaxSize)elseUnusualToExit(FULL_LINK, NULL);}// if (Link == NULL || NewItem == NULL)elseUnusualToExit(NullPointer, NULL);}// 本函数order越大效率越低// 在链表Link中删除指定边void DelSearchListByLink(LinkEdgeValue * const Link, const EdgeValue * const DelEdge){// if (Link != NULL && DelEdge != NULL)if (Link && DelEdge){// if (Link->size != 0)if (Link->size){if (Link->size > 1){NodeOfEdge * result = Link->head;if (result->item.start.KeyValue != DelEdge->start.KeyValue || result->item.end.KeyValue != DelEdge->end.KeyValue) // 首个结点不为欲删除的结点{// while (result->next != NULL)while (result->next){if (result->next->item.start.KeyValue != DelEdge->start.KeyValue || result->next->item.end.KeyValue != DelEdge->end.KeyValue)result = result->next;// if (result->next->item.start.KeyValue != DelEdge->start.KeyValue && result->next->item.end.KeyValue != DelEdge->end.KeyValue)else{NodeOfEdge * const ptr = result->next;result->next = ptr->next;free(ptr);--Link->size;return; // 若链表中有重复的指定元素值删除本行}}}// if (result->item.start.KeyValue == DelEdge->start.KeyValue && result->item.end.KeyValue == DelEdge->end.KeyValue)else // 首个结点为欲删除的结点{NodeOfEdge * const ptr = Link->head->next;free(Link->head);Link->head = ptr;--Link->size;}}// if (Link->size == 1)else{if (Link->head->item.start.KeyValue == DelEdge->start.KeyValue && Link->head->item.end.KeyValue == DelEdge->end.KeyValue){free(Link->head);Link->head = Link->tail = NULL;Link->size = 0;}}}// if (Link->size == 0)elseUnusualToExit(EMPTY_LINK, NULL);}// if (Link == NULL || DelEdge == NULL)elseUnusualToExit(NullPointer, NULL);}void DelStartOrEndOfTheEdgeByLink(LinkEdgeValue * const Link, const VertexSize * const DelEdge, const VertexSize MaxVertex){// if (Link != NULL && DelEdge != NULL)if (Link && DelEdge){// if (Link->size != 0)if (Link->size){if (Link->size > 1){NodeOfEdge * result = Link->head;if (result->item.start.KeyValue == *DelEdge || result->item.end.KeyValue == *DelEdge) // 首个结点为欲删除的结点{NodeOfEdge * const ptr = Link->head->next;free(Link->head);Link->head = ptr;--Link->size;}// while (result->next != NULL)while (result->next){if (result->next->item.start.KeyValue != *DelEdge && result->next->item.end.KeyValue != *DelEdge)result = result->next;// if (result->next->item.start.KeyValue == *DelEdge || result->next->item.end.KeyValue == *DelEdge)else{NodeOfEdge * const ptr = result->next;result->next = ptr->next;free(ptr);--Link->size;}}result = Link->head;// while (result != NULL)while (result){if (result->item.start.KeyValue == MaxVertex)result->item.start.KeyValue = *DelEdge;if (result->item.end.KeyValue == MaxVertex)result->item.end.KeyValue = *DelEdge;result = result->next;}}// if (Link->size == 1)else{if (Link->head->item.start.KeyValue == *DelEdge || Link->head->item.end.KeyValue == *DelEdge){free(Link->head);Link->head = Link->tail = NULL;Link->size = 0;}}}// if (Link->size == 0)elseUnusualToExit(EMPTY_LINK, NULL);}// if (Link == NULL || DelEdge == NULL)elseUnusualToExit(NullPointer, NULL);}

// main.c// 本文件为图接口测试程序 仅供参考#include "graph.h"int main(const int argc, const char * const argv[ ]){Graph Graph;char * const FileName = "Graph";const char kind = 4; // 1无向图 2有向图 3无向网络 4有向网络const VertexValue NewVertex[] = { { 0 }, { 1 }, { 2 }, { 3 }, { 4 }, { 5 }, { 6 } };const EdgeValue NewEdges[] = {{ 0, 1, 2 },{ 2, 0, 4 },{ 0, 3, 1 },{ 1, 3, 3 },{ 1, 4, 10 },{ 3, 2, 2 },{ 3, 4, 7 },{ 2, 5, 5 },{ 3, 5, 8 },{ 3, 6, 4 },{ 4, 6, 6 },{ 6, 5, 1 } };CreateGraph(&Graph, kind, FileName);// 必须以0 1 2 3的递增顺序输入顶点VertexSize V;for(V = 0; V < sizeof(NewVertex) / sizeof(NewVertex[0]); ++V)AddVertexOfGraph(&Graph, &NewVertex[V]);EdgeSize E;for (E = 0; E < sizeof(NewEdges) / sizeof(NewEdges[0]); ++E)AddEdgeOfGraph(&Graph, &NewEdges[E]);OutputGraphToFile(&Graph);DistoryGraph(&Graph);CreateGraph(&Graph, kind, FileName);InputGraphFromFile(&Graph);MGraph MG;ALGraph ALG;CreateMGraph(&Graph, &MG);CreateALGraph(&Graph, &ALG);MakeMGraph(&Graph, &MG);MakeALGraph(&Graph, &ALG);OutputMGraphToFile(&Graph, &MG);OutputALGraphToFile(&Graph, &ALG);OutputMGraphToMonitor(&Graph, &MG, stdout);OutputALGraphToMonitor(&Graph, &ALG, stdout);// UnweightedByMGraph(&Graph, &MG, &NewVertex[0], &NewVertex[5], stdout);// UnweightedByALGraph(&Graph, &ALG, &NewVertex[0], &NewVertex[5], stdout);// DijkstraByMGraph(&Graph, &MG, &NewVertex[0], &NewVertex[5], stdout);// DijkstraByALGraph(&Graph, &ALG, &NewVertex[0], &NewVertex[5], stdout);// FloydByMGraph(&Graph, &MG, &NewVertex[0], &NewVertex[5], stdout);// FloydByALGraph(&Graph, &ALG, &NewVertex[0], &NewVertex[5], stdout);// 最小生成树PrimByMGraph(&Graph, &MG, &NewVertex[0]);PrimByALGraph(&Graph, &ALG, &NewVertex[0]);KruskalMGraph(&Graph, &MG);KruskalALGraph(&Graph, &ALG);// DelVertexOfGraph(&Graph, &NewVertex[4]);// DelEdgeOfGraph(&Graph, &NewEdges[8]);DistoryGraph(&Graph);DistoryMGraph(&MG);DistoryALGraph(&Graph, &ALG);#ifdef WINDOWS_VISUALSTUDIO_getch();#endifreturn 0;}

0 0
原创粉丝点击