1. 程式人生 > >圖的幾種儲存方式

圖的幾種儲存方式

之前幾天把資料結構扔在一邊,在看離散數學的圖論部分,看了大部分,最後還是覺得純數學的,有一些可能現在我剛接觸圖還不會覺得有什麼用,所以就選擇性的跳過一些,現在也決定先放下書,回到資料結構上,開始圖的部分的學習。

圖的儲存通用的儲存方式有鄰接矩陣表示法、鄰接表表示法。為方便有向圖的頂點的入度與出度的計算,有 有向圖的十字連結串列表示法。為方便對無向圖的邊進行操作,有 無向圖的鄰接多重表表示法。

鄰接矩陣表示法應該算是最容易的一種表示法,一些簡單的操作比如查詢某頂點的指定鄰接點等很容易實現。

鄰接表表示在計算無向圖頂點的度很方便,計算有向圖的出度也很方便,但是計算入度的話就要從第一個結點開始遍歷,比較麻煩,這時採用逆鄰接表表示法的話,求有向圖的入度就會很方便,相應的,出度就不方便了,所以要根據需要選擇儲存結構。

如果在程式中要統計有向圖的度,那麼最好的方式就是採用十字連結串列的儲存方式。

鄰接多重表可以看作是對無向圖的鄰接矩陣的一種壓縮表示,當然這種結構在邊的操作上會方便很多,但是我現在還沒學到,所以暫時還不知道。下面是幾種表示方法的演算法實現,逆鄰接表和鄰接表的實現方式幾乎一樣,所以就不貼出來了。

#define MAX_VERTEX_NUM 20

#include<iostream>
#include<string>
using namespace std;

template<class T>
int Locate_Vex(T G,string x) //定位頂點位置
{
	for(int k=0;G.vexs[k]!=x;k++);
	return k;
}

//鄰接矩陣儲存圖
struct MGraph
{
	string vexs[MAX_VERTEX_NUM];//頂點陣列
	int arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; //鄰接矩陣
	int vexnum;//頂點數目
	int arcnum;//邊數目
};

void CreateUDN_MG(MGraph &G)
{
	//採用鄰接矩陣表示法,構造無向網
	cin>>G.vexnum>>G.arcnum;
	for(int i=0;i<G.vexnum;i++)
		cin>>vaxs[i];
	
	for(i=0;i<G.vexnum;i++)
		for(int j=0;j<G.vexnum;j++)
			G.arcs[i][j]=-1;
	//上面是初始化鄰接矩陣,-1表示兩點間邊的權值為無窮大
	
	for(int k=0;k<G.arcnum;k++)
	{
		string v1,v2;
		int w;
		cin>>v1>>v2>>w;
		i=Locate_Vex(G,v1);
		j=Locate_Vex(G,v2);
		while(i<0|| i>G.vexnum-1 || j<0 || j>G.vexnum-1)
		{
			cout<<"結點位置輸入錯誤,重新輸入: ";
			cin>>v1>>v2>>w;
			i=Locate_Vex(G,v1);
			j=Locate_Vex(G,v2);	
		}
		G.arcs[i][j]=w;
		G.arcs[j][i]=G.arcs[i][j]; //置對稱邊
	}
}

//鄰接表儲存圖
//表結點
struct ArcNode
{
	int adjvex; //弧所指向頂點的位置
	ArcNode *nextarc;// 指向下一條弧
};

//頭結點
typedef struct VNode
{
	string data;//頂點名
	ArcNode *firstarc;//指向第一條關聯頂點的弧
}AdjList[MAX_VERTEX_NUM];

struct ALGraph
{
	AdjList vertices;//頭結點陣列
	int vexnum;
	int arcnum;
};

