数据结构之图_Graph_List

来源:互联网 发布:java定义二维数组 编辑:程序博客网 时间:2024/06/07 16:32
#ifndef GRAPH_LIST_H_INCLUDED
#define GRAPH_LIST_H_INCLUDED
#include<iostream>
#include<queue>
#include<stack>
using std::cout;
using std::cin;
using std::endl;

struct Edge
{
 friend class Graph_List;
 Edge(int ver, int w, Edge* e = NULL){ VerAdj = ver; cost = w; link = e; }
 int VerAdj;/*链接顶点序列,从0开始编号*/
 int cost;/*边的权值*/
 Edge* link;/*指向下一个节点的指针*/

};

struct Vertex
{
 friend class Graph_List;
 int VerName;/*顶点的头指针*/
 Edge* adjacent;/*边链表的头指针*/
};


class Graph_List
{
private:
 Vertex *Head;/*顶点链表的头指针*/
 int graphsize;/*图中当前顶点的个数*/
 int MaxGraphSize;
public:
 Graph_List(int MaxSize = 100) :MaxGraphSize(MaxSize),Head(NULL){};
 ~Graph_List();
 void CreatGraph();/*图的构建*/
 int GetWeight(const int& v1, const int& v2);/*返回权值*/
 void InsertEdge(const int& v1, const int& v2);/*插入边*/
 void DeleEdge(const int& v1, const int& v2);/*删除边*/
 int GetFirstNeighbor(const int &v);/*顶点v的第一个链接顶点*/
 int GetNextNeighbor(const int& v1, const int& v2);/*顶点v的下一个个链接顶点*/
 void REDF(const int& v, int* visited);/*深度遍历的递归实现*/
 void DepthFirstSearch();/*深度遍历*/
 void BFS(const int& s);/*广度遍历*/
 void Show();/*测试函数,show图的边及顶点*/
 void DShortestPath(const int& v);/*Djkstra算法*/

};

void Graph_List::CreatGraph()
{
 int e;
 int from, to, weight;
 Head = new Vertex[MaxGraphSize];
 cout << "请输入顶点个数:";
 cin >> graphsize;
 for (int i = 0; i<graphsize; i++)
 {
  Head[i].VerName = i;
  Head[i].adjacent = NULL;
 }
 cout << "请输入边的条数:";
 cin >> e;
 for (int i = 0; i<e; i++)
 {
  cout << "请输入新边的始点,终点,和权值:";
  cin >> from >> to >> weight;
  Edge* p = new Edge(to, weight);
  Edge* q = Head[from].adjacent;
  if (q == NULL)
  {
   Head[from].adjacent = p;
  }
  else
  {
   while (q->link != NULL)
   {
    q = q->link;
   }
   q->link = p;

  }
 }

}

void Graph_List::Show()
{
 cout << "show:" << endl;
 for (int i = 0; i<graphsize; i++)
 {
  cout << Head[i].VerName;
  Edge* p = Head[i].adjacent;
  while (p)
  {
   cout << p->VerAdj;
   p = p->link;
  }
  cout << endl;
 }
}

Graph_List::~Graph_List()
{
 for (int i = 0; i<graphsize; i++)/*删除每个顶点的边链表*/
 {
  Edge* p = Head[i].adjacent;
  while (p != NULL)
  {
   Head[i].adjacent = p->link;
   delete p;/*每一次删除的都是第二个*/
   p = Head[i].adjacent;
  }
 }
 delete[] Head;
}

int Graph_List::GetWeight(const int& v1, const int& v2)
{
 if (v1<0 || v2<0)
 {
  return 0;
 }

 Edge *p = Head[v1].adjacent;
 while (p != NULL)
 {
  if (p->VerAdj == v2)
  {
   return p->cost;
  }
  p = p->link;
 }

 return 0;
}

void Graph_List::InsertEdge(const int& v1, const int& v2)
{
 if (v1<0 || v2<0)
 {
  cout << "图中无此顶点,不能插入边.";
  return;
 }
 Edge* p = Head[v1].adjacent;

 while (p->link != NULL)
 {
  if (p->VerAdj == v2)
  {
   cout << "次边已存在.";
   return;
  }
  p = p->link;
 }

 cout << "请输入边<" << v1 << "," << v2 << ">的权值:";
 int weight;
 cin >> weight;
 p->link = new Edge(v2, weight);
 cout << "成功插入边<" << v1 << "," << v2 << ">." << endl;
}

