数据结构复习:图的基本操作、应用(邻接表实现)

#include <iostream>
#include "Stack.h"
#include "Queue.h"

#define INFINITY 2147483647
#define MaxVertexNum 15
typedef struct VertexType {
    char value;
} VertexType;
typedef struct ArcNode {
    int adjvex; // 边/弧指向哪个顶点
    struct ArcNode *next;//指向下一条弧的指针
    int weight;//权值
} ArcNode, *Arc;
typedef struct VNode {
    VertexType data;//顶点信息
    ArcNode *first;//第一条边/弧信息
} VNode, AdjList[MaxVertexNum];

//用邻接表存储的图
typedef struct {
    AdjList vertices;
    int vexnum, arcnum;//图的顶点数和边数
    int type;//图的类型  0为无向图 1为有向图
} ALGraph;

//初始化一个具有一个顶点的图
void InitALGraph(ALGraph &G, int type) {
    for (int i = 0; i < MaxVertexNum; ++i) {
        G.vertices[i].first = NULL;
        G.vertices[i].data = {};
    }
    G.vexnum = 0;
    VNode &vNode = G.vertices[G.vexnum];
    vNode.data = {'A'};
    vNode.first = NULL;
    G.vexnum++;
    G.arcnum = 0;
    G.type = type;
}

//在图G中插入顶点x
void InsertVertex(ALGraph &G, char x) {
    VNode &vNode = G.vertices[G.vexnum];
    vNode.data = {x};
    vNode.first = NULL;
    G.vexnum++;
}


//判断是否是顶点
bool isVertex(ALGraph G, int x) {
    return (x >= 0) && (x < G.vexnum);
}

//无向边(x,y) 或 有向边<x,y>不存在,则向图G中添加该边
void AddEdge(ALGraph &G, int x, int y) {
    if (!isVertex(G, x) || !isVertex(G, y)) {
        return;
    }
    ArcNode *p = (ArcNode *) malloc(sizeof(ArcNode));
    if (p == NULL) return;
    p->next = NULL;
    p->weight = 0;
    p->adjvex = y;
    if (G.vertices[x].first == NULL) {
        G.vertices[x].first = p;
    } else {
        ArcNode *s = G.vertices[x].first;
        while (s->next != NULL) {
            s = s->next;
        }
        Arc &arc = s;
        arc->next = p;
    }
    if (G.type == 0) {//无向图
        ArcNode *q = (ArcNode *) malloc(sizeof(ArcNode));
        if (q == NULL) return;
        q->next = NULL;
        q->weight = 0;
        q->adjvex = x;
        if (G.vertices[y].first == NULL) {
            G.vertices[y].first = q;
        } else {
            ArcNode *s = G.vertices[y].first;
            while (s->next != NULL) {
                s = s->next;
            }
            Arc &arc = s;
            arc->next = q;
        }
    }
    G.arcnum++;
}

//判断图G是否存在边<x,y>或(x,y)
bool Adjacent(ALGraph G, int x, int y) {
    if (!isVertex(G, x) || !isVertex(G, y)) {
        return false;
    }
    ArcNode *p = G.vertices[x].first;
    while (p != NULL) {
        if (p->adjvex == y) {
            return true;
        }
        p = p->next;
    }
    return false;
}

//在图G中删除顶点x
void DeleteVertex(ALGraph &G, int x) {
    if (!isVertex(G, x)) {
        return;
    }
    ArcNode *p = G.vertices[x].first;
    if (p == NULL) {
        //x不存在出边
        if (G.type == 0) {//无向图直接删除
            G.vertices[x].data = {};
            G.vexnum--;
            return;
        }
    } else {
        //先删除x的链表
        while (p != NULL) {
            ArcNode *q = p;
            p = p->next;
            free(q);
        }
        G.vertices[x].first = NULL;
        G.vertices[x].data = {};
        G.vexnum--;

    }
    //删除入边,包含两种情况
    //1)有向图不存在出边,但是可能有入边
    //2)无向图已经删除了入边,要找到所有出边删除
    for (int i = 0; i < G.vexnum + 1; ++i) {
        if (x == i) continue;
        ArcNode *q = G.vertices[i].first;
        if (q == NULL) {
            continue;
        }

        if (q != NULL && q->adjvex == x) {
            G.vertices[i].first = q->next;
        }
        while (q->next != NULL && q->next->adjvex != x) {
            q = q->next;
        }
        if (q->next != NULL && q->next->adjvex == x) {
            ArcNode *s = q->next;
            q->next = q->next->next;
            free(s);
        }
    }

}

