图----邻接表

来源:互联网 发布:跟知乎类似的网站 编辑:程序博客网 时间:2024/06/13 21:09

无向图的实现
要求:基于邻接表实现图的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 ADTprivate:  void operator =(const List&) {}      // Protect assignment  List(const List&) {}           // Protect copy constructorpublic:  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 GRAPHtemplate <typename VertexType>class Graph {private:  void operator =(const Graph&) {}     // Protect assignment  Graph(const Graph&) {}         // Protect copy constructorpublic:  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

原创粉丝点击