图----邻接表

无向图的实现
要求:基于邻接表实现图的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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值