//无向边(x,y) 或 有向边<x,y>存在,则删除该边
void RemoveEdge(ALGraph &G, int x, int y) {
    if (!isVertex(G, x) || !isVertex(G, y)) {
        return;
    }
    ArcNode *p = G.vertices[x].first;
    if (p == NULL) {
        if (G.type == 0) {
            printf("边/弧 %c%c不存在\n", G.vertices[x].data.value, G.vertices[y].data.value);
            return;
        }
    } else {
        if (p->adjvex == y) {//如果第一个结点是y
            G.vertices[x].first = p->next;
            free(p);
            G.arcnum--;
        } else {
            while (p->next != NULL && p->next->adjvex != y) {
                p = p->next;
            }
            if (p->next == NULL) {//没找到边
                printf("边/弧 %c%c不存在\n", G.vertices[x].data.value, G.vertices[y].data.value);
                return;
            }
            G.arcnum--;
            ArcNode *s = p->next;
            p->next = p->next->next;
            free(s);
        }
        if (G.type == 0) {//如果删除的是无向图,这时候已经找到并删除了xy,这时候需要找到yx删除
            ArcNode *q = G.vertices[y].first;//边一定存在
            if (q->adjvex == x) {//第一个就是
                G.vertices[y].first = q->next;
                free(q);
            } else {//不是第一个
                while (q->next->adjvex != x) {
                    q = q->next;
                }
                ArcNode *s = q->next;
                q->next = q->next->next;
                free(s);
            }
        }
    }
}

//求图G中顶点x的第一个邻接点,若有返回顶点号。若x没有邻接点或图中不存在x,返回-1
int FirstNeighbor(ALGraph G, int x) {
    if (!isVertex(G, x)) return -1;
    ArcNode *p = G.vertices[x].first;
    if (p == NULL) {
        if (G.type == 0) {
            return -1;
        }
    } else {
        return p->adjvex;
    }

    return -1;//找不到
}

//假设图G中顶点y是x的一个邻接点,返回除了y之外顶点x的下一个邻接点的顶点号,若y是x的最后一个邻接点,返回-1
int NextNeighbor(ALGraph G, int x, int y) {
    if (!isVertex(G, x) || !isVertex(G, y)) {
        return -1;
    }
    ArcNode *p = G.vertices[x].first;
    bool yExist = false;
    if (p == NULL) {
        if (G.type == 0) {
            return -1;
        }
    } else {
        while (p != NULL && p->adjvex != y) {
            p = p->next;
        }
        if (p == NULL || p->next == NULL) {//没找到y或者 y是出边最后一个顶点
            if (G.type == 0) { // 如果是无向图
                return -1;
            }
            if (p != NULL && p->next == NULL) {
                //如果y是出边的最后一个结点
                yExist = true;
            }
        } else {
            return p->next->adjvex;
        }
    }

    return -1;//没找到
}

//列出图G中与顶点x临界的边
void Neighbors(ALGraph G, int x) {
    printf("与顶点%c临界的边有:", G.vertices[x].data.value);
    if (!isVertex(G, x)) {
        return;
    }
    ArcNode *p = G.vertices[x].first;
    if (p == NULL) {
        if (G.type == 0) {//如果是无向图
            printf("不存在与顶点x临界的边\n");
            return;
        }
    } else {
        ArcNode *p = G.vertices[x].first;
        while (p != NULL) {
            printf("%c%c ", G.vertices[x].data.value, G.vertices[p->adjvex].data.value);
            p = p->next;
        }
    }
    if (G.type == 0) {
        printf("\n");
        return;
    }
    //如果是有向图,寻找x的所有入边
    for (int i = 0; i < G.vexnum; ++i) {
        ArcNode *q = G.vertices[i].first;
        while (q != NULL) {
            if (q->adjvex == x) {//找到了一条x的入边
                printf("%c%c ", G.vertices[i].data.value, G.vertices[x].data.value);
            }
            q = q->next;
        }
    }
    printf("\n");
}

//获取图G中边<x,y>或(x,y)对应的权值
int Get_edge_value(ALGraph G, int x, int y) {
    if (!isVertex(G, x) || !isVertex(G, y)) {
        return -1;
    }
    ArcNode *p = G.vertices[x].first;
    while (p != NULL) {
        if (p->adjvex == y) {
            return p->weight;
        }
        p = p->next;
    }
    return -1;//没找到xy的边
}