void Graph_List::DeleEdge(const int& v1, const int& v2)
{
 if (v1<0 || v2<0)
 {
  std::cout << "顶点不在此图中.";
  return;
 }

 Edge* p = Head[v1].adjacent;
 while (p != NULL)
 {
  if (p == Head[v1].adjacent && (p->VerAdj == v2))
  {       /*第一条边为目标边*/
   //  std::cout<<"此边已存在.";
   Head[v1].adjacent = p->link;
   delete p;
   std::cout << "<" << v1 << "," << v2 << ">已经删除." << std::endl;

  }
  else if (p->link != NULL && (p->link->VerAdj == v2))
  {
   /*中间的一条边为目标边*/

   // std::cout<<"此边已存在.";
   Edge *temp = p->link;
   p->link = temp->link;
   delete temp;
   std::cout << "<" << v1 << "," << v2 << ">已经删除." << std::endl;

  }
  else if (p->VerAdj == v2)
  {/*目标边边为最后一条边*/
   std::cout << "此边已存在.";
   Edge *temp = p->link;
   p->link = temp->link;
   delete temp;
   std::cout << "<" << v1 << "," << v2 << ">已经删除." << std::endl;
  }
  p = p->link;
 }
}

int Graph_List::GetFirstNeighbor(const int &v)
{
 if (v<0)
 {
  std::cout << "顶点不在此图中.";
  return -1;
 }

 Edge* p = Head[v].adjacent;
 if (p != NULL)
 {
  return p->VerAdj;
 }
 return -1;
}

int Graph_List::GetNextNeighbor(const int& v1, const int& v2)
{
 if (v1<0 || v2<0)
 {
  std::cout << "顶点不在此图中.";
  return -1;
 }
 Edge *p = Head[v1].adjacent;
 while (p->VerAdj != v2&&p != NULL)
  p = p->link;
 if (p == NULL)
  return -1;
 p = p->link;
 if (p == NULL)
 {
  return -1;
 }
 return p->VerAdj;
}

void Graph_List::DepthFirstSearch()
{
 int *visited = new int[graphsize];
 for (int k = 0; k<graphsize; k++)
  visited[k] = 0;
 REDF(0, visited);
 delete[] visited;
}

void Graph_List::REDF(const int& v, int* visited)
{
 std::cout << v << " ";
 visited[v] = 1;/*设置成为被访问*/
 int w = GetFirstNeighbor(v);
 while (w != -1)
 {
  if (!visited[w])
  {
   REDF(w, visited);
  }
  w = GetNextNeighbor(v, w);/*回溯,w为v的上一个顶点*/
 }

}

void Graph_List::BFS(const int& s)
{
 int* visited = new int[graphsize];
 for (int k = 0; k<graphsize; k++)
  visited[k] = 0;
 std::cout << s << " ";
 visited[s] = 1;
 std::queue<int> graphQueue;
 graphQueue.push(s);
 while (!graphQueue.empty())
 {
  int v = graphQueue.front();
  graphQueue.pop();
  int w = GetFirstNeighbor(v);
  while (w != -1)
  {
   if (!visited[w])
   {
    std::cout << w << " ";
    visited[w] = 1;
    graphQueue.push(w);
   }
   w = GetNextNeighbor(v, w);
  }
 }
 delete[] visited;

}

void Graph_List::DShortestPath(const int& v)
{
 /*     
 path[]记录v到i的最短路径上的顶点的i的前驱节点
 dist[]记录从v到i的最短路径
 辅助数组s[],数组的初值设为0,一旦顶点i访问,s[i]设置为1
 (1)设s为初始顶点,Ds=0
 (2)在为范文的顶点中选择Dv的最小顶点,访问v,另s[v]=1
 (3)一次考察v的连接顶点w,若Dv+weight(<v,w>)<Dv,则更新Dw的值,使Dw=Dv+weight(<v,w>)
 (4)重复2,3,直到所有的顶点都被访问完
 */

 //int v;
 int k, u;
 Edge*p;
 int max = 10000;
 int n = graphsize;
 int* path = new int[graphsize];
 int* dist = new int[graphsize];
 int* s = new int[graphsize];/*s数组记录是否被访问过*/
 for (int i = 0; i<n; i++)/*初始化数组*/
 {
  path[i] = -1;
  dist[i] = max;
  s[i] = 0;
 }
 dist[v] = 0; s[v] = 1;/*起始顶点标记为被访问*/
 p = Head[v].adjacent;
 u = v;/*u为即将被访问的顶点*/
 for (int j = 0; j<n; j++)
 {
  while (p != NULL)
  {
   /*修改u连接的顶点s[],path[],dist[]的值*/
   k = p->VerAdj;
   if (s[k] != 1 && dist[u] + p->cost<dist[k])
   {
    dist[k] = dist[u] + p->cost;
    path[k] = u;
   }
   p = p->link;
  }
 }

 int ldist = max;
 for (int i = 0; i<n; i++)
 {
  /*确定即将被访问的顶点u*/
  if (dist[i]>0 && dist[i]<ldist&&s[i] == 0)
  {
   ldist = dist[i];
   u = i;
  }
 }
 s[u] = 1;/*访问u*/
 p = Head[u].adjacent;
 for (int i = 0; i<n; i++)
  std::cout << path[i] << " ";
 for (int i = 0; i<n; i++)
  std::cout << dist[i] << " ";
 delete[] path;
 delete[] dist;
}

#endif
0 0