图的一般算法(伪代码)

##1。广度优先搜索(BFS)

bool visited[Max_vertex_num];
void BFSTraverse(Graph G) {
    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);            // 访问
    }
}

void BFS(Graph G, int v) {
    visit(v);
    visited[v] = true;
    while(!isEmpty(Q)) {
        DeQueue(Q, v);
        for (w = FirstNeighbor(G, v); w >= 0; w = NextNeighbor(G, v, w))    // 检查所有邻接点
        {
            if(!visited[w]) {
                visit(v);
                visit[w] = true;;
                EnQueue(Q, w);   // 顶点w入队列
            } // if
        }// for
    }// while
}// BFS

##2。BFS求解单源最短路径问题

const int Int_max = 0x7fffffff;
void BFS_mindist(Graph G, int u) {
    for (int i = 0; i < G.vexnum; ++i)
        d[i] = Int_max;                 // 初始化初始路径长度
    visited[u] = true;
    d[u] = 0;
    EnQueue(Q, u);
    while(!isEmpty(Q)) {
        DeQueue(Q, u);                  // 队头出列
        for (w = FirstNeighbor(G, u); w >= 0; w = NextNeighbor(G, u, w))
        {
            if(!visited[w]) {           // 访问尚未访问的邻接顶点
                visited[w] = true;
                d[w] = d[u] + 1;        // 路径长度+1
                EnQueue(Q, w);          // 顶点入队
            } // if
        }// for
    }// while
}

##3。深度优先搜索(DFS)

// 递归形式
bool visited[Max_vertex_num];
void DFSTraverse(Graph G) {
    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);
}
void DFS(Graph, int v) {
    visit(v);
    visited[v] = true;
    for (w = FirstNeighbor(G, w); w >= 0; w = NextNeighbor(G, v, w))
        if(!visited[w])     // 访问尚未访问的顶点
            DFS(G, w);
}


/*****************************************************************/


// 非递归形式
bool visited[Max_vertex_num];
void DFS_non_rc(Graph G, int v) {
    int w;
    InitStack(S);
    for (int i = 0; i < G.vexnum; ++i)
        visited[i] = false;
    Push(S, v);
    visited[v] = true;

    while(!IsEmpty(S)) {
        k = Pop(S);
        visit(k);
        for(w = FirstNeighbor(G, k); w >= 9; w = NextNeighbor(G, k, w)) {
            if(!visited[w]) {
                Push(S, w);
                visited[w] = true;
            }// if
        }// for
    }// while
}

##4。拓扑排序

// indegree[i]为第i个顶点的入度
bool TopologicalSort(Graph G) {
    // 如果G存在拓扑序列,返回true;否则返回false,即G中存在环
    InitStack(S);
    for (int i = 0; i < G.vexnum; ++i)  // 寻找入度为0的点,即无前驱的点
    {
        if(indegree[i] == 0)
            Push(S, i);
    }// for
    int count = 0;                      // 记录当前以输出的点的个数
    while(!IsEmpty(S)) {
        Pop(S, i);
        print[count++] = i;             // 记录输出顶点
        for (p = G.vertices[i].firstarc; p; p = p->nextarc)
        {// 将此顶点所指向的顶点的入度减1,减完之后入度为0的点入栈,此步骤即删除顶点和其出边的操作
            v = p->adjvex;
            if(!(--indegree[v]))
                Push(S, v);
        }// for
    }// while
    if(count < G.vexnum)    return false;   // 若输出点的个数小于图顶点个数,说明图中存在环
    else    return true;
}

##5。最短路径(Dijkstra)

5.1 邻接矩阵版 O(V^2)

// 邻接矩阵版
const int maxv = 1000;
const int inf = 100000000;

int n, G[maxv][maxv];
int d[maxv];
bool vis[maxv] = {false};