//设置图G中边<x,y>或(x,y)对应的权值为v
void Set_edge_value(ALGraph &G, int x, int y, int v) {
    if (!isVertex(G, x) || !isVertex(G, y)) {
        return;
    }
    ArcNode *p = G.vertices[x].first;
    while (p != NULL) {
        if (p->adjvex == y) {
            ArcNode &arc = *p;
            arc.weight = v;

        }
        p = p->next;
    }
    if (G.type == 0) {
        ArcNode *q = G.vertices[y].first;
        while (q != NULL) {
            if (q->adjvex == x) {
                ArcNode &arc = *q;
                q->weight = v;
            }
            q = q->next;
        }
    }
}

//访问顶点v
void visit(ALGraph G, int v) {
    printf("%c ", G.vertices[v].data.value);
}

LinkQueue Q;//队列用于存放顺序访问的结点
int visited[MaxVertexNum];//存放每个结点的访问情况

//广度优先遍历
void BFS(ALGraph G, int v) { //从顶点 v 出发
    visit(G, v);
    visited[v] = true;
    EnQueue(Q, v);
    while (!QueueEmpty(Q)) {
        int x;
        DeQueue(Q, x);
        int y = FirstNeighbor(G, x);//找到第一个邻接点
        while (y != -1) {
            if (!visited[y]) {//如果未被访问过
                visited[y] = true;//访问该邻接点
                visit(G, y);
                EnQueue(Q, y);//入队
            }
            y = NextNeighbor(G, x, y);//访问下一个邻接点
        }
    }
}

void BFSTraverse(ALGraph G) {
    printf("广度优先遍历序列: ");
    for (int i = 0; i < G.vexnum; ++i) {
        visited[i] = false;
    }
    InitQueue(Q);
    for (int i = 0; i < G.vexnum; ++i) {
        if (!visited[i]) { //如果当前结点没有被访问
            BFS(G, i);
        }
    }
    printf("\n");
}

//深度优先遍历
void DFS(ALGraph G, int v) {
    visited[v] = true;
    visit(G, v);
    for (int w = FirstNeighbor(G, v); w >= 0; w = NextNeighbor(G, v, w)) {
        if (!visited[w])
            DFS(G, w);
    }
}

void DFSTraverse(ALGraph G) {
    printf("深度优先遍历序列: ");
    for (int i = 0; i < G.vexnum; ++i) {
        visited[i] = false;
    }
    for (int i = 0; i < G.vexnum; ++i) {
        if (!visited[i]) { //非联通图无法一次访问完成
            DFS(G, i);
        }
    }
    printf("\n");
}

bool isJoin[MaxVertexNum];//标记各结点是否加入树
int lowCast[MaxVertexNum];//各结点加入树的最低代价

//Prim算法求最小代价生成树
void Prim(ALGraph G) {
    printf("\nPrim算法求最小代价生成树: ");
    isJoin[0] = true;//将第一个结点加入树
    for (int i = 1; i < G.vexnum; ++i) {
        isJoin[i] = false;
    }
    lowCast[0] = 0;
    for (int j = 1; j < G.vexnum; ++j) {
        int w = Get_edge_value(G, 0, j);//获取余该顶点关联的边/弧的权值
        if (w != -1) {
            lowCast[G.vertices[j].data.value] = w;
        } else {
            lowCast[G.vertices[j].data.value] = INFINITY;
        }
    }
    int minWeight = -1, minIndex = -1;
    while (true) {
        minIndex = -1, minWeight = -1;//如果代价表中不存在未被访问的结点,则为minIndex未更新
        for (int k = 0; k < G.vexnum; ++k) {
            //获取代价表中未被访问结点到最小值
            if (!isJoin[k] && lowCast[k] != INFINITY) {
                if (minIndex == -1) {
                    minWeight = lowCast[k];
                    minIndex = k;
                } else {
                    if (lowCast[k] < minWeight) {
                        minWeight = lowCast[k];
                        minIndex = k;
                    }
                }
            }
        }
        if (minIndex == -1)
            break;
        isJoin[minIndex] = true;//访问顶点
        for (int j = 1; j < G.vexnum; ++j) {
            if (!isJoin[j]) {//如果该顶点未加入生成树
                int w = Get_edge_value(G, minIndex, j);//获取顶点相关的边的权值
                if (w != -1) {//如果边存在
                    if (w < lowCast[j]) { //较小,则更新代价表
                        lowCast[j] = w;
                    }
                }
            }
        }
    }
    int value = 0;
    for (int i = 0; i < G.vexnum; ++i) {
        value += lowCast[i];
    }
    printf("最小代价:%d", value);
    printf("\n");
}

