数据结构--无向图--初级版
其实图的存储结构很简单,常见的就是邻接表和邻接矩阵。
个人觉得,比较复杂的是求最短路径之类的算法。
下面先发一个基础版的,实现了深度和广度优先遍历。
但这里的遍历方法和大多数教科书上有了一点区别,就是没有用递归,而是用栈代替了。因为递归是讲所谓的“现场”保存到调用栈中,而调用栈好像很小,很容易溢出。
但这个版本也存在一些效率问题,我会在注释里写出
里面使用的liststock其实就是封装了一个前面介绍的链表类。很简单
1 #pragma once;
2 #include <iostream>
3 #include "mylist.h"
4 #include "liststack.h"
5
6 /************************************************************************/
7 /* 用邻接表结构实现图 */
8 /************************************************************************/
9
10 template<typename T>
11 struct vertex
12 {
13 T data;
14 int nWeight;
15 mylist<int> borders;
16 };
17
18 const int MAX_VERTEX_COUNT = 6;
19
20 template<typename T>
21 class mygraph
22 {
23 public:
24 mygraph()
25 {
26 m_size = MAX_VERTEX_COUNT;
27
28 }
29
30 void setVertexData(int nVertex, const T& data, int nWeight)
31 {
32 if(nVertex >= m_size)
33 {
34 throw("超出顶点数量");
35 }
36 m_vertexlist[nVertex].data = data;
37 m_vertexlist[nVertex].nWeight = nWeight;
38 }
39
40 void addBorder(int nVertex, int nRelation)
41 {
42 if(nVertex >= m_size || nRelation >= m_size)
43 {
44 throw("超出顶点数量");
45 }
46 _addBorder(nVertex, nRelation);
47 _addBorder(nRelation, nVertex);
48 //无向图,需要同时设置两个顶点的关系
49 }
50
51 //广度优先遍历
52 void BFS(int nFirstVertex)
53 {
54 bool visitRecord[MAX_VERTEX_COUNT];
55 liststack<int> searchStack;
56
57
58
59 searchStack.push(nFirstVertex);
60 while(!searchStack.empty())
61 {
62 int nCurrentVertex = searchStack.pop();
63
64 visitRecord[nCurrentVertex] = true;
65
66 mylist<int>::Iterator iBegin = m_vertexlist[nCurrentVertex].borders.begin();
67 while(iBegin != m_vertexlist[nCurrentVertex].borders.end())
68 {
69 if(!visitRecord[*iBegin])
70 {
71 visitRecord[*iBegin] = true;
72 //
73 searchStack.push(*iBegin);
74 cout<< nCurrentVertex << "--" << *iBegin << endl;
75
76 }
77 iBegin ++;
78 }
79
80 }
81
82
83 }
84
85 //深度优先遍历
86 void DFS(int nFirstVertex)
87 {
88 bool visitRecord[MAX_VERTEX_COUNT];
89 liststack<int> searchStack;
90
91 int i;
92 for(i = 0; i < m_size; i ++)
93 {
94 visitRecord[i] = false;
95 }
96
97
98
99 while(!searchStack.empty())
100 {
101 int nCurrentVertex = searchStack.top();
102
103 visitRecord[nCurrentVertex] = true;
104
105 mylist<int>::Iterator iBegin = m_vertexlist[nCurrentVertex].borders.begin();
106
107 //这里就存在一个效率问题,每次都从邻接表的头开始遍历。
108 //但之所以没有保存链表中的迭代器对象,是担心在多线程操作中,
109 //可能一个线程遍历,另一个线程在给图增加定点。
110 //虽然这个实现版本中定点数是固定的,但绝对很容易就改成可动态增长的。
111 //一旦数组动态增长,那么链表中的指针就会变为无效。
112 //大家都知道,复制指针是很危险的,除非用灵巧指针代替。
113 //今后的版本中会修改这个问题
114 while(iBegin != m_vertexlist[nCurrentVertex].borders.end())
115 {
116 if(!visitRecord[*iBegin])
117 {
118 visitRecord[*iBegin] = true;
119 searchStack.push(*iBegin);
120 cout << nCurrentVertex << "-" << *iBegin << endl;
121 break;
122 }
123 iBegin ++;
124 }
125 if(iBegin == m_vertexlist[nCurrentVertex].borders.end())
126 {
127
128 searchStack.pop();
129 }
130 }
131 }
132
133 private:
134 void _addBorder(int nVertex, int nRelation)
135 {
136
137 if(!(m_vertexlist[nVertex].borders.find(nRelation) == m_vertexlist[nVertex].borders.end()))
138 {
139 return ;
140 }
141
142 m_vertexlist[nVertex].borders.insert(nRelation);
143 }
144 size_t m_size;
145 vertex<T> m_vertexlist[MAX_VERTEX_COUNT];
146
147 };
2 #include <iostream>
3 #include "mylist.h"
4 #include "liststack.h"
5
6 /************************************************************************/
7 /* 用邻接表结构实现图 */
8 /************************************************************************/
9
10 template<typename T>
11 struct vertex
12 {
13 T data;
14 int nWeight;
15 mylist<int> borders;
16 };
17
18 const int MAX_VERTEX_COUNT = 6;
19
20 template<typename T>
21 class mygraph
22 {
23 public:
24 mygraph()
25 {
26 m_size = MAX_VERTEX_COUNT;
27
28 }
29
30 void setVertexData(int nVertex, const T& data, int nWeight)
31 {
32 if(nVertex >= m_size)
33 {
34 throw("超出顶点数量");
35 }
36 m_vertexlist[nVertex].data = data;
37 m_vertexlist[nVertex].nWeight = nWeight;
38 }
39
40 void addBorder(int nVertex, int nRelation)
41 {
42 if(nVertex >= m_size || nRelation >= m_size)
43 {
44 throw("超出顶点数量");
45 }
46 _addBorder(nVertex, nRelation);
47 _addBorder(nRelation, nVertex);
48 //无向图,需要同时设置两个顶点的关系
49 }
50
51 //广度优先遍历
52 void BFS(int nFirstVertex)
53 {
54 bool visitRecord[MAX_VERTEX_COUNT];
55 liststack<int> searchStack;
56
57
58
59 searchStack.push(nFirstVertex);
60 while(!searchStack.empty())
61 {
62 int nCurrentVertex = searchStack.pop();
63
64 visitRecord[nCurrentVertex] = true;
65
66 mylist<int>::Iterator iBegin = m_vertexlist[nCurrentVertex].borders.begin();
67 while(iBegin != m_vertexlist[nCurrentVertex].borders.end())
68 {
69 if(!visitRecord[*iBegin])
70 {
71 visitRecord[*iBegin] = true;
72 //
73 searchStack.push(*iBegin);
74 cout<< nCurrentVertex << "--" << *iBegin << endl;
75
76 }
77 iBegin ++;
78 }
79
80 }
81
82
83 }
84
85 //深度优先遍历
86 void DFS(int nFirstVertex)
87 {
88 bool visitRecord[MAX_VERTEX_COUNT];
89 liststack<int> searchStack;
90
91 int i;
92 for(i = 0; i < m_size; i ++)
93 {
94 visitRecord[i] = false;
95 }
96
97
98
99 while(!searchStack.empty())
100 {
101 int nCurrentVertex = searchStack.top();
102
103 visitRecord[nCurrentVertex] = true;
104
105 mylist<int>::Iterator iBegin = m_vertexlist[nCurrentVertex].borders.begin();
106
107 //这里就存在一个效率问题,每次都从邻接表的头开始遍历。
108 //但之所以没有保存链表中的迭代器对象,是担心在多线程操作中,
109 //可能一个线程遍历,另一个线程在给图增加定点。
110 //虽然这个实现版本中定点数是固定的,但绝对很容易就改成可动态增长的。
111 //一旦数组动态增长,那么链表中的指针就会变为无效。
112 //大家都知道,复制指针是很危险的,除非用灵巧指针代替。
113 //今后的版本中会修改这个问题
114 while(iBegin != m_vertexlist[nCurrentVertex].borders.end())
115 {
116 if(!visitRecord[*iBegin])
117 {
118 visitRecord[*iBegin] = true;
119 searchStack.push(*iBegin);
120 cout << nCurrentVertex << "-" << *iBegin << endl;
121 break;
122 }
123 iBegin ++;
124 }
125 if(iBegin == m_vertexlist[nCurrentVertex].borders.end())
126 {
127
128 searchStack.pop();
129 }
130 }
131 }
132
133 private:
134 void _addBorder(int nVertex, int nRelation)
135 {
136
137 if(!(m_vertexlist[nVertex].borders.find(nRelation) == m_vertexlist[nVertex].borders.end()))
138 {
139 return ;
140 }
141
142 m_vertexlist[nVertex].borders.insert(nRelation);
143 }
144 size_t m_size;
145 vertex<T> m_vertexlist[MAX_VERTEX_COUNT];
146
147 };