图的邻接表(广度优先遍历,深度优先遍历,最小生成树(Kruskal算法))

main.h:

#include <iostream>
#include <queue>
#define DefaultSize 10
#define maxWeight -1
using namespace std;

template<typename T,typename E>
struct Edge
{
	int dest;
	E cost;
	Edge<T,E> *link;
	Edge(int d=0,int c=0):dest(d),cost(c),link(NULL){}

};

template<typename T,typename E>
struct Vertex
{
	T data;
	Edge<T,E> *adj;
};

template<typename T,typename E>
class Base
{
	public:
	virtual T getValue(int i)=0;
	virtual E getWeight(int v1,int v2)=0;
	virtual bool insertVertex(const T& vertex)=0;
	virtual bool insertEdge(const T& l,const T& r,E cost)=0;
	virtual void Show()=0;
	virtual bool removeEdge(int v1,int v2)=0;
	virtual bool removeVertex(int v)=0;
	virtual int getFirstNeighbor(int v)=0;
	virtual int NumberOfEdge()=0;
	virtual int getNextNeighbor(int v,int w)=0;
};
template<typename T,typename E>
class Graphlnk:public Base<T,E>
{
	public:

		Graphlnk(int sz=DefaultSize)
		{
			numVertices=0;
			maxVertices=DefaultSize;
			numEgde=0;
			NodeTable = new Vertex<T,E>[sz];
			for(int i=0;i<sz;i++)
			{
				NodeTable[i].adj=NULL;
			}
		}
		int NumberOfEdge()
		{
			return numEgde;
		}
		int getFirstNeighbor(int v)
		{
			if(v<0||v>=numVertices)return -1;
			Edge<T,E> *p = NodeTable[v].adj;
			if(p!=NULL)
			{
				return p->dest;
			}
			return -1;
		}
	int getNextNeighbor(int v,int w)
	{
			if(v<0 || v>=numVertices || w<0 || w>=numVertices)
			{
				return -1;
			}
			Edge<T,E> *p = NodeTable[v].adj;
			while(p!=NULL)
			{

				if(p->dest == w)
				{
					if(p->link!=NULL)
						return p->link->dest;
				}
				p = p->link;
			}
			return -1;
	}
	bool removeVertex(int v)
	{
		Edge<T,E> *p = NodeTable[v].adj;
		while(p!=NULL)
		{
			removeEdge(v,p->dest);
			p=p->link;
		}
		NodeTable[v].data = NodeTable[numVertices-1].data;
		NodeTable[v].adj = NodeTable[numVertices-1].adj;
		p = NodeTable[numVertices-1].adj;
		Edge<T,E> *q = NULL;
		while(p!=NULL)
		{
			int index = p->dest;
			q = NodeTable[index].adj;
			while(q!=NULL)
			{
				if(q->dest==(numVertices-1))
				{
						q->dest = v;
						break;
				}
				q=q->link;
			}
			p=p->link;
		}
		numVertices--;
	}
	bool removeEdge(int v1,int v2)
	{
		if(v1<0||v1>=numVertices||v2<0||v2>=numVertices)
			{return false;}
		Edge<T,E> *p = NodeTable[v1].adj;
		Edge<T,E> *q = NULL;
		while(p!=NULL && p->dest!=v2)
		{
			q=p;
			p=p->link;
		}
		if(q==NULL && p==NULL)
		{
			return false;
		}
		if(q==NULL && p!=NULL && p->dest==v2)
		{
			NodeTable[v1].adj=p->link;
			delete p;
		}
		if(p==NULL)
		{
			return false;
		}
		else if(q!=NULL)
		{
			q->link=p->link;
			delete p;
		}
		p = NodeTable[v2].adj;
		q = NULL;
		while(p!=NULL && p->dest!=v1)
		{
			q=p;
			p=p->link;
		}
		if(q==NULL && p==NULL)
		{
			return false;
		}
		if(q==NULL && p!=NULL && p->dest==v1)
		{
		NodeTable[v2].adj=p->link;
		delete p;
		}
		if(p==NULL)
		{
			return false;
		}
		else if(q!=NULL)
		{
			q->link=p->link;
			delete p;
		}
		numEgde--;
	}
	bool insertEdge(const T& l,const T& r,E cost)
	{
		int v1 = getValuePos(l);
		int v2 = getValuePos(r);
		Edge<T,E> *p = NodeTable[v1].adj;
		Edge<T,E> *s = new Edge<T,E>(v2,cost);
		Edge<T,E> *q = NULL;
		while(p!=NULL && p->dest!=cost)
		{
			q=p;
			p=p->link;
		}
		if(p!=NULL && p->dest==cost)
		{
			return false;
		}
		if(q==NULL)
		{
			NodeTable[v1].adj = s;
		}
		if(p==NULL && q!=NULL)
		{
			s->link = NodeTable[v1].adj;
		  NodeTable[v1].adj=s;
		}
		p = NodeTable[v2].adj;
		s = new Edge<T,E>(v1,cost);
		q = NULL;
		while(p!=NULL && p->dest!=cost)
		{
			q=p;
			p=p->link;
		}
		if(p!=NULL && p->dest==cost)
		{
			return false;
		}
		if(q==NULL)
		{
			NodeTable[v2].adj = s;
		}
		if(p==NULL&&q!=NULL)
		{
			s->link = NodeTable[v2].adj;
		  NodeTable[v2].adj=s;
		}
		numEgde++;
	}
	bool insertVertex(const T& vertex)
	{
		NodeTable[numVertices++].data=vertex;
		return true;
	}
	void Show()
	{
		Edge<T,E> *p=NULL;
		for(int i=0;i<numVertices;i++)
		{
			cout<<NodeTable[i].data<<">  ";
			p=NodeTable[i].adj;
			while(p!=NULL)
			{
				cout<<p->dest<<"--"<<p->cost<<"    ";
				p=p->link;
			}
			cout<<endl;
		}
	}
	E getWeight(int v1,int v2)
	{
		if(v1<0 || v1>=numVertices || v2<0 || v2>=numVertices)
			{
				return -1;
			}
		 Edge<T,E> *p = NodeTable[v1].adj;
		// Edge<T,E> *m = NULL;
		while(p!=NULL)
			{
				//m = p;
				if(p->dest==v2)
						break;
				p=p->link;
			}
			if(p!=NULL)
				{return p->cost;}
			else
				{return maxWeight;}
	}
	T getValue(int i)
	{
			return	NodeTable[i].data;
	}
 int NumberOfVertices()
	{
		return numVertices;
	}
		int getValuePos(const T &t)
		{
			for(int i=0;i<numVertices;i++)
			{
				if(NodeTable[i].data==t)
					return i;
			}
			return -1;
		}
	Edge<T,E> * getNodeptr(int i)
	{
		return NodeTable[i].adj;
	}
	private:
		int numVertices;
		int maxVertices;
		int numEgde;
		Vertex<T,E> *NodeTable;
};

