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。