邻接表的深度遍历算法c语言,图的遍历和生成树求解实现(邻接矩阵、邻接表 —图的深度广度遍历算法的实现和最小生成树PRIM和KR...

http://blog.chinaunix.net/uid-20357359-id-1963174.html

#include

#include

using namespace std;

#define int_max 10000

#define inf 9999

#define max 20

//…………………………………………邻接矩阵定义……………………

typedef struct ArcCell

{

int adj;

char *info;

}ArcCell, AdjMatrix[20][20];

typedef struct

{

char vexs[20];

AdjMatrix arcs;

int vexnum, arcnum;

}MGraph_L;

//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

int localvex(MGraph_L G, char v)//返回V的位置

{

int i = 0;

while (G.vexs[i] != v)

{

++i;

}

return i;

}

int creatMGraph_L(MGraph_L &G)//创建图用邻接矩阵表示

{

char v1, v2;

int i, j, w;

cout << "…………创建无向图…………" << endl <<

"请输入图G顶点和弧的个数:(4 6)不包括“()”" << endl;

cin >> G.vexnum >> G.arcnum;

for (i = 0; i != G.vexnum; ++i)

{

cout << "输入顶点" << i << endl;

cin >> G.vexs[i];

}

for (i = 0; i != G.vexnum; ++i)

for (j = 0; j != G.vexnum; ++j)

{

G.arcs[i][j].adj = int_max;

G.arcs[i][j].info = NULL;

}

for (int k = 0; k != G.arcnum; ++k)

{

cout << "输入一条边依附的顶点和权:(a b 3)不包括“()”" <<

endl;

cin >> v1 >> v2 >> w;//输入一条边依附的两点及权值

i = localvex(G, v1);//确定顶点V1和V2在图中的位置

j = localvex(G, v2);

G.arcs[i][j].adj = w;

G.arcs[j][i].adj = w;

}

cout << "图G邻接矩阵创建成功!" << endl;

return G.vexnum;

}

void ljjzprint(MGraph_L G)

{

int i, j;

for (i = 0; i != G.vexnum; ++i)

{

for (j = 0; j != G.vexnum; ++j)

cout << G.arcs[i][j].adj << " ";

cout << endl;

}

}

int visited[max];//访问标记

int we;

typedef struct arcnode//弧结点

{

int adjvex;//该弧指向的顶点的位置

struct arcnode *nextarc;//弧尾相同的下一条弧

char *info;//该弧信息

}arcnode;

typedef struct vnode//邻接链表顶点头接点

{

char data;//结点信息

arcnode *firstarc;//指向第一条依附该结点的弧的指针

}vnode, adjlist;

typedef struct//图的定义

{

adjlist vertices[max];

int vexnum, arcnum;

int kind;

}algraph;

//…………………………………………队列定义……………………

typedef struct qnode

{

int data;

struct qnode *next;

}qnode, *queueptr;

typedef struct

{

queueptr front;

queueptr rear;

}linkqueue;

//………………………………………………………………………

typedef struct acr

{

int pre;//弧的一结点

int bak;//弧另一结点

int weight;//弧的权

}edg;

int creatadj(algraph &gra, MGraph_L G)//用邻接表存储图

{

int i = 0, j = 0;

arcnode *arc, *tem, *p;

for (i = 0; i != G.vexnum; ++i)

{

gra.vertices[i].data = G.vexs[i];

gra.vertices[i].firstarc = NULL;

}

for (i = 0; i != G.vexnum; ++i)

{

for (j = 0; j != G.vexnum; ++j)

{

if (gra.vertices[i].firstarc == NULL)

{

if (G.arcs[i][j].adj != int_max&&j != G.vexnum)

{

arc = (arcnode *)malloc(sizeof(arcnode));

arc->adjvex = j;

gra.vertices[i].firstarc = arc;

arc->nextarc = NULL;

p = arc;

++j;

while (G.arcs[i][j].adj != int_max&&j !=

G.vexnum)

{

tem = (arcnode *)malloc(sizeof(arcnode));

tem->adjvex = j;

gra.vertices[i].firstarc = tem;

tem->nextarc = arc;

arc = tem;

++j;

}

--j;

}

}

else

{

if (G.arcs[i][j].adj != int_max&&j != G.vexnum)

{

arc = (arcnode *)malloc(sizeof(arcnode));

arc->adjvex = j;

p->nextarc = arc;

arc->nextarc = NULL;

p = arc;

}

}

}

}

gra.vexnum = G.vexnum;

gra.arcnum = G.arcnum;

cout << "图G邻接表创建成功!" << endl;

return 1;

}

void adjprint(algraph gra)

{

int i;

for (i = 0; i != gra.vexnum; ++i)

{

arcnode *p;

cout << i << " ";

p = gra.vertices[i].firstarc;

while (p != NULL)

{

cout << p->adjvex;

p = p->nextarc;

}

cout << endl;

}

}

int firstadjvex(algraph gra, vnode v)//返回依附顶点V的第一个点

//即以V为尾的第一个结点

{

if (v.firstarc != NULL)

return v.firstarc->adjvex;

}

int nextadjvex(algraph gra, vnode v, int

w)//返回依附顶点V的相对于W的下一个顶点

{

arcnode *p;

p = v.firstarc;

while (p != NULL&&p->adjvex != w)

{

p = p->nextarc;

}

if (p->adjvex == w&&p->nextarc != NULL)

{

p = p->nextarc;

return p->adjvex;

}

if (p->adjvex == w&&p->nextarc == NULL)

return -10;

}

int initqueue(linkqueue &q)//初始化队列

{

q.rear = (queueptr)malloc(sizeof(qnode));

q.front = q.rear;

if (!q.front)

return 0;

q.front->next = NULL;

return 1;

}

int enqueue(linkqueue &q, int e)//入队

{

queueptr p;

p = (queueptr)malloc(sizeof(qnode));

if (!p)

return 0;

p->data = e;

p->next = NULL;

q.rear->next = p;

q.rear = p;

return 1;

}

int dequeue(linkqueue &q, int &e)//出队

{

queueptr p;

if (q.front == q.rear)

return 0;

p = q.front->next;

e = p->data;

q.front->next = p->next;

if (q.rear == p)

q.rear = q.front;

free(p);

return 1;

}

int queueempty(linkqueue q)//判断队为空

{

if (q.front == q.rear)

return 1;

return 0;

}

void bfstra(algraph gra)//广度优先遍历

{

int i, e;

linkqueue q;

for (i = 0; i != gra.vexnum; ++i)

visited[i] = 0;

initqueue(q);

for (i = 0; i != gra.vexnum; ++i)

if (!visited[i])

{

visited[i] = 1;

cout << gra.vertices[i].data;

enqueue(q, i);

while (!queueempty(q))

{

dequeue(q, e);

// cout<

for (we = firstadjvex(gra, gra.vertices[e]); we >= 0; we =

nextadjvex(gra, gra.vertices[e], we))

{

if (!visited[we])

{

visited[we] = 1;

cout << gra.vertices[we].data;

enqueue(q, we);

}

}

}

}

}

int dfs(algraph gra, int i);//声明DFS

int dfstra(algraph gra)

{

int i, j;

for (i = 0; i != gra.vexnum; ++i)

{

visited[i] = 0;

}

for (j = 0; j != gra.vexnum; ++j)

{

if (visited[j] == 0)

dfs(gra, j);

}

return 0;

}

int dfs(algraph gra, int i)

{

visited[i] = 1;

int we1;

// cout<

cout << gra.vertices[i].data;

// cout<

for (we = firstadjvex(gra, gra.vertices[i]); we >= 0; we =

nextadjvex(gra, gra.vertices[i], we))

{

// cout<

we1 = we;

//

cout<

if (visited[we] == 0)

//  cout<<

dfs(gra, we);//<

// cout<

we = we1;

// cout<

}

return 12;

}

int bfstra_fen(algraph gra)//求连通分量

{

int i, j;

for (i = 0; i != gra.vexnum; ++i)

{

visited[i] = 0;

}

for (j = 0; j != gra.vexnum; ++j)

{

if (visited[j] == 0)

{

dfs(gra, j);

cout << endl;

}

}

return 0;

}

typedef struct

{

int adjvex;

int lowcost;

}closedge;

int prim(int g[][max], int n) //最小生成树PRIM算法

{

int lowcost[max], prevex[max];

//LOWCOST[]存储当前集合U分别到剩余结点的最短路径

//prevex[]存储最短路径在U中的结点

int i, j, k, min;

for (i = 2; i <= n; i++)

//n个顶点,n-1条边

{

lowcost[i] = g[1][i]; //初始化

prevex[i] = 1; //顶点未加入到最小生成树中

}

lowcost[1] = 0; //标志顶点1加入U集合

for (i = 2; i <= n; i++)

//形成n-1条边的生成树

{

min = inf;

k = 0;

for (j = 2; j <= n; j++)

//寻找满足边的一个顶点在U,另一个顶点在V的最小边

if ((lowcost[j]

{

min = lowcost[j];

k = j;

}

printf("(%d,%d)%d\t", prevex[k] - 1, k - 1, min);

lowcost[k] = 0; //顶点k加入U

for (j = 2; j <= n; j++)

//修改由顶点k到其他顶点边的权值

if (g[k][j]

{

lowcost[j] = g[k][j];

prevex[j] = k;

}

printf("\n");

}

return 0;

}

int acrvisited[100];//kruscal弧标记数组

int find(int acrvisited[], int f)

{

while (acrvisited[f]>0)

f = acrvisited[f];

return f;

}

void kruscal_arc(MGraph_L G, algraph gra)

{

edg edgs[20];

int i, j, k = 0;

for (i = 0; i != G.vexnum; ++i)

for (j = i; j != G.vexnum; ++j)

{

if (G.arcs[i][j].adj != 10000)

{

edgs[k].pre = i;

edgs[k].bak = j;

edgs[k].weight = G.arcs[i][j].adj;

++k;

}

}

int x, y, m, n;

int buf, edf;

for (i = 0; i != gra.arcnum; ++i)

acrvisited[i] = 0;

for (j = 0; j != G.arcnum; ++j)

{

m = 10000;

for (i = 0; i != G.arcnum; ++i)

{

if (edgs[i].weight

{

m = edgs[i].weight;

x = edgs[i].pre;

y = edgs[i].bak;

n = i;

}

}

//  cout<

//  cout<

buf = find(acrvisited, x);

edf = find(acrvisited, y);

//  cout<

"<

edgs[n].weight = 10000;

if (buf != edf)

{

acrvisited[buf] = edf;

cout << "(" << x << "," << y <<

")" << m;

cout << endl;

}

}

}

void main()

{

algraph gra;

MGraph_L G;

int i, d, g[20][20];

char a = 'a';

d = creatMGraph_L(G);

creatadj(gra, G);

vnode v;

cout << endl << "……####注意:若该图为非强连通图(含有多个连通分量)时"

<< endl

<< "  最小生成树不存在,则显示为非法值。" << endl <<

endl;

cout << "…………………菜单……………………" << endl <<

endl;

cout << "0、显示该图的邻接矩阵……………………" << endl;

cout << "1、显示该图的邻接表……………………" << endl;

cout << "2、深度优先遍历…………………………" << endl;

cout << "3、广度优先遍历…………………………" << endl;

cout << "4、最小生成树PRIM算法…………………" << endl;

cout << "5、最小生成树KRUSCAL算法………………" << endl;

cout << "6、该图的连通分量………………………" << endl <<

endl;

int s;

char y = 'y';

while (y = 'y')

{

cout << "请选择菜单:" << endl;

cin >> s;

switch (s)

{

case 0:

cout << "邻接矩阵显示如下:" << endl;

ljjzprint(G);

break;

case 1:

cout << "邻接表显示如下:" << endl;

adjprint(gra);

break;

case 2:

cout << "广度优先遍历:";

bfstra(gra);

cout << endl;

break;

case 3:

for (i = 0; i != gra.vexnum; ++i)

{

visited[i] = 0;

}

cout << "深度优先遍历:";

dfstra(gra);

cout << endl;

break;

case 4:

for (i = 0; i != G.vexnum; ++i)

for (int j = 0; j != G.vexnum; ++j)

g[i + 1][j + 1] = G.arcs[i][j].adj;

cout << "prim:" << endl;

prim(g, d);

break;

case 5:

cout << "kruscal:" << endl;

kruscal_arc(G, gra);

break;

case 6:

cout << "连通分量:";

bfstra_fen(gra);

break;

}

cout << endl << "是否继续?y/n:";

cin >> y;

if (y == 'n')

break;

}

}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值