图论与贪心算法

1. 图的顺序存储

//邻接矩阵
#define MaxVerterNum 100
typedef char VerterType;
typedef int EdgeType;
typedef struct
{
    VerterType vexs[MaxVerterNum];  //存储顶点的一维数组
    EdeType edges[MaxVerterNum][MaxVerterNum];
    int n, e;  //图当前的顶点数和边数
}MGragh;

void CreateMGragh(MGragh *G)  //时间复杂度O(n^2)
{
    int i, j, k, w;
    scanf ("%d%d, &G->n, &G->e");  //读入顶点数和边数
    for (i = 0; i < G->n; i++)  //读入顶点信息,建立顶点表
        G->vexs[i] = getchar();
    for (i = 0; i < G->n; i++)  //邻接矩阵初始化
        for (j = 0; i < G->n; j++)
            G->edges[i][j] = 0;
    for (k = 0; k < G->e; k++)  //读入e条边,建立邻接矩阵
    {
        scanf ("%d%d", &i, &j);  //读入边<vi,vj>上的权w
        G->edges[i][j] = 1;
        G->edges[j][i] = 1;
    }
}

2. 图的链式存储

//邻接表
typedef struct node  //边表结点
{
    int adjtex;  //邻接点域
    struct node *next;  //链域
}EdgeNode;  //若也表示边上的权,增加一个数据域

typedef struct vnode  //顶点表结点
{
    VertexType vertex;  //顶点域
    EdgeNode *firstedeg;  //边表头指针
}VertexNode;

typedef VertexNode AdjList[MaxNodeNum];

typedef struct
{
    AdjList adjlist;  //邻接表
    int n, e;  //顶点数和边数
}ALGraph;  //对于简单应用无需定义此类型,直接使用AdjList类型

void CreateALGraph(ALGraph *G)
{
    int i, j, k;
    EdgeNode *s;
    scanf("%d%d", &G->n, &G->e);  //读入顶点数和边数
    for (i = 0; i < G->n; i++)  //建立顶点表
    {
        G->adjlist[i].vertex = getchar();  //读入顶点信息
        G->adjlist[i].firstedge = NULL;  //边表置空
    }
    for (k = 0; k < G->e; k++)  //建立边表
    {
        scanf("%d%d", &i, &j);  //读入边(vi, vj)的顶点对序
        s = (EdgeNode *)malloc(sizeof(EdgeNOde));  //生成边表结点
        s->adjvex = j;  //邻结点的序号为j
        s->next = G->adjlist[i].firstedge;  //前插入
        G->adjlist[i].firstedge = s;  //将新结点*是插入vi头部
        s = (EdgeNode *)malloc(sizeof(EdgeNode));
        s->adjvex = i;  //邻接序号为i
        s->next = G->adjlist[j].firstedge;
        G->adjlist[j].firstedge;  //将新结点*s插入vj头部
    }
}

3. 深度优先遍历的递归算法

void dfs(int v0)  //从顶点v0开始
{
    visted[v0] = 1;  //访问标志置为1,表示已被访问
    w = firstadj(g, v0);  //w是v0的第一个邻接点
    while (w != 0)
    {
        if (visted[w] == 0) dfs(w);  //顶点未被访问,则递归地进行深度遍历
        w = nextadj(g, v0, w);  //顶点已访问,则取顶点v0在w后面的下一个邻接点
    }
}

4. 广度优先遍历的递归算法

void bfs(Graph g, int v0)
{  //从v0出发广度优先遍历图g
    visited[v0] = 1;
    Enqueue(Q, v0);
    while (!Empty(Q))
    {
        v = Dlqueue(Q);  //取队头元素
        w = Firstadj(g,v);  //求v的第一个邻接点
        while (w != 0)
        {
            if (visited[w] == 0)
            {
                visited[w] = 1;
                Enqueue(Q, w);
            }
            w = Nextadj(g, v, w);  //求下一个邻接点
        }
    }
}

5. 贪心算法

//活动安排问题的贪心算法
public static int GreedySelector(int []s, int []f, boolean a[])
{  /*各活动的起始时间和结束时间存储于数组s和f中且按结束时间的非减序排列f1<=f2<=f3..<=fn */
    int n =s.length - 1;
    a[1] = true;  /*用集合a来存储所选择的活动,活动i在集合中当且仅当a[i]=true,j记录最近一次加入a的活动 */
    int j = 1;
    int count = 1;
    for (int i = 2; i <= n; i++)
    {
        if (s[i] >= f[j])
        {
            a[i] = ture;
            j = i;
            count++;
        }
        else a[i] = false;
    }
    return count;
}

6. 最小生成树

  • 切分性质:令S为顶点集合的任一子集,并令e为一个终点在S中且具有最小权重的边。最小生成树T’必包含e。
  • 回路/圈性质:令C是图G中任一回路,并令f是回路C中具有最大权重的边。最小生成树T’必定不包含f。
    原文作者:贪心算法
    原文地址: https://blog.csdn.net/JasonCaine/article/details/82596054
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