template<typename T,typename E>
void DFS(Graphlnk<T,E>& G,const T& v,bool visted[])
{
		int index = G.getValuePos(v);
		cout<<G.getValue(index)<<endl;
		visted[index]=true;
		int w = G.getFirstNeighbor(index);
		while(w!=-1)
		{
			if(!visted[w])DFS(G,G.getValue(w),visted);
			w = G.getNextNeighbor(index,w);
		}
	/*	while(index!=-1)
		{
			int x = 0;
			while(!visted[index])
			{
					cout<<G.getValue(index)<<endl;
					visted[index]=true;
					x = G.getFirstNeighbor(index);
					DFS(G,G.getValue(x),visted);
			}
			index = G.getNextNeighbor(x,index);
		}*/
}

template<typename T,typename E>
void DFS(Graphlnk<T,E>& G,const T& v)
{
		int n = G.NumberOfVertices();
		bool *visted = new bool[n];
		for(int i=0;i<n;i++)
		{
			visted[i] = false;
		}
		DFS(G,v,visted);
}

template<typename T,typename E>
void BFS(Graphlnk<T,E>& G,const T& v)
{
	int n = G.NumberOfVertices();
	bool *visted = new bool[n];
	for(int i=0;i<n;i++)
	{
		visted[i] = false;
	}
	int i = G.getValuePos(v);
	queue<int> Q;
	Q.push(i);
	int index;
while(!Q.empty())
	{
		index = Q.front();
		Q.pop();
		if(!visted[index])
		{
		cout<<G.getValue(index)<<endl;
		visted[index] = true;
		}
		int x = G.getFirstNeighbor(index);
		while(x!=-1)
	 {
		if(!visted[x])
		{
		Q.push(x);
		}
		x = G.getNextNeighbor(index,x);
	 }
	}
}

