图算法集锦

--------------
1)图存储结构
--------------
typedef int WeightType;                 //权重类型
typedef int VertexType;                    //顶点类型
const int MaxVertexNum = 10;             //最大顶点
const int MaxEdgeNum = 10;                //最大边数
const WeightType maxvalue = 1000;        //最大值1000

//图数组存储
typedef VertexType vexlist[MaxVertexNum];//顶点向量
typedef int adjmatrix[MaxVertexNum][MaxVertexNum];  

//图链接表存储
struct edgenode {
int adjvex;          //结点序号
WeightType weight;   //权重
edgenode* next;      //指向下一个结点
};
typedef edgenode* adjlist[MaxVertexNum];

//图边集存储
struct edge{
int fromvex;            //起始点
int endvex;             //终点
WeightType weight;//权重
};
typedef edge edgeset[MaxEdgeNum];

---------------
2)图的遍历
---------------
 1    #include <iostream>
 2    #include <cstdlib>
 3    #include <string>
 4   
 5   
 6    using namespace std;
 7   
 8    typedef int VertexType;
 9    typedef int WeightType;
10   
11    const int MaxVertexNum = 10;
12    const  WeightType MaxValue = 1000;
13   
14    typedef VertexType vexlist[MaxVertexNum];
15    typedef int adjmatrix[MaxVertexNum][MaxVertexNum];
16   
17   
18    void dfsMatrix(adjmatrix GA,int i, int n,bool * visited)
19    {
20        cout<<i<<' ';
21        visited[i] = true;
22        for (int j = 0; j < n; ++j)
23            {
24                if(GA[i][j]!=0&&GA[i][j]!=MaxValue&&!visited[j])
25                    dfsMatrix(GA,j,n,visited);
26            }
27    }
28   
29    void bfsMatrix(adjmatrix GA,int i,int n,bool* visited)
30    {
31        const int maxsize = 30;
32        int q[maxsize] = {0};
33        int front = 0,rear = 0;
34        cout<< i <<' ';
35        visited[i] = true;
36        q[++rear] = i;
37        while (front != rear)
38            {
39                front = (front+1)%maxsize;
40                int k = q[front];
41                for (int j = 0; j < n; ++j)
42                    {
43                        if (GA[k][j]!=0&&GA[k][j]!=MaxValue&&!visited[j])
44                            {
45                                cout<<j<<' ';
46                                visited[j] = true;
47                                rear = rear+1%maxsize;
48                                q[rear] = j;
49                            }//if
50                    }//for
51            }//while
52    }
53   
54    int main(int argc, char * argv[])
55    {
56        cout << "======= DFS ====== " << endl;
57        for (i = 0; i < n; ++i)
58            {
59                visited[i] = false;
60            }
61        dfsMatrix(ga,0,n,visited);
62        cout<<endl;
63   
64        cout << "======= BFS ====== " << endl;
65        for (i = 0; i < n; ++i)
66            {
67                visited[i] = false;
68            }
69        bfsMatrix(ga,0,n,visited);
70        cout<<endl;
71   
72        return 0;
73    }
-------------------
3)图的连通性问题(最小生成树)
-------------------
1.prim算法:(适合求稠密图求最小生成树)(O(n^2))
Prim算法的基本思想是:
  (1) 在图G=(V, E) (V表示顶点,E表示边)中,从集合V中任取一个顶点(例如取顶点v0)放入集合 U中,这时 U={v0},集合T(E)为空。
  (2) 从v0出发寻找与U中顶点相邻(另一顶点在V中)权值最小的边的另一顶点v1,并使v1加入U。即U={v0,v1 },同时将该边加入集合T(E)中。
  (3) 重复(2),直到U = V为止。
  这时T(E)中有n-1条边,T = (U, T(E))就是一棵最小生成树。
 1    #include <iostream>
 2    #include <cstring>
 3    #include <fstream>
 4   
 5    using namespace std;
 6   
 7    typedef int WeightType;
 8    typedef int VertexType;
 9    const int MaxVertexNum = 10;
