数据结构-3
线性结构是树的一般情况,树则是图的一般情况,那么现在开始实现图的有关算法
先梳理一遍图的概述:
包含:Vertex一组顶点(非空)
Edge一组边(可空)<集合V之间的关系的解释>
定义:图是由非空有限顶点集合(V)和有限边集合(E)组合成的一种数据结构。Graph=( V, E ) V = {x | x ∈某个数据对象 } 是顶点的有穷非空集合;
术语:无向图:顶点之间一定互通
有向图:顶点之间存在单向连通
邻接:俩点单/双向连通
关联:一条边可以关联两个点
完全图:任意两顶点互通
度:分为入度或出度,是对顶点的描述词,称该顶点的入度或出度,入度是只允许从别的点到该点,出度则是从该点到别的点
权:一般是边的长度,
路径:依次遍历顶点序列之间的边所形成的轨迹。
环:循环的路径
存储结构:
邻接矩阵:二维数组,x轴坐标和y轴坐标处的值表示两点是否连通
邻接表:在邻接矩阵出现大量空数据时,用链表代替非空值
十字链表:顾名思义,交叉的链表构成的图,是邻接表的优化方案
邻接多重表:十字链表在无向图上的优化方案
边集数组:两个一维数组,一个储存V一个储存E,优点在于可以方便对边依次操作
操作集:
创建图Graph Create,
插入顶点Graph InsertVertex,
插入边Graph Edge,
深度优先搜索DFS,
广度优先搜索BFS,
求最小生成树MST,(Prim算法和Kruskal算法)
我要实现的:
以邻接矩阵和邻接表实现以上所有操作集...要耐心!!!
#include <iostream> using namespace std; struct Queue { int arr[100]; int maxlen; int left;//队列尾巴 int right;//队列头 int len; void Init() { maxlen = 100; left = 0; right = -1; len = 0; } bool IsNull() { if (len==0)return true; return false; } bool IsFull() { if (len == maxlen)return true; return false; } bool Enqueque(int num) { bool rt=false; if (!IsFull())//一定不能满 { right++; arr[right%maxlen] = num; len++; rt = true; } return rt; } int Dequeque() { int rt = 0x7fffffff; if (!IsNull())//一定不能是空的 { rt = arr[left % maxlen]; len--; left++; } return rt; } void Show() { for (int i=0; i < len ; i++) { cout<< arr[(left+i)%maxlen]<< " "; } cout << endl; } }; struct Path { int* parr; int len; int* pre; void Init(int l) { parr = (int*)malloc(sizeof(int) * l); pre = (int*)malloc(sizeof(int) * l);//用于BFS记录路径,但是最好采用结构体! len = 0; } void Add(int _pre,int now) { parr[len] = now; pre[len++] = _pre; } int Find(int value) { int r = -1; for (int i = 0; i < len; i++) { if (parr[i] == value) { r = i; break; } } return r; } bool Contain(int a) { for (int i = 0; i < len; i++) { if (a == parr[i])return true; } return false; } void Show(int type) { if (type == 0) { for (int i = 0; i < len; i++) { cout << parr[i] << " ,"; } } else { for (int i = len-1; i >=0; i--) { cout << parr[i] << " ,"; } } } }; Path rPath; struct Graph { int** arr; int h; int w; void Create(int _h) { arr = (int**)malloc(sizeof(int*) *_h); for (int i = 0; i < _h; i++) { arr[i]= (int*)malloc(sizeof(int) * _h); } h = _h; w = _h; for(int j=0;j<_h;j++) for (int i = 0; i < _h; i++) { arr[j][i] = 0; } } //由于邻接矩阵点已经全部存在,所以只需要设置边即可 void SetEdge(int _h,int _w,int value) { arr[_h][_w] = value; } void DFS(Path p, Graph map, int now, int target, int size, int len)//size为整张图的尺寸 { if (now == target) { cout << "DFS "; p.Show(0); cout << endl; if (len<rPath.len) { rPath = p; } return; } len++; p.Add(-1,now); for (int i = 0; i < size; i++) { if (w = map.arr[now][i] != 0 && !p.Contain(i))//与1相邻的点是否包含在path中 DFS(p,map, i, target, size,len); //C语言结构体参数为值传递,故不需要回溯,如果使用数组,就必须回溯 } } Path BFS(Graph map, int now, int target,int size) { //层序遍历一样的方法 Path p;//用于存放已经走过的点 p.Init(100); Path rp;//用于存放路径 rp.Init(100); Queue q; q.Init(); q.Enqueque(now); p.Add(-1,now); int pi = 0; while (!q.IsNull()) { int t = q.Dequeque();//取出一个 for (int i = 0; i < size; i++) { if (map.arr[t][i] != 0) { if (i == target) { p.Add(t, i); cout << "BFS"; while (i != -1) { rp.Add(t, i); i = p.pre[p.Find(i)]; } return rp; } if (!p.Contain(i))//未走过 { q.Enqueque(i); p.Add(t,i); } } } } cout << "找不到路径"<<endl; return rp; } void Show() { for (int j = 0; j < h; j++) { for (int i = 0; i < w; i++) { cout << arr[j][i] << " "; } cout<<endl; } } }; void AA(Path p) { cout << "函数内 设置前 p.parr[0] = " << p.parr[0] << endl; p.parr[0] = 2; cout << "函数内 设置后 p.parr[0] = " << p.parr[0] << endl; } int main() { Graph t; t.Create(6);//六个点 t.SetEdge(0, 1, 1); t.SetEdge(1, 0, 1); t.SetEdge(0, 5, 1); t.SetEdge(5, 0, 1); t.SetEdge(1, 2, 1);//设置1->2距离1 t.SetEdge(2, 1, 1);//设置2->1距离1 t.SetEdge(2, 3, 1); t.SetEdge(3, 2, 1); t.SetEdge(2, 4, 1); t.SetEdge(4, 2, 1); t.SetEdge(3, 4, 1); t.SetEdge(4, 3, 1); t.SetEdge(4, 5, 1); t.SetEdge(5, 4, 1); t.SetEdge(3, 5, 1); t.SetEdge(5, 3, 1); t.Show(); cout << endl; //遍历 Path p; p.Init(100); rPath.Init(100); rPath.len = 99999; t.DFS(p,t,1,4,6,0); cout << "DFS最短路径:"; rPath.Show(0); cout << "4 ,"; cout << endl; cout << endl; rPath = t.BFS(t, 1, 4, 6); cout << "最短路径:"; rPath.Show(1); cout << endl; cout << endl; return 0; }
未完待续

浙公网安备 33010602011771号