void Dijkstra(int s) {
    fill(d, d + maxv, inf);             // fill函数将整个d数组赋值为inf
    d[s] = 0;                           // 起点到达自身的距离为0
    for (int i = 0; i < n; ++i)
    {
        int u = -1, min = inf;          // u是d[u]最小,min存放该最小的d[u]
        // 找到未访问顶点中d[]最小的
        for (int j = 0; j < n; ++j)
        {
            if(!vis[j] && d[j] < min) {
                u = j;
                min = d[j];
            }
        }// for
        // 若找不到小于inf的d[u],则说明剩下的顶点和起点s不连通
        if(u == -1) return ;

        vis[u] = true;                  // 标记u已访问
        for (int v = 0; v < n; ++v)
        {
            // 如果v未访问 且 u能达到v 且 以u为中介可以使d[v]更优
            if(!vis[v] && G[u][v] != inf && d[u] + G[u][v] < d[v]) {
                d[v] = d[u] + G[u][v];  // 优化d[v]
            }
        }// for
    }// for
}// Dijkstra

5.2 邻接表版 O(V^2)

// 邻接表版
const int maxv = 1000;
const int inf = 100000000;
struct Node
{
    int v, dis;         // v为顶点, dis表示边权
};

vector adj[maxv]; // 邻接表
int n;                  // 标记顶点个数
int d[maxv];            // 记录到达各点的最短路径长度
bool vis[maxn] = {false};

void Dijkstra(int s) {
    fill(d, d + maxv, inf);
    d[s] = 0;
    for (int i = 0; i < n; ++i)
    {
        int u = -1, min = inf;
        for (int j = 0; j < n; ++j)
        {
            if(!vis[j] && d[j] < min) {
                u = j;
                min = d[j];
            }
        }// for

        // 若找不到小于inf的d[u],则说明剩下的顶点和起点s不连通
        if(u == -1) return ;

        vis[u] = true;
        // 只有此处与邻接矩阵版不同
        for (int j = 0; j < adj[u].size(); ++j)
        {
            int v = adj[u][j].v;
            // 如果v未访问 且 u能达到v 且 以u为中介可以使d[v]更优
            if(!vis[v] && d[u] + adj[u][j].dis < d[v]) {
                d[v] = d[u] + adj[u][j].dis;
            }
        }// for
    }// for
}// Dijkstra

5.3 优先队列改进版
已测试

// 改进版
#include 
#include 
using namespace std;

const int inf = 100000000;
const int maxn = 510;

int n;
int d[maxn], G[maxn][maxn];
bool vis[maxn] = { false };
typedef pair P;   // first是最短距离,second是顶点编号, pair默认以first排序
priority_queue, greater

> pq; void Dijkstra(int s) { P p; int u, v; fill(d, d + maxn, inf); d[s] = 0; vis[s] = true; while (!pq.empty()) pq.pop(); // 清空 pq.push(P(0, s)); while (!pq.empty()) { p = pq.top(); pq.pop(); int u = p.second; if (p.first > d[u]) continue; vis[u] = true; for (int v = 0; v < n; v++) { if (vis[v] == false && G[u][v] != inf) { if (d[v] > d[u] + G[u][v]) { d[v] = d[u] + G[u][v]; pq.push(P(d[v], v)); } } } } }


6。Prim最小生成树
和Dijkstra很相似,由Dijkstra代码修改而来
还没有测试


#include 
#include 
using namespace std;

const int inf = 100000000;
const int maxn = 510;

int n;
int d[maxn], G[maxn][maxn]; // d[]的定义与 Dijkstra不同,Prim的d[]表示的是顶点与集合S的最短距离
bool vis[maxn] = { false };

typedef pair P;   // first是最短距离,second是顶点编号, pair默认以first排序
priority_queue, greater

> pq; vector pre[v], path, temp; int Prim(int s) { P p; int cost = 0; // 记录最小生成树的边权之和 d[s] = 0; vis[0] = true; while(!pq.empty()) pq.pop(); pq.push(P(0, s)); while(!pq.empty()) { p = pq.top(); pq.pop(); int u = p.second; if(p.first > d[u]) continue; vis[u] = true; cost += d[u]; for (int v = 0; v < n; ++v) { // 以u为中介点可以使v距离集合S更近 if(!vis[u] && G[u][v] != inf && G[u][v] < d[v]) { d[v] = G[u][v]; pq.push(P(d[v], v)); pre[v].push_back(u); // 记录最小生成树 } } } return cost; // 返回最小生成树的点权之和 }// Prim

你可能感兴趣的:(图)