typedef struct {
    int vertex1;
    int vertex2;
    int weight;
} WeightOrderEdge;//存储按照权值排序的边
typedef struct Node {
    int data;
    int parent;
} Node;
typedef struct {
    Node sets[MaxVertexNum];
    int n;
} UFSets;

//初始化集合
void InitUFSets(UFSets &S, int size) {
    for (int i = 0; i < size; ++i) {
        S.sets[i].data = {i};
        S.sets[i].parent = -1;
    }
    S.n = size;
}

//查找某个元素的属于哪个集合
int Find(UFSets S, int i) {
    if (S.sets[i].parent == -1)
        return i;
    while (S.sets[i].parent != -1) {
        i = S.sets[i].parent;
    }
    return i;
}

//合并两个集合
void Union(UFSets &S, int index1, int index2) {
    Node &root1 = S.sets[index1];
    Node &root2 = S.sets[index2];
    if (root1.parent >= 0 ||
        root2.parent >= 0) {//不是集合
        return;
    }
    root2.parent = index1;
}

//Kruskal算法求最小代价生成树
void Kruskal(ALGraph G) {
    printf("\nKruskal算法求最小代价生成树: ");
    WeightOrderEdge E[G.arcnum]; //存储按照权值排序的边信息
    for (int i = 0; i < G.arcnum; ++i) {
        E[i].weight = INFINITY;
        E[i].vertex1 = -1;
        E[i].vertex2 = -1;
    }
    int k = 0;
    //将各条边按照权值排序
    for (int i = 0; i < G.vexnum; ++i) {
        for (int j = 0; j < G.vexnum; ++j) {
            if (i <= j) {
                int w = Get_edge_value(G, i, j);
                if (w != -1) {
                    E[k].vertex1 = i;
                    E[k].vertex2 = j;
                    E[k].weight = w;
                    k++;
                }
            }
        }
    }
    for (int i = 0; i < G.arcnum - 1; ++i) {
        int min = i;
        for (int j = i + 1; j < G.arcnum; ++j) {
            if (E[j].weight < E[min].weight) {
                min = j;
            }
        }
        if (min != i) {
            int minVertex1 = E[min].vertex1, minVertex2 = E[min].vertex2, minWeight = E[min].weight;
            int iVertex1 = E[i].vertex1, iVertex2 = E[i].vertex2, iWeight = E[i].weight;
            E[min].vertex1 = iVertex1;
            E[min].vertex2 = iVertex2;
            E[min].weight = iWeight;
            E[i].vertex1 = minVertex1;
            E[i].vertex2 = minVertex2;
            E[i].weight = minWeight;
        }
    }
    UFSets S;
    InitUFSets(S, G.arcnum);//初始化集合
    int value = 0;//统计最小代价(权值之和)
    for (int i = 0; i < G.arcnum; ++i) {
        //检查两个顶点是否属于同一集合
        int vertex1 = E[i].vertex1;
        int vertex2 = E[i].vertex2;
        int set1 = Find(S, vertex1);
        int set2 = Find(S, vertex2);
        if (set1 == set2) {//说明已经联通
            continue;
        } else {//不是一个集合,合并
            Union(S, set1, set2);
            value += E[i].weight;
        }
    }
    printf("最小代价:%d\n", value);
}

int d[MaxVertexNum];//路径长度
int path[MaxVertexNum];//路径从哪个顶点过来


//广度优先搜索算法求顶点 v 到其他顶点的最短路径 用于(无权图、权值为1的图)
void BFS_MIN_DISTANCE(ALGraph G, int v) { //从顶点 v 出发
    printf("\nBFS求顶点 %d 到其他各顶点之间的最短路径: ", v);
    for (int i = 0; i < G.vexnum; ++i) {
        visited[i] = false;
    }
    InitQueue(Q);
    for (int i = 0; i < G.vexnum; ++i) {
        d[i] = INFINITY;
        path[i] = -1;
    }
    d[v] = 0;//顶点v到顶点v的距离为0
    visited[v] = true;
    EnQueue(Q, v);
    while (!QueueEmpty(Q)) {
        int x;
        DeQueue(Q, x);
        int y = FirstNeighbor(G, x);//找到第一个邻接点
        while (y != -1) {
            if (!visited[y]) {//如果未被访问过
                d[y] = d[x] + 1;//路径长度 +1
                path[y] = x;//最短路径应从x到y
                visited[y] = true;//访问该邻接点
                EnQueue(Q, y);//入队
            }
            y = NextNeighbor(G, x, y);//访问下一个邻接点
        }
    }
    printf("\n");
}