10    const int MaxEdgeNum = 10;
11    const WeightType maxvalue = 100;
12    typedef VertexType vexlist[MaxVertexNum];
13    typedef int adjmatrix[MaxVertexNum][MaxVertexNum];
14   
15    struct edge{
16        int fromvex;
17        int endvex;
18        WeightType weight;
19    };
20    typedef edge edgeset[MaxEdgeNum];
21   
22    void mst_prim(adjmatrix GA, edgeset CT,int n)
23    {
24        //利用普里姆算法从顶点v0出发求出用邻接矩阵GA表示的图的最小生成树,
25        //最小生成树的边集存于数组CT中
26        int i,j,k,min,t,m,w;
27        //v0 initial CT
28        for (i = 0; i < n-1; ++i)
29            {
30                CT[i].fromvex = 0;
31                CT[i].endvex = i+1;
32                CT[i].weight = GA[0][i+1];
33            }
34        //进行n-1循环,每次求出最小生成树中的第k条边
35        for(k = 1;k<n;k++)
36            {
37                //从CT[k-1]至CT[n-1]中查找最短边CT[m]
38                min = CT[k-1].weight;//先假设CT[k-1]为最短边
39                m=k-1;
40                for (j = k-1; j < n-1; ++j)
41                    {
42                        if (CT[j].weight<min)
43                            {
44                                min = CT[j].weight;
45                                m = j;
46                            }
47                    }
48                swap(CT[k-1] , CT[m]);//把最短边调到k-1下标的位置
49                j = CT[k-1].endvex;//把新并入最小生成树T中的顶点的顶点序号赋值给j
50            /*
51             *-------------------------------------
52            *修改LW中的有关边,使T中到T外的每一个顶点各保持一条到目前为止最短边
53            *CT[0]~CT[K-2](已经求得的最短边): CT[K]: CT[K-1]~CT[n-1]
54            *对于T:n-(k+1)中的每个顶点t,若(j,t)边上的权值小于原来已经保留从T
55            *到顶点t的最短边的权值,则用(j,t)修改之,使得从T中到T外顶点t的最短边
56            *为(j,t),否则原有最短边保持不变。
57            *-------------------------------------
58            */
59                for (i = k; i < n-1; ++i)
60                    {
61                        t=CT[i].endvex;
62                        w=GA[j][t];
63                        if(w<CT[i].weight){
64                            CT[i].weight = w;
65                            CT[i].fromvex = j;
66                        }
67                    }//inner for
68            }//outer for
69    }
70   
71    void mst_kruskal(edgeset GE,edgeset CT,int n)
72    {
73        int i,j;
74        //用二维数组s作为集合使用,其中每一行元素
75        //s[i][0]~s[i][n-1]用来表示一个集合,若s[i][t]==1
76        //则表示v[t]顶点属于该集合,否则不属于s[i]集合
77        adjmatrix s;
78   
79        for (i = 0; i < n; ++i)
80            {
81                for (j = 0; j < n; ++j)
82                    {
83                        if(i ==j) s[i][j] = true;
84                        else s[i][j] = false;
85                    }
86            }
87   
88        int k =1;//k表示待获取的最小生成树中的边数,初值为1
89        int d = 0;//d表示GE中待扫描边元素的下标位置,初值为0
90        int m1,m2;
91   
92        while (k<n)
93            {
94                /*for(i=0;i<n;i++)
95                  {//求出边GE[d]的两个顶点所在集合的序号m1和m2]
96                  for(j=0;j<n;j++)
97                  {
98                  if(GE[d].fromvex==j&&s[i][j]==1)//找起点
99                  m1=i;
100                  if(GE[d].endvex==j&&s[i][j]==1)//找终点
101                  m2=i;
102                  }
103   
104                  }*/
105                //可以把上面的二重for循环改良成如下的一重for循环
106                for (i = 0; i < n; ++i)
107                    {
108                        if(s[i][GE[d].fromvex] == true) m1 =i;
109                        if(s[i][GE[d].endvex] == true) m2 = i;
110                    }
111   
112                if (m1 != m2)
113                    {
114                        //若两集合序号不等,则表明GE[d]是生成树中的一条边,
115                        //应将它加入到数组C中
116                        CT[k-1] = GE[d];
117                        k++;
118                        for (j = 0; j < n; ++j)
119                            {//合并两个集合,并将另一个置为空集
120                                s[m1][j] = s[m1][j]||s[m2][j];
121                                s[m2][j] = false;
122                            }
123                    }
124                d++;//d后移一个位置,以便扫描GE中的下一条边
125            }
126    }
127   
128    int main(int argc, char * argv[])
129    {
130        ifstream cin ("aaa.txt");
131        adjmatrix ga;
132        edgeset ge;
133        edgeset ct;
134        int vexnum;
135        int edgenum;
136        int casenum;
137        int cn = 0;
138        cin>>casenum;
139        cout<<"There are "<<casenum<<" cases;"<<endl;
140        while(cin>>vexnum)
141            {
142                if(88 == vexnum)break;
143                cn++;
144                for(int i = 0 ;i<vexnum;i++)
145                    {
146                        for(int j = 0; j<vexnum;j++)
147                            {
148                                cin>>ga[i][j];
149                            }
150                    }
151                mst_prim(ga,ct,vexnum);
152                cout<<"The "<<cn<<"th case:"<<endl;
153                for(int i=0;i<vexnum-1;i++)
154                    {
155                        cout<<" 起点:"<<ct[i].fromvex<<"  "
156                            <<"终点:"<<ct[i].endvex<<"  "
157                            <<"权值:"<<ct[i].weight<<endl;
158                    }
159            }
160        puts("--------------------------");
161        cin>>vexnum>>edgenum;
162        for (int i = 0;i<edgenum;i++)
163            {
164                cin>>ge[i].fromvex>>ge[i].endvex>>ge[i].weight;       
165            }
166        mst_kruskal(ge,ct,vexnum);
167        for(int i=0;i<vexnum-1;i++)
168            {
169                cout<<" 起点:"<<ct[i].fromvex<<"  "
170                    <<"终点:"<<ct[i].endvex<<"  "
171                    <<"权值:"<<ct[i].weight<<endl;
172            }
173        return 0;
174    }
--------------------------
There are 3 cases;
The 1th case:
 起点:0  终点:3  权值:5
 起点:3  终点:1  权值:3
 起点:3  终点:5  权值:7
 起点:5  终点:2  权值:2
 起点:2  终点:4  权值:6
 起点:3  终点:6  权值:15
The 2th case:
 起点:0  终点:2  权值:3
 起点:2  终点:1  权值:4
The 3th case:
 起点:0  终点:2  权值:3
 起点:2  终点:1  权值:4
-------------------------
 起点:0  终点:4  权值:4
 起点:1  终点:2  权值:5
 起点:1  终点:3  权值:8
 起点:1  终点:5  权值:12
 起点:0  终点:1  权值:18
---------------------------

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值