无向图的实现
要求:基于邻接表实现图的ADT,以及图的各种基本操作。
一、邻接表
数组与指针结合的存储方式。
1.图中的每一个顶点一维数组存储,在顶点数组中还需有指向第一个邻接点的指针。
2.图中每个顶点和他的所有的邻接点构成一个线性表。
如下图即为一个无向图的邻接表表示法:
就上图建立一个邻接表。
1)建立一个一维数组储存顶点值。
1)有多少个顶点就要建立多少条单链表。本图需要建立4条单链表。注:每个单链表的第一个元素即为该顶点本身。
V0->v1->v2->v3
v1->v0->v2
v2->v0->v1->v3
v3->v0->v2
2)在实际中存储的单链表应为每个顶点元素在数组中的下标。
带权值的有向图:
二、数据结构
1.顶点类ADT
template <typename E> class Link {
public:
E element; // Value for this node
Link *next; // Pointer to next node in list
// Constructors
Link(const E& elemval, Link* nextval =NULL)
{ element = elemval; next = nextval; }
Link(Link* nextval =NULL) { next = nextval; }
};
2、单链表类
template <typename E> class List { // List ADT
private:
void operator =(const List&) {} // Protect assignment
List(const List&) {} // Protect copy constructor
public:
List() {} // Default constructor
virtual ~List() {} // Base destructor
// Clear contents from the list, to make it empty.
virtual void clear() = 0;
// Insert an element at the current location.
// item: The element to be inserted
virtual void insert(const E& item) = 0;
// Append an element at the end of the list.
// item: The element to be appended.
virtual void append(const E& item) = 0;
// Remove and return the current element.
// Return: the element that was removed.
virtual E remove() = 0;
// Set the current position to the start of the list
virtual void moveToStart() = 0;
// Set the current position to the end of the list
virtual void moveToEnd() = 0;
// Move the current position one step left. No change
// if already at beginning.
virtual void prev() = 0;
// Move the current position one step right. No change
// if already at end.
virtual void next() = 0;
// Return: The number of elements in the list.
virtual int length() const = 0;
// Return: The position of the current element.
virtual int currPos() const = 0;
// Set current position.
// pos: The position to make current.
virtual void moveToPos(int pos) = 0;
// Return: The current element.
virtual const E& getValue() const = 0;
};
3、图ADT
#ifndef GRAPH
#define GRAPH
template <typename VertexType>
class Graph {
private:
void operator =(const Graph&) {} // Protect assignment
Graph(const Graph&) {} // Protect copy constructor
public:
Graph() {} // Default constructor
virtual ~Graph() {} // Base destructor
// Initialize a graph of n vertices
virtual void Init(int n) =0;
// Return: the number of vertices and edges
virtual int n() =0;
virtual int e() =0;
// Return v's first neighbor
virtual int first(int v) =0;
// Return v's next neighbor
virtual int next(int v, int w) =0;
//设置图的类型(有向图或无向图)
virtual void setType(bool flag)=0;
//获取图的类型
virtual bool getType()=0;
//找到(包含实际信息的)顶点在图中的位置
virtual int locateVex(VertexType u) =0;
//返回某个顶点的值(实际信息)
virtual VertexType getVex(int v)=0;
//给某个顶点赋值
virtual void putVex(int v,VertexType value) =0;
// Set the weight for an edge
virtual void setEdge(int v1, int v2, int wght) =0;
// Delete an edge
virtual void delEdge(int v1, int v2) =0;
// Determine if an edge is in the graph
virtual bool isEdge(int i, int j) =0;
// Return an edge's weight
virtual int weight(int v1, int v2) =0;
// Get and Set the mark value for a vertex
virtual int getMark(int v) =0;
virtual void setMark(int v, int val) =0;
};
#endif
三、构造图
char* getl(char* buffer, int n, FILE* fid) {
char* ptr;
ptr = fgets(buffer, n, fid);
while ((ptr != NULL) && (buffer[0] == '#'))
ptr = fgets(buffer, n, fid);
return ptr;
}
/*
构建图
*/
//template <typename GType>
Graph<string>* createGraph( FILE* fid) {
char buffer[LINELEN+1]; // Line buffer for reading
int i, v1, v2, dist;
/*【读取顶点个数】 */
if (getl(buffer, LINELEN, fid) == NULL) // Unable to get number of vertices
{ cout << "Unable to read number of vertices\n";
return NULL;
}
int num=atoi(buffer);
/*【建图初始化】 */
Graph<string>* G = new Graphl<string>(num);
/*【读取图的顶点信息并存储】 */
if (getl(buffer, LINELEN, fid) == NULL) // Unable to get graph type
{ cout << "Unable to read info of vertices\n";
return NULL ;
}
char* cbuff=buffer;
string ver=strtok(cbuff," ");//空格分割各顶点信息
//存储前n-1个
for(i=0;i<num-1;i++){
G->putVex(i,ver);//存储顶点信息
ver=strtok(NULL," ");
}
//最后一个顶点信息之后的字符可能是\t之类的字符故不能和上面一样
//直接用空格分割
int k=0;
while(ver[k]>=33&&ver[k]<=126){
k++;
}
ver=ver.substr(0,k);//获取最后一个顶点信息
G->putVex(i,ver);//存储顶点信息
/*【读取图的类型】 */
if (getl(buffer, LINELEN, fid) == NULL) // Unable to get graph type
{ cout << "Unable to read graph type\n";
return NULL ;
}
if (buffer[0] == 'U')//无向图
G->setType(true);//undirected = true;
else if (buffer[0] == 'D')//有向图
G->setType(false);//undirected = false;
else {
cout << "Bad graph type: |" << buffer << "|\n";
return NULL;
}
/*【读取边数和边】 */
if (getl(buffer, LINELEN, fid) == NULL) // Unable to get graph type
{ cout << "Unable to read num of edges\n";
return NULL ;
}
int num_edge=atoi(buffer);
for(int m=0;m<num_edge;m++){
getl(buffer, LINELEN, fid);
string sbuff=buffer;
string tvalue;
int loc1=sbuff.find(' ');//找到第一个分割空格的位置
tvalue=sbuff.substr(0,loc1);//读取第一个顶点信息到tvalue
//cout<<"第一个顶点" <<tvalue<<endl;
//找到第一个顶点在图中的位置
v1 = G->locateVex(tvalue);
int loc2=sbuff.find(' ',loc1+1);//找第二个分割空格的位置
tvalue=sbuff.substr(loc1+1,loc2-loc1-1);//读取第二个顶点信息到tvalue
//cout<<"第二个顶点" <<tvalue<<endl;
//找到第二个顶点在图中的位置
v2 = G->locateVex(tvalue);
//获取dist边权值
i=loc2+1;
dist=atoi(&buffer[i]);
//cout<<"dist="<<dist<<endl;
//存储边
G->setEdge(v1,v2,dist);
}
return G;
}
最后:我只是一只勤劳的搬运工,感谢学长学姐的源码,还有。。。。http://blog.csdn.net/jnu_simba/article/details/8866844