bool final[MaxVertexNum];//标记各个顶点是否已找到最短路径
int dist[MaxVertexNum];//最短路径长度
//int path[MaxVertexNum];//路径上的直接前驱

//Dijkstra求单源点最短路径问题(带权图、无权图) 不适合带负权值的图
void Dijkstra(ALGraph G, int v) {
    printf("\nDijkstra算法求顶点 %d 到其他各顶点之间的最短路径: ", v);
    for (int i = 0; i < G.vexnum; ++i) {
        final[i] = false;//标记其他结点还没有找到最短路径
        dist[i] = INFINITY;
        path[i] = -1;
    }
    path[v] = -1;
    dist[v] = 0;
    final[v] = true;
    for (int j = 0; j < G.vexnum; ++j) {
        if (j != v) {
            int w = Get_edge_value(G, v, j);
            if (w != -1) {
                dist[j] = w;
                path[j] = v;
            }
        }
    }
    int min;
    while (true) {
        min = -1;
        for (int i = 0; i < G.vexnum; ++i) {
            if (!final[i]) {
                if (min == -1) {
                    min = i;
                } else {
                    if (dist[i] < dist[min]) {
                        min = i;
                    }
                }
            }
        }
        if (min == -1) {
            break;
        }
        final[min] = true;
        for (int j = 0; j < G.vexnum; ++j) {
            if (!final[j]) {
                int w = Get_edge_value(G, min, j);
                if (w != -1) {
                    int d = w + dist[min];
                    if (d < dist[j]) {
                        dist[j] = d;
                        path[j] = min;
                    }
                }
            }
        }
    }
    printf("\n");

}

int paths[MaxVertexNum][MaxVertexNum];//各个顶点之间的中转点
int A[MaxVertexNum][MaxVertexNum];//各个顶点之间的最短路径长度


LinkStack S;

void getPaths(ALGraph G, int i, int j) {
    if (paths[i][j] == -1) {
        printf("->%d", j);
        return;
    }
    if (A[i][j] != INFINITY) {
        int k = paths[i][j];
        getPaths(G, i, k);
        getPaths(G, k, j);
    }
}

// Floyd 算法求各顶点之间的最短路径
void Floyd(ALGraph G) {
    printf("Floyd算法求各顶点之间的最短路径:\n");
    //初始化
    for (int i = 0; i < G.vexnum; ++i) {
        for (int j = 0; j < G.vexnum; ++j) {
            paths[i][j] = -1;
            if (i == j) {
                A[i][j] = 0;
                continue;
            }
            int w = Get_edge_value(G, i, j);
            if (w != -1) {
                A[i][j] = w;
            } else {
                A[i][j] = INFINITY;
            }
        }
    }
    for (int k = 0; k < G.vexnum; ++k) {
        for (int i = 0; i < G.vexnum; ++i) {
            for (int j = 0; j < G.vexnum; ++j) {
                if (A[i][k] == INFINITY || A[k][j] == INFINITY) {
                    continue;
                }
                if (A[i][j] > A[i][k] + A[k][j]) {
                    A[i][j] = A[i][k] + A[k][j];
                    paths[i][j] = k;
                }
            }
        }
    }

    InitStack(S);
    for (int i = 0; i < G.vexnum; ++i) {
        printf("顶点%d到其他顶点  最短路径: \n", G.vertices[i].data.value);
        for (int j = 0; j < G.vexnum; ++j) {

            if (A[i][j] != INFINITY) {
                printf("%d到%d: ", i, j);
                printf("%d", i);
                getPaths(G, i, j);
                printf("\n");
            }
        }
    }
    printf("\n");
}

int indegree[MaxVertexNum];//记录当前顶点入度
int print[MaxVertexNum];//记录拓扑序列

