图的储存方式之邻接链表

邻接表

邻接表是一种顺序存储与链接存储相结合的存储方式。对于图中的每个顶点,将所有邻接于该顶点的顶点链成一个表,称为该顶点的表边(有向图称为出边表)。为了方便对所有边表头指针进行存取操作,可以采取顺序存储。存储边表头指针的数组和存储顶点信息的数组构成了邻接表的表头数组,称为顶点表。

C++:

struct ArcNode

{

         intadjvex;

         ArcNode*next;

 } ;

 templete<class DataType>

 struct VertexNode

 {

        DataType vertex;

        ArcNode* firstedge;

 };

在图的邻接链表中,容易解决以下事情:

1.      对于无向图,顶点的度等于边表中顶点的个数。对于有向图,顶点的出度等于出边表中顶点的个数,入度等于各顶点的出边表中该顶点的个数。为了确定入度,可以建立逆邻接表。

2.      判断两顶点之间是否存在边,只需要测试顶点的出边表中是否存在相应顶点的节点

3.      要找顶点所有的邻接点,只需遍历该顶点的出边表

算法:

template <class DataType>

 class ALGraph

 {

        public:

          ALGraph(DataType a[],int n,int e);//构造函数,nnodes,e edges

          ~ALGraph(){};

          void DFSTraverse(int v);

          void BFSTraverse(int v);

         private:

          VertexNode adjlist[MaxSize];   //存放顶点表的数组

          int vertexNum, arcNum;      //图的顶点数和边数

 };

构造函数:

 

 template <class DataType>

ALGraph<DataType>::ALGraph(DataTypea[],int n,int e)

 {

        vertexNum=n;arcNum=e;

         for(int i=0;i<vertexNum;i++)

         {

                   adjlist[i].vertex=a[i];

                   adjlist[i].firstedge=null;  

         }       

         for(intk=0;k<arcNum;k++)

         {

                   cin>>i>>j;

                   s=newArcnode;

                   s->next=adjlist[i].firstedge;

                   adjlist[i].firstedge=s;

         }

 };

深度优先遍历:

template <class DataType>

 voidALGraph<DataType>::DFSTraverse(int v)

 {

        cout<<adjlist[v].vertex;

        visited[v]=1;

        p=adjlist[v].firstedge;

        while (p!=null)

        {

                 j=p->adjvex;

                 if(visited[j]==0)DFSTraverse(j);

                 p=p->next;

          }

 }

广度优先遍历:

 template <class DataType>

 void ALGraph<DataType>::BFSTraverse(int v)

  {

       front=rear=-1;

       cout<<adjlist[v].vertex;

       visited[v]=1;

       Q[++rear]=v;

       while(front!=rear)

       {

                v=Q[++front];

                p=adjlist[v].firstarc;

                while(p!=null)

                {

                         j=p->adjvex;

                         if(visited[j]==0)

                         {

                                   cout<<adjlist[j].vertex;

                                   visited[j]=1;

                                   Q[++rear]=j;

                              }

                              p=p->next;

                     }

           }

  }

下面是使用Dijkstra算法以邻接链表的形式实现最短路径的示例代码: ```cpp #include <iostream> #include <vector> #include <queue> #include <limits.h> using namespace std; // 邻接链表中的边结构体 struct Edge { int to; // 目标节点 int weight; // 边权重 Edge(int t, int w): to(t), weight(w) {} }; // 邻接链表中的节点结构体 struct Node { int id; // 节点编号 int distance; // 起点到该节点的最短距离 vector<Edge> edges; // 与该节点相连的边 bool operator<(const Node& other) const { // 定义小于运算符,用于优先队列中 return distance > other.distance; } }; // 计算起点到所有节点的最短路径 vector<int> dijkstra(vector<Node>& graph, int start) { vector<int> distances(graph.size(), INT_MAX); // 起点到每个节点的最短距离 distances[start] = 0; // 起点到自己的距离为0 priority_queue<Node> pq; pq.push({start, 0, graph[start].edges}); while (!pq.empty()) { Node node = pq.top(); pq.pop(); if (distances[node.id] < node.distance) continue; // 优化1:如果已经处理过该节点,则忽略 distances[node.id] = node.distance; for (Edge edge : node.edges) { int newDist = node.distance + edge.weight; if (newDist < distances[edge.to]) { pq.push({edge.to, newDist, graph[edge.to].edges}); distances[edge.to] = newDist; } } } return distances; } int main() { int n, m; cin >> n >> m; vector<Node> graph(n); for (int i = 0; i < m; i++) { int u, v, w; cin >> u >> v >> w; graph[u].edges.push_back({v, w}); graph[v].edges.push_back({u, w}); } vector<int> distances = dijkstra(graph, 0); for (int i = 0; i < n; i++) { cout << "Distance from 0 to " << i << " is " << distances[i] << endl; } return 0; } ``` 在上述代码中,我们首先定义了邻接链表中的边和节点结构体,然后实现了计算起点到所有节点的最短路径的dijkstra函数。在函数中,我们使用一个优先队列来保存待处理的节点,并根据节点与起点的距离从小到大排序。在每次处理队首节点时,我们更新与该节点相连的所有节点的最短距离,并将它们加入优先队列中。在处理完所有节点后,我们返回起点到所有节点的最短距离。 在main函数中,我们首先读取输入的节点数量和边数量,并根据输入构造邻接链表。然后调用dijkstra函数,计算起点到所有节点的最短距离,并输出结果。 需要注意的是,由于STL中的优先队列使用堆实现,每次插入和删除元素的时间复杂度为O(log n),因此总时间复杂度为O((m + n) log n),其中m为边数,n为节点数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值