void CreateDG_ALG(ALGraph &G)
{
	//採用鄰接表儲存表示,構造有向圖G
	string v1,v2;
	int i,j,k;
	cin>>G.arcnum>>G.vexnum;
	
	//構造頭結點陣列
	for(i=0;i<G.vexnum;i++)
	{
		cin>>G.vertices[i].data;
		G.vertices[i].firstarc=NULL;
	}

	//輸入各弧並構造鄰接表
	for(k=0;k<G.arcnum;k++)
	{
		cin>>v1>>v2;
		i=Locate_Vex(G,v1);
		j=Locate_Vex(G,v2);
		while(i<0|| i>G.vexnum-1 || j<0 || j>G.vexnum-1)
		{
			cout<<"結點位置輸入錯誤,重新輸入: ";
			cin>>v1>>v2;
			i=Locate_Vex(G,v1);
			j=Locate_Vex(G,v2);	
		}
	
		ArcNode *p=new ArcNode;
		p->adjvex=j;
		p->nextarc=NULL;
		p->nextarc=G.vertices[i].firstarc;
		G.vertices[i].firstarc=p;
	}
}

//十字連結串列方式儲存有向圖
//弧結點
struct ArcBox
{
	int tailvex,headvex;//弧結點頭尾結點位置
	ArcBox *hlink,*tlink;//弧頭和弧尾相同的弧的鏈域
};

//頂點結點
struct VexNode
{
	string data;
	ArcBox *firstin,*firstout;//頂點第一條入弧和出弧
};

struct OLGraph
{
	VexNode xlist[MAX_VERTEX_NUM];
	int vexnum;
	int arcnum;
};

void CreateDG_OLG(OLGraph &G)
{
	//採用十字連結串列儲存表示,構造有向圖G
	string v1,v2;
	int i,j,k;
	cin>>G.vexnum>>G.arcnum;
	for(i=0;i<G.vexnum;i++)
	{
		cin>>G.xlist[i].data;
		G.xlist[i].firstin=NULL;
		G.xlist[i].firstout=NULL;
	}
	for(k=0;k<G.arcnum;k++)
	{
		cin>>v1>>v2;
		i=Locate_Vex(G,v1);
		j=Locate_Vex(G,v2);
	
		while(i<0|| i>G.vexnum-1 || j<0 || j>G.vexnum-1)
		{
			cout<<"結點位置輸入錯誤,重新輸入: ";
			cin>>v1>>v2;
			i=Locate_Vex(G,v1);
			j=Locate_Vex(G,v2);	
		}		

		ArcBox *p=new ArcBox;
		p->tailvex=i;
		p->headvex=j;
		p->hlink=G.xlist[j].firstin;
		p->tlink=G.xlist[i].firstout;
		G.xlist[i].firstout=G.xlist[j].firstin=p;
	}
}
		
//鄰接多重表儲存
//邊結點
struct EBox
{
	int mark;//標誌域,指示該邊是否被訪問過(0:沒有 1:有)
	int ivex,jvex;//該邊關聯的兩個頂點的位置
	EBox *ilink,*jlink;//分別指向關聯這兩個頂點的下一條邊
};

//頂點結點
struct VexBox
{
	string data;
	EBox *firstedge;//指向第一條關聯該結點的邊
};

struct AMLGraph
{
	VexBox adjmulist[MAX_VERTEX_NUM];
	int vexnum;
	int arcnum;
};

void CreateUDG_AML(AMLGraph &G)
{
	//用鄰接多重表儲存,構造無向圖G
	string v1,v2;
	int i,j,k;
	cin>>G.vexnum>>G.arcnum;
	for(i=0;i<G.vexnum;i++)
	{
		cin>>G.adjmulist[i].data;
		G.adjmulist[i].firstedge=NULL;
	}

	for(k=0;k<G.arcnum;k++)
	{
		cin>>v1>>v2;
		i=Locate_Vex(G,v1);
		j=Locate_Vex(G,v2);
		
		while(i<0|| i>G.vexnum-1 || j<0 || j>G.vexnum-1)
		{
			cout<<"結點位置輸入錯誤,重新輸入: ";
			cin>>v1>>v2;
			i=Locate_Vex(G,v1);
			j=Locate_Vex(G,v2);	
		}

		EBox *p=new EBox;
		p->ivex=i;
		p->jvex=j;
		p->ilink=G.adjmulist[i].firstedge;
		p->jlink=G.adjmulist[j].firstedge;
		p->mark=0;
		G.adjmulist[i].firstedge=G.adjmulist[j].firstedge=p;
	}
}