template<typename T,typename E>
void Search(Graphlnk<T,E> &G)
{
	bool *visted = new bool[G.NumberOfVertices()];
	for(int i=0;i<G.NumberOfVertices();i++)
		{
			if(!visted[i])
				DFS(G,G.getValue(i),visted);
		}
}

main.cpp:

#include <iostream>
#include "main.h"
using namespace std;

template<typename T>
class MinHeap
{
	public:
	MinHeap(int sz)
	{
		Maxsize = sz;
		data = new T[sz];
		Numsize = 0;
	}
	void Insert(T x)
	{
		data[Numsize++] = x;
		int n = Numsize/2;
		while(n>=0)
		{
			Sort(data,n);
			n--;
		}
	}
	void Swap(T *a,T *b)
		{
			T temp = *a;
			*a = *b;
			*b = temp;
		}
	T Remove()
	{
		T temp = data[0];
		int n=Numsize;
		Numsize=0;
		for(int i=1;i<n;i++)
		{
			Insert(data[i]);
		}
		return temp;
	}
	void Sort(T a[],int n)
	{
			int i = n ;
			int j = 2*i+1;
			while(j<Numsize)
			{
					if(j+1<Numsize && a[j]>a[j+1])
						j=j+1;
					if(j<Numsize && a[i]>a[j])
							Swap(&a[i],&a[j]);
					i = j;
					j = 2*i+1;
			}
	}
	void Show()
	{
		for(int i=0;i<Numsize;i++)
		{
			cout<<data[i]<<"  ";
		}
		cout<<endl;
	}
	private:
	T *data;
	int Maxsize;
	int Numsize;
};

class UFset
{
	public:
	UFset(int sz)
	{
		parent = new int[sz];
		size = sz;
		for(int i=0;i<sz;i++)
		{
			parent[i]=-1;
		}
	}
	void Show()
	{
	for(int i=0;i<size;i++)
		{
			cout<<parent[i]<<"  ";
	  }
		cout<<endl;
		for(int j=0;j<size;j++)
		{
			cout<<j<<"   ";
		}
		cout<<endl;
	}
	void Union(int a,int b)
	{
		int x = Find(a);
		int y = Find(b);
		if(x!=y)
		{
			if(x>y)
					{
					parent[x]+=parent[y];
					parent[y]=x;
					}
			else
					{
					parent[y]+=parent[x];
					parent[x]=y;
					}
		}
	}
	int Find(int x)
	{
		while(parent[x]>0)
			  x=parent[x];
		return x;
	}
	private:
	int *parent;
	int size;
};

#define Default -1
const float maxValue = Default;
template<typename T,typename E>
struct MSTEdgeNode
{
	int tail,head;E key;
	MSTEdgeNode():tail(-1),head(-1),key(0){}
	bool operator > (const MSTEdgeNode<T,E> &MST)
	{
		return key>MST.key;
	}
	bool operator < (const MSTEdgeNode<T,E> &MST)
	{
		return key<MST.key;
	}
	MSTEdgeNode& operator = (const MSTEdgeNode& MST)
	{
		tail = MST.tail;
		head = MST.head;
		key = MST.key;
		return *this;
	}
};

