1.图的数字特性:
1.1 握手定理: 图中的节点度数等于边数的2 倍。
公式表达为
2.欧拉公式:
记忆公式为: 顶+ 面= 2+边
设G是任意的联通图,则有
n : G 中的顶点数目
m :是边数目
r: 面的数目
即: 联通图中顶点数-边数+面的数目=2;
2 图操作:
//图的遍历很重要:仅仅给出非递归实现,图的很多操作 CRUD 都是基于R的,只不过是条件中操作
//写代码是从内向外写的。
//这里数据结构选用的是邻接表
1.1 深度遍历(DFS)
思想:
/* Adjlist g ,邻接表
vertype u 遍历的开始节点
vertype v 遍历的结束节点
*/
void aldfs(Adjlist g,vertype u,vertype v){
int top=0,s[];
//5.初始化栈了:
int top=0,s[]';
s[++top]=u;
visited[u]=1;
//栈操作
while(top>0 || p)
{
//4.temp 从哪儿来,从栈中获得 因为 图是地址结构,需要保存地址,因为沿着图的单向访问到地点就不能回来了所以要保存
temp=s[top];
//3.P从哪儿来->p 在邻接表的首地址上
p=g[temp].firstarc; //
//7.访问下一个邻接地址:现在到了链表的操作了
while(p!=null && visited[p->adjvex]==1)
p=p->next;
//8.链表的操作
if(p==null) //销毁栈
top--;
else
{
//2.i 是从取自邻接点的
i=p->adjvex;
//1.条件输出栈中的内容
if(i==v) //起点终点相同则是遍历完全
for(k=1;k<=top;k++)
{printf(“%3d”,s[k]);
printf("%3d\n",v);
}
else //10.继续压入栈
{
visited[i]=1;
s[++top]=i;
}
}
}
1.2 宽度遍历(BFS)
//这时要用的队列来保存对应的地址,为什么??你想想:把这些图看成横向的多链表结构:满足先进先出的特性:
void bfs(graph g, vertype v0)
{
visit(v0);
visited[v0]=1;
//1.初始化队列
initqueue(Q);
enqueue(Q,v0); //V0 入列
while(!empty(Q))
{
v=delqueue(Q);
w=firstadj(g,v); //求顶点的V的第一个临界点
while(W!=0)
{
if(visited[w]==0) //邻接点没访问
{
visit(w);
visited[w]=1;
enqueue(Q,w);
w=nextadj(g,v,w);
}
}
void Traver()
{
for (i=1;i<n;i++)
for(i=1;i<=n;i++)
if(visited[i] ==0)
bfs(i);
}
3.图转化
1.讨论如下:
当图向树转化时有
1.最小生成树
2.单源最短路径:
3.对顶点的路径问题:
//限于时间写出伪代码:
1.最小生成树
限于时间写出伪代码以后再实现:
如是权值,则“使用破圈方法”
思想: 排序删边测联通,若是联通继续删,指导n-1 条边结束:
typdedef stuct
{
int i;
int j;
int w;//权值
} node ;
node edge[];
scanf(“%d%d”,&e,&n);//输入变数和顶点数目
for(i=0;i<=e;i++)
scanf(“%d%d%d”,edge[i].i,edge[i].j,edge[i].w);
//插入排序 :
for(i=2;i<=e;i++)
{
edge[0]=edge[i]; j=i-1;
while(edge[j].w<edge[0].w)
edge[j+1]=edge[j--]; //操作后每次地址移动。
edge[j+1]=edge[0];
}
k=1,eg=e;
while(eg>=n) //eg-n>=1 剩下n-1 条边,C语言中非0 为假, 大于1 为真
{
if(connect(K)) // 注意这里的Connect 是图是否联通的方法
{
// 删除第 K条边是联通的继续删除
edge[k].w=0;eg—; //边数减少1
}
k++;
}
2.单源最短路径:
Dijikstr思想是:
列表交点求最值,最值点组合该点联通点 再最值
//设数据结构是邻接表实现
//定义邻接表的矩阵
struct node
{
int adjvex, //邻接节点
int weigth ; //权值
int strct * next
} p;
void shorttest_Dijkstra(){
//1.初始化
int dist[],s[]; //dist最短路径, s数组存放顶点是否找到最短路径
for(i=1;i<=n;i++)
{
dist[i]=MAX;
s[i]=0; //0 表示未找到
}
//2.
for(int j=1;j<=n;j++){
//转换节点状态时的 地址赋值
for(s[j]==0 && dist[j<max])
{u=j;max=dist[j]}
s[u]=1; //标识改点被选中
p=g[u].firstarc; //链表首地址
while(p) //遍历链表
j=p->adjvex;
if(dist[j]=dist[u]+p->weight){ //dist u,v 是边
dist[j]=dist[u]+p->weight //3. 路径权值再符合 p=p->next;
}
}
}
3.对顶点的路径问题:
FLOAY算法:
思想: 不解释:
三重循环: i ,k,,j 型
void Shortpath(AdjMatrix g)
{
//初始化
AdjMatrix length; // 邻接矩阵的结构体:
for(i=0;i<=n;i++)
for(j=1;j<=n;j++)
length[i][j]=g[i][j]; //初始化
for(k=1;k<=n;k++)
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(length[i][k]+length[k][j]<length[i][j]) //i ,k,i 型
ength[i][j]=length[i][k]+length[k][j] ;
}