//拓扑排序
bool TopologicalSort(ALGraph G) {
    //初始化
    for (int i = 0; i < G.vexnum; ++i) {
        indegree[i] = 0;
    }
    //获取每个顶点的入度
    for (int i = 0; i < G.vexnum; ++i) {
        for (int j = 0; j < G.vexnum; ++j) {
            if (Adjacent(G, i, j)) {
                indegree[j]++;
            }
        }
    }
    InitStack(S);
    for (int i = 0; i < G.vexnum; ++i) {
        if (indegree[i] == 0) {//将所有入度为0的顶点进栈
            Push(S, i);
        }
    }
    int v;
    int count = 0;//记录当前输出的顶点
    while (!StackEmpty(S)) {
        Pop(S, v);
        print[count++] = v;
        //检查入度为当前顶点的顶点
        for (int i = 0; i < G.vexnum; ++i) {
            if (Adjacent(G, v, i)) {
                //检查入度为当前顶点的顶点
                if (--indegree[i] == 0) {
                    Push(S, i);
                }
            }
        }
    }
    if (count < G.vexnum) {
        return false;//拓扑排序失败,有向图中存在回路
    } else {
        return true;
    }

}

int outdegree[MaxVertexNum];//记录当前结点的出度

//逆拓扑排序实现
bool ReverseTopologicalSort(ALGraph G) {
    //初始化
    for (int i = 0; i < G.vexnum; ++i) {
        outdegree[i] = 0;
    }
    //获取每个顶点的出度
    for (int i = 0; i < G.vexnum; ++i) {
        for (int j = 0; j < G.vexnum; ++j) {
            if (Adjacent(G, i, j)) {
                outdegree[i]++;
            }
        }
    }
    InitStack(S);
    for (int i = 0; i < G.vexnum; ++i) {
        if (outdegree[i] == 0) {//将所有出度为0的顶点进栈
            Push(S, i);
        }
    }
    int v;
    int count = 0;//记录当前输出的顶点
    while (!StackEmpty(S)) {
        Pop(S, v);
        print[count++] = v;
        //检查出度为当前顶点的顶点
        for (int i = 0; i < G.vexnum; ++i) {
            if (Adjacent(G, i, v)) {
                if(--outdegree[i]==0) {
                    Push(S,i);
                }
            }
        }
    }
    if (count < G.vexnum) {
        return false;//逆拓扑排序失败,有向图中存在回路
    } else {
        return true;
    }
}


//深度优先遍历
void DFSTopo(ALGraph G, int v) {
    visited[v] = true;
//    visit(G, v);
    for (int w = FirstNeighbor(G, v); w >= 0; w = NextNeighbor(G, v, w)) {
        if (!visited[w])
            DFSTopo(G, w);
    }
    printf("%d ",v);
}

void DFSTraverseTopo(ALGraph G) {
    printf("使用深度优先遍历算法得到逆拓扑序列: \n");
    for (int i = 0; i < G.vexnum; ++i) {
        visited[i] = false;
    }
    for (int i = 0; i < G.vexnum; ++i) {
        if (!visited[i]) { //非联通图无法一次访问完成
            DFSTopo(G, i);
        }
    }
    printf("\n");
}