template<typename T,typename E>
class MinSpanTree
{
	protected:
	MSTEdgeNode<T,E> *edgevalue;
	int MaxSize,n;
	public:
	MinSpanTree(int sz=Default-1):MaxSize(sz),n(0)
	{
		edgevalue = new MSTEdgeNode<T,E>[sz];
	}
	int Insert(MSTEdgeNode<T,E>& item)
	{
		edgevalue[n++]=item;
	}
	void Show()
	{
		for(int i=0;i<n;i++)
		{
			cout<<edgevalue[i].tail<<":"<<edgevalue[i].head<<":"<<edgevalue[i].key<<"  ";
			cout<<endl;
		}
	}
};

template<typename T,typename E>
void Kruskal(Graphlnk<T,E>& G,MinSpanTree<T,E> &MST)
{
  MSTEdgeNode<T,E> ed;int u,v,count;
  int n = G.NumberOfVertices();
	int m = G.NumberOfEdge();
  MinHeap<MSTEdgeNode<T,E> >H(m);
	UFset F(n);
	for(u = 0;u<n;u++)
		{
			for( v = u+1;v<n;v++)
				{
					if(G.getWeight(u,v)!=maxValue)
					{
						ed.tail = u;
						ed.head = v;
						ed.key = G.getWeight(u,v);
						H.Insert(ed);
						//H.Show();
					}
				}
		}
	count=1;
	while(count<m)
		{
			ed = H.Remove();
			u = F.Find(ed.tail);
			v = F.Find(ed.head);
			if(u != v)
				{
						F.Union(u,v);
						MST.Insert(ed);
				}
				count++;
		}
}

int main()
{
	MinSpanTree<char,int> mst(10);
	Graphlnk<char,int> gh;
	gh.insertVertex('A');
	gh.insertVertex('B');
	gh.insertVertex('C');
	gh.insertVertex('D');
	gh.insertVertex('E');
	gh.insertVertex('F');
	gh.insertVertex('G');

	gh.insertEdge('A','B',28);
	gh.insertEdge('B','C',16);
	gh.insertEdge('C','D',12);
	gh.insertEdge('D','E',22);
	gh.insertEdge('E','F',25);
	gh.insertEdge('F','A',10);
	gh.insertEdge('B','G',14);
	gh.insertEdge('D','G',18);
	gh.insertEdge('E','G',24);
	gh.Show();
	cout<<"-------------------"<<endl;
	Kruskal(gh,mst);
	mst.Show();
	return 0;
}
时间: 2024-08-30 05:10:31

图的邻接表(广度优先遍历,深度优先遍历,最小生成树(Kruskal算法))的相关文章

图的邻接表+深度优先遍历+广度优先遍历

1 /** 2 无向图的邻接表存储 3 深度优先遍历递归 4 广度优先遍历递归+非递归 5 */ 6 #include <stdio.h> 7 #include <string.h> 8 #include <malloc.h> 9 #define N 5 10 #define MAX 50 11 typedef struct A{ 12 int adjvex; 13 struct A* nextArc; 14 }Arc; 15 typedef struct node{

浅谈数据结构之图的邻接表深度和广度优先遍历(九)

邻接矩阵是一种不错的图存储结构,但是我们发现,对于边数相对较少的图,这种结构是存在对存储空间的极大浪费的.我们知道,顺序存储结构存在预先分配内存可能造成空间浪费的问题,于是引出了链式存储的结构.同样的,我们也可以考虑对边或弧使用链式存储的方式来避免空间浪费的问题.因此,对于图的存储结构,我们同样引入了一种数组与链表相组合的存储方法,我们一般称之为邻接表. 邻接表的处理方法是这样的:(1).图中顶点用一个一维数组存储,当然,顶点也可以用单链表来存储,不过数组可以较容易的读取顶点的信息,更加方便:另

图的邻接表表示、广度优先、深度优先搜索

图,就是我们在数据结构中学到的图,它是一种存储信息的结构.图是一类在实际应用中非常常见的数据结构,当数据规模大到一定程度时,如何对其进行高效计算即成为迫切需要解决的问题.最常见的大规模图数据的例子就是互联网网页数据,网页之间通过链接指向形成规模超过500 亿节点的巨型网页图.再如,Facebook 社交网络也是规模巨大的图,仅好友关系已经形成超过10 亿节点.千亿边的巨型图,考虑到Facebook 正在将所有的实体数据节点都构建成网状结构,其最终形成的巨型网络数据规模可以想见其规模.要处理如此规

图的遍历---深度优先遍历与广度优先遍历

对下图进行遍历,分别采用深度优先和广度优先 1.深度优先遍历的主要思想:首先从一个未被访问的顶点作为起始顶点,沿当前顶点的边走到未访问过的顶点: 当没有未访问过的顶点时,则回到上一个顶点,继续试探访问别的顶点,直到所有顶点都被访问. 显然,深度优先遍历是沿着图的某一条分支遍历直到末端,然后回溯,再沿着另一条进行同样的遍历,直到所有顶点被访问. /*深度优先搜索算法遍历图的各个顶点*/ #include<stdio.h> int n, sum, book[101]; int e[101][101

数据结构学习笔记05图 (邻接矩阵 邻接表--&gt;BFS DFS)

数据结构之图 图(Graph) 包含 一组顶点:通常用V (Vertex) 表示顶点集合 一组边:通常用E (Edge) 表示边的集合 边是顶点对:(v, w) ∈E ,其中v, w ∈ V 有向边<v, w> 表示从v指向w的边(单行线) 不考虑重边和自回路 无向图:边是无向边(v, w) 有向图:边是有向边<v, w> 连通:如果从V到W存在一条(无向)路径,则称V和W是连通的 连通图(Connected Graph):如果对于图的任一两个顶点v.w∈V,v和w都是连通的,则称

数据结构之---C语言实现图的邻接表存储表示

// 图的数组(邻接矩阵)存储表示 #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_NAME 3 // 顶点字符串的最大长度+1 #define MAX_VERTEX_NUM 20 typedef int InfoType; // 存放网的权值 typedef char VertexType[MAX_NAME]; // 字符串类型 typedef enum{DG, DN, AG

图(邻接表)

我们先来看一个图 我们想将这个图的信息存储到邻接表中,我们需要一个数组保存节点信息,还要有一个节点用来保存与该节点相邻的节点信息. 1 typedef struct arc_node 2 { 3 int pos; 4 int distance; 5 struct arc_node * next; 6 } Arc_node;//保存Node节点的相邻节点信息 7 8 typedef struct node 9 { 10 node_type info; 11 Arc_node * next; 12

基于C++ STL图的邻接表表示及深度、广度搜索实现

基于C++ STL图的邻接表表示及深度.广度搜索实现,对图论的学习有帮助,代码如下: #include <iostream> #include <vector> #include <set> using namespace std; #define MAX(a, b) ((a) > (b) ? (a) : (b) ) //定义图的定点 typedef struct Vertex { int id; vector<int> connectors; //存

看数据结构写代码(36) 图的邻接表表示与实现

图的邻接表表示法,是为每一个顶点建立一个链表,链表里存放着相同弧尾的 弧的信息,这些链表顺序存放在数组中.下面是无向图g2的邻接表 邻接表 比 邻接矩阵 节省空间,同时 也带来一些操作上的 不便,例如 看 两个顶点是否 相邻,需要 遍历 链表,在 求 无向图顶点的度时,只需 遍历 顶点的链表,而 求 有向图 顶点的度 需要 遍历 整个图 查找 弧头 为这个顶点的 个数. 如果 不想这样做,可以 建立 逆邻接表,即 链表里 存放着 相同 弧头的 弧 的信息. 下一节 要说的 十字链表 类似于这种结