int main() {
    setbuf(stdout, NULL);

    //测试 图的基本操作
    ALGraph G;
    int type = 0;
    InitALGraph(G, type);
//    InsertVertex(G, 'G');
    InsertVertex(G, 'B');
    InsertVertex(G, 'C');
    InsertVertex(G, 'D');
    InsertVertex(G, 'E');
    InsertVertex(G, 'F');

    AddEdge(G, 0, 1);//A-B
    AddEdge(G, 0, 2);//A-C
    AddEdge(G, 0, 3);//A-D

//    AddEdge(G, 1, 4);//B-E
    AddEdge(G, 1, 5);//B-F

    AddEdge(G, 2, 4);//C-E

    AddEdge(G, 3, 5);//D-F

    BFSTraverse(G);
    DFSTraverse(G);
    int x, y;
    x = 0, y = 1;
    for (int i = 0; i < G.vexnum; ++i) {
        x = i;
        if (type == 0) {
            printf("顶点%c存在的边: ", G.vertices[x].data.value);
        } else {
            printf("顶点%c存在的弧: ", G.vertices[x].data.value);
        }
        for (int j = 0; j < 6; ++j) {
            y = j;
            if (Adjacent(G, x, y)) {
                printf("%c%c ", G.vertices[x].data.value, G.vertices[y].data.value);
            }
        }
        printf("\n");
    }

    for (int i = 0; i < G.vexnum; ++i) {
        x = i;
        y = FirstNeighbor(G, x);
        if (y != -1) {
            printf("顶点%c的邻接点有: %c ", G.vertices[x].data.value, G.vertices[y].data.value);
            y = (NextNeighbor(G, x, y));
            while (y != -1) {
                printf("%c ", G.vertices[y].data.value);
                y = (NextNeighbor(G, x, y));
            }
            printf("\n");
        } else {
            printf("顶点%c不存在或没有邻接点\n", G.vertices[x]);
        }
    }

    for (int i = 0; i < 6; ++i) {
        Neighbors(G, i);
    }

    x = 0, y = 1;
    int v = 12;
    Set_edge_value(G, x, y, v);

    for (int i = 0; i < G.vexnum; ++i) {
        x = i;
        printf("与顶点%c相邻的边的权值: ", G.vertices[x].data.value);
        for (int j = 0; j < 6; ++j) {
            y = j;
            int w = Get_edge_value(G, x, y);
            if (w != -1) {
                printf("%c%c: %d  ", G.vertices[x].data.value, G.vertices[y].data.value, w);
            }
        }
        printf("\n");
    }


//    RemoveEdge(G, 0, 3);//删除边AD
//    printf("删除边/弧 AD\n");
//    printf("删除边/弧 AD\n");
//    RemoveEdge(G, 0, 3);//删除边AD
//    printf("删除边/弧 AB\n");
//    RemoveEdge(G, 0, 1);//删除边AB
//
//    printf("删除边/弧 AC\n");
//    RemoveEdge(G, 0, 2);//删除边AC


//    DeleteVertex(G,1);

    //测试 广度优先搜索算法 求无权图单源点最短路径

    InitStack(S);
    for (int i = 0; i < G.vexnum; ++i) {
        BFS_MIN_DISTANCE(G, i);
        printf("顶点%c到其他顶点  最短路径: \n", G.vertices[i]);
        for (int j = 0; j < G.vexnum; ++j) {
            int k = path[j];
            printf("%c到%c: %d  ", G.vertices[i].data.value, G.vertices[j].data.value, d[j]);

            while (k != -1) {
                Push(S, G.vertices[k].data.value);
                k = path[k];
            }
            while (!StackEmpty(S)) {
                int e;
                Pop(S, e);
                printf("%c->", e);
            }
            printf("%c\n", G.vertices[j].data.value);
        }
        printf("\n");

    }


    //测试 求最小代价生成树  Prim 算法 和 Kruskal 算法
    InitALGraph(G, type);

//    InsertVertex(G,'0');

    G.vertices[0].data.value = 0;
    InsertVertex(G, 1);
    InsertVertex(G, 2);
    InsertVertex(G, 3);
    InsertVertex(G, 4);
    InsertVertex(G, 5);
//    InsertVertex(G,6);

    AddEdge(G, 0, 1);
    Set_edge_value(G, 0, 1, 6);
    AddEdge(G, 0, 2);
    Set_edge_value(G, 0, 2, 5);
    AddEdge(G, 0, 3);
    Set_edge_value(G, 0, 3, 1);

    AddEdge(G, 1, 3);
    Set_edge_value(G, 1, 3, 5);
    AddEdge(G, 1, 4);
    Set_edge_value(G, 1, 4, 3);

    AddEdge(G, 2, 3);
    Set_edge_value(G, 2, 3, 4);
    AddEdge(G, 2, 5);
    Set_edge_value(G, 2, 5, 2);

    AddEdge(G, 3, 4);
    Set_edge_value(G, 3, 4, 6);
    AddEdge(G, 3, 5);
    Set_edge_value(G, 3, 5, 4);

    AddEdge(G, 4, 5);
    Set_edge_value(G, 4, 5, 6);

    for (int i = 0; i < 6; ++i) {
        x = i;
        printf("与顶点%d相邻的边的权值: ", G.vertices[x].data.value);
        for (int j = 0; j < 6; ++j) {
            y = j;
            int w = Get_edge_value(G, x, y);
            if (w != -1) {
                printf("%d%d: %d  ", G.vertices[x].data.value, G.vertices[y].data.value, w);
            }
        }
        printf("\n");
    }

    Prim(G);

    Kruskal(G);


    //测试 Dijkstra算法
    type = 1;
    InitALGraph(G, type);
    G.vertices[0].data.value = 0;
    InsertVertex(G, 1);
    InsertVertex(G, 2);
    InsertVertex(G, 3);
    InsertVertex(G, 4);
    AddEdge(G, 0, 1);
    Set_edge_value(G, 0, 1, 10);
    AddEdge(G, 0, 4);
    Set_edge_value(G, 0, 4, 5);

    AddEdge(G, 1, 2);
    Set_edge_value(G, 1, 2, 1);
    AddEdge(G, 1, 4);
    Set_edge_value(G, 1, 4, 2);

    AddEdge(G, 2, 3);
    Set_edge_value(G, 2, 3, 4);

    AddEdge(G, 3, 0);
    Set_edge_value(G, 3, 0, 7);
    AddEdge(G, 3, 2);
    Set_edge_value(G, 3, 2, 6);


    AddEdge(G, 4, 1);
    Set_edge_value(G, 4, 1, 3);
    AddEdge(G, 4, 2);
    Set_edge_value(G, 4, 2, 9);
    AddEdge(G, 4, 3);
    Set_edge_value(G, 4, 3, 2);


    for (int i = 0; i < G.vexnum; ++i) {
        Dijkstra(G, i);
        printf("顶点%d到其他顶点  最短路径: \n", G.vertices[i].data.value);
        for (int j = 0; j < G.vexnum; ++j) {
            int k = path[j];
            printf("%d到%d: %d  ", G.vertices[i].data.value, G.vertices[j].data.value, dist[j]);

            while (k != -1) {
                Push(S, G.vertices[k].data.value);
                k = path[k];
            }
            while (!StackEmpty(S)) {
                int e;
                Pop(S, e);
                printf("%d->", e);
            }
            printf("%d\n", G.vertices[j].data.value);
        }
        printf("\n");
    }

    //测试 Floyd 算法求各顶点之间的最短路径
//
//    //测试 三个顶点
//    InitALGraph(G, type);
//    G.vertices[0].data.value = 0;
//
//    InsertVertex(G, 1);
//    InsertVertex(G, 2);
//
//    AddEdge(G,0,1);
//    Set_edge_value(G,0,1,6);
//
//    AddEdge(G,1,0);
//    Set_edge_value(G,1,0,10);
//
//    AddEdge(G,0,2);
//    Set_edge_value(G,0,2,13);
//    AddEdge(G,2,0);
//    Set_edge_value(G,2,0,5);
//
//    AddEdge(G,1,2);
//    Set_edge_value(G,1,2,4);
//
//    Floyd(G);

    //测试 五个顶点
    type = 1;
    InitALGraph(G, type);
    G.vertices[0].data.value = 0;

    InsertVertex(G, 1);
    InsertVertex(G, 2);
    InsertVertex(G, 3);
    InsertVertex(G, 4);

    AddEdge(G, 0, 2);
    Set_edge_value(G, 0, 2, 1);
    AddEdge(G, 0, 4);
    Set_edge_value(G, 0, 4, 10);

    AddEdge(G, 1, 3);
    Set_edge_value(G, 1, 3, 1);
    AddEdge(G, 1, 4);
    Set_edge_value(G, 1, 4, 5);

    AddEdge(G, 2, 1);
    Set_edge_value(G, 2, 1, 1);
    AddEdge(G, 2, 4);
    Set_edge_value(G, 2, 4, 7);

    AddEdge(G, 3, 4);
    Set_edge_value(G, 3, 4, 1);

    Floyd(G);


    InitALGraph(G, type);
    G.vertices[0].data.value = 0;

    InsertVertex(G, 1);
    InsertVertex(G, 2);
    InsertVertex(G, 3);
    InsertVertex(G, 4);
    AddEdge(G, 0, 1);
    AddEdge(G, 1, 3);

    AddEdge(G, 3, 4);
    AddEdge(G, 2, 3);
    AddEdge(G, 2, 4);
//    AddEdge(G, 4, 2);
    if (TopologicalSort(G)) {
        printf("拓扑排序成功,拓扑序列为:\n");
        for (int i = 0; i < G.vexnum; ++i) {
            printf("%d ", print[i]);
        }
        printf("\n");
    } else {
        printf("拓扑排序失败\n");
    }

    if (ReverseTopologicalSort(G)) {
        printf("逆拓扑排序成功,逆拓扑序列为:\n");
        for (int i = 0; i < G.vexnum; ++i) {
            printf("%d ", print[i]);
        }
        printf("\n");
    } else {
        printf("逆拓扑排序失败\n");
    }

    DFSTraverseTopo(G);
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值