数据结构:图的实现--邻接表

                          图的实现:邻接表

当图中的边数较少时,用邻接表来实现图结构,则会浪费很多内存空间。因此,考虑另一种实现图结构的方法:邻接表。在邻接表中主要有两种节点结构体:

顶点节点


边节点


直接看代码

类定义

[cpp]  view plain copy
  1. #include<iostream>  
  2. #include<iomanip>  
  3. using namespace std;  
  4. //最大权值  
  5. #define MAXWEIGHT 100  
  6. //边节点  
  7. typedef struct edgenode_tag  
  8. {  
  9.     int adjvex;  //邻接点  
  10.     int weight;  //边的权值  
  11.     struct edgenode_tag *next;  
  12. }EdgeNode;  
  13. //顶点节点  
  14. typedef struct vertex_tag  
  15. {  
  16.     int vertex;   //顶点  
  17.     EdgeNode *next;  
  18. }Vertex;  
  19. class Graph  
  20. {  
  21. private:  
  22.     //是否带权  
  23.     bool isWeighted;  
  24.     //是否有向  
  25.     bool isDirected;  
  26.     //顶点数  
  27.     int numV;  
  28.     //边数  
  29.     int numE;  
  30.     //邻接表  
  31.     Vertex *adjList;  
  32. public:  
  33.     /* 
  34.     构造方法 
  35.     numV是顶点数,isWeighted是否带权值,isDirected是否有方向 
  36.     */  
  37.     Graph(int numV, bool isWeighted = falsebool isDirected = false);  
  38.     //建图  
  39.     void createGraph();  
  40.     //析构方法  
  41.     ~Graph();  
  42.     //获取顶点数  
  43.     int getVerNums()  
  44.     {return numV;}  
  45.     //获取边数  
  46.     int getEdgeNums()  
  47.     {return numE;}  
  48.     //插入边  
  49.     void insertEdge(int tail, int head, int weight = 1);  
  50.     void insertedge(int tail, int head, int weight);  
  51.     //设置指定边的权值  
  52.     void setEdgeWeight(int tail, int head, int weight);  
  53.     //打印邻接表  
  54.     void printAdjacentList();  
  55.     //检查输入  
  56.     bool check(int tail, int head, int weight = 1);  
  57. };  

类实现

[cpp]  view plain copy
  1. /* 
  2. 构造方法 
  3. numV是顶点数,isWeighted是否带权值,isDirected是否有方向 
  4. */  
  5. Graph::Graph(int numV, bool isWeighted, bool isDirected)  
  6. {  
  7.     while (numV <= 0)  
  8.     {  
  9.         cout << "输入的顶点数不正确!,重新输入 ";  
  10.         cin >> numV;  
  11.     }  
  12.     this->numV = numV;  
  13.     this->isWeighted = isWeighted;  
  14.     this->isDirected = isDirected;  
  15.     //边数初始化为0  
  16.     numE = 0;  
  17.     adjList = new Vertex[numV];  //指针数组  
  18.     for (int i = 0; i < numV; i++)  
  19.     {  
  20.         adjList[i].vertex = i;  
  21.         adjList[i].next = NULL;  
  22.     }  
  23. }  
  24. //建图  
  25. void Graph::createGraph()  
  26. {  
  27.     //用一个新的变量表示边数,numE的修改则留到insertedge()中  
  28.     int numEdge = 0;  
  29.     cout << "输入边数 ";  
  30.     while (cin >> numEdge && numEdge < 0)  
  31.         cout << "输入有误!,重新输入 ";  
  32.   
  33.     int i, j, w;  
  34.     if (!isWeighted)  //无权图  
  35.     {  
  36.         cout << "输入每条边的起点和终点:\n";  
  37.         for (int k = 0; k < numEdge; k++)  
  38.         {  
  39.             cin >> i >> j;  
  40.             while (!check(i, j))  
  41.             {  
  42.                 cout << "输入的边不对!重新输入\n";  
  43.                 cin >> i >> j;  
  44.             }  
  45.             insertEdge(i, j);  
  46.         }  
  47.     }  
  48.     else  //有权图  
  49.     {  
  50.         cout << "输入每条边的起点、终点和权值:\n";  
  51.         for (int k = 0; k < numEdge; k++)  
  52.         {  
  53.             cin >> i >> j >> w;  
  54.             while (!check(i, j, w))  
  55.             {  
  56.                 cout << "输入的边不对!重新输入\n";  
  57.                 cin >> i >> j >> w;  
  58.             }  
  59.             insertEdge(i, j, w);  
  60.         }  
  61.     }  
  62. }  
  63. //析构方法  
  64. Graph::~Graph()  
  65. {  
  66.     int i;  
  67.     EdgeNode *p, *q;  
  68.     for (i = 0; i < numV; i++)  
  69.     {  
  70.         if (adjList[i].next)  
  71.         {  
  72.             p = adjList[i].next;  
  73.             while (p)  
  74.             {  
  75.                 q = p->next;  
  76.                 delete p;  
  77.                 p = q;  
  78.             }  
  79.         }  
  80.     }  
  81.     delete[]adjList;  
  82. }  
  83. //设置指定边的权值  
  84. void Graph::setEdgeWeight(int tail, int head, int weight)  
  85. {  
  86.     if (!isWeighted)  //无权图  
  87.     {  
  88.         while (!check(tail, head))  
  89.         {  
  90.             cout << "输入的边不对!重新输入\n";  
  91.             cin >> tail >> head;  
  92.         }  
  93.         insertEdge(tail, head);  
  94.     }  
  95.     else  //有权图  
  96.     {  
  97.         while (!check(tail, head, weight))  
  98.         {  
  99.             cout << "输入的边不对!重新输入\n";  
  100.             cin >> tail >> head >> weight;  
  101.         }  
  102.         insertEdge(tail, head, weight);  
  103.     }  
  104. }  
  105. //插入边  
  106. void Graph::insertEdge(int vertex, int adjvex, int weight)  
  107. {  
  108.     insertedge(vertex, adjvex, weight);  
  109.     if (!isDirected)  //无向图  
  110.         insertedge(adjvex, vertex, weight);  
  111. }  
  112. void Graph::insertedge(int vertex, int adjvex, int weight)  
  113. {  
  114.     EdgeNode *p, *q, *r;  
  115.     p = q = r = NULL;  
  116.     if (adjList[vertex].next)   //非第一个节点  
  117.     {  
  118.         p = adjList[vertex].next;  
  119.         //移动p到合适位置  
  120.         while (p && (p->adjvex < adjvex))  
  121.         {  
  122.             q = p;  
  123.             p = p->next;  
  124.         }  
  125.         if (p && (p->adjvex == adjvex))  //修改已有边权值  
  126.             p->weight = weight;  
  127.         else  
  128.         {  
  129.             r = new EdgeNode;  
  130.             r->adjvex = adjvex;  
  131.             r->weight = weight;  
  132.             r->next = p;  
  133.             //当加入的新节点位于表的第一个位置  
  134.             if (adjList[vertex].next == p)  
  135.                 adjList[vertex].next = r;  
  136.             else  
  137.                 q->next = r;  
  138.             numE++;  
  139.         }  
  140.     }  
  141.     else  
  142.     {  
  143.         p = new EdgeNode;  
  144.         p->adjvex = adjvex;  
  145.         p->weight = weight;  
  146.         p->next = NULL;  
  147.         adjList[vertex].next = p;  
  148.         numE++;  
  149.     }  
  150. }  
  151. //输入检查  
  152. bool Graph::check(int tail, int head, int weight)  
  153. {  
  154.     if (tail >= 0 && tail < numV && head >= 0 && head < numV   
  155.         && weight > 0 && weight <= MAXWEIGHT)  
  156.         return true;  
  157.     else  
  158.         return false;  
  159. }  
  160. //打印邻接表  
  161. void Graph::printAdjacentList()  
  162. {  
  163.     int i;  
  164.     EdgeNode *edge = NULL;  
  165.     for (i = 0; i < numV; i++)  
  166.     {  
  167.         edge = adjList[i].next;  
  168.         if (edge) //为什么加一个if判断?跟后面的换行有关。若某顶点无邻接点(无边),则会空出一行  
  169.         {  
  170.             while (edge)  
  171.             {  
  172.                 cout << "w(" << i << "," << edge->adjvex << ")=" << edge->weight << "  ";  
  173.                 edge = edge->next;  
  174.             }  
  175.             cout << endl;  
  176.         }  
  177.     }  
  178. }  
主函数

[cpp]  view plain copy
  1. int main(void)  
  2. {  
  3.     cout << "******使用邻接表实现图结构***by David***" << endl;  
  4.     bool isDirected, isWeighted;  
  5.     int numV;  
  6.     cout << "建图" << endl;  
  7.     cout << "输入顶点数 ";  
  8.     cin >> numV;  
  9.     cout << "边是否带权值,0(不带) or 1(带) ";  
  10.     cin >> isWeighted;  
  11.     cout << "是否是有向图,0(无向) or 1(有向) ";  
  12.     cin >> isDirected;  
  13.     Graph graph(numV, isWeighted, isDirected);  
  14.     cout << "这是一个";  
  15.     isDirected ? cout << "有向、" : cout << "无向、";  
  16.     isWeighted ? cout << "有权图" << endl : cout << "无权图" << endl;  
  17.     graph.createGraph();  
  18.     cout << "打印邻接表" << endl;  
  19.     graph.printAdjacentList();  
  20.     cout << endl;  
  21.     int tail, head, weight;  
  22.     cout << "修改指定边的权值" << endl;  
  23.     if (isWeighted)  //针对有权图  
  24.     {  
  25.         cout << "输入边的起点、终点和权值 ";  
  26.         cin >> tail >> head >> weight;  
  27.         graph.setEdgeWeight(tail, head, weight);  
  28.     }  
  29.     else  //针对无权图  
  30.     {  
  31.         cout << "输入边的起点、终点 ";  
  32.         cin >> tail >> head;  
  33.         graph.setEdgeWeight(tail, head, 1);  
  34.     }  
  35.     cout << "修改成功!" << endl;  
  36.     cout << "打印邻接矩阵" << endl;  
  37.     graph.printAdjacentList();  
  38.     system("pause");  
  39.     return 0;  
  40. }  
运行


邻接表




完整代码下载:图的实现:邻接表


转载请注明出处,本文地址:http://blog.csdn.net/zhangxiangdavaid/article/details/38323593


若有所帮助,顶一个哦!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这是我的作业。。。。希望对各位有#include <stdio.h> #include <malloc.h> #include <stdlib.h> #define SIZE (xsize*ysize+1) //一系列全局变量便于传递参数 int *location,*way, xsize,ysize,firstx,firsty, noworder; int getnum (void);//取数函数,取数成功返回1,否则返回-1 int init (void); //初始化函数,申请数组空间,以及初始化数组, //申请成功返回1,否则返回-1 int play (void); //下棋函数,下棋成功返回1,否则返回-1 int back (void); //悔棋函数,悔棋成功返回1,否则返回-1 void print (void);//输出函数,顺序输出马踩的棋盘一维坐标 //////////////////////////// void main () { int canget,caninit,canplay,canback; do canget=getnum(); while(canget==-1); caninit=init(); if(caninit==-1) exit (0);//终止程序运行 for (;noworder<SIZE-1;) { if(way[location[noworder]]>0 && way[location[noworder]]<=8) { canplay=play(); if(canplay==-1) way[location[noworder]]++;//当前方法不可行,改变方法 } else { canback=back(); if(canback==-1) { printf("不可能遍历整个棋盘!\n"); getchar();getchar(); exit (0);//当程序不能再悔棋时终止程序运行 } else way[location[noworder]]++; //当前方法不可行,改变方法 } } if(noworder==SIZE-1)//已经遍历整个棋盘 print(); getchar();getchar(); } //////////////////////////// int getnum() { printf("输入棋盘规格(假定无0点)和入口坐标:\n"); printf("输入棋盘规格xsize="); scanf("%d",&xsize); printf("输入棋盘规格ysize="); scanf("%d",&ysize); printf("输入入口坐标x="); scanf("%d",&firstx); printf("输入入口坐标y="); scanf("%d",&firsty); if (firstx>xsize || firsty>ysize || firstx<=0 || firsty<=0 || xsize <3 || ysize<3) { printf("输入有误,重新输入:\n\n\a"); return -1; } else return 1; } //////////////////////////// int init (void) { location=(int *)malloc(sizeof(int)*SIZE); way=(int *)malloc(sizeof(int)*SIZE); if(location==NULL || way==NULL) { printf("系统申请内存空间失败!程序执行终止!\a"); return -1; } for(int i=0;i<SIZE;i++)//初始化数组 { way[i]=0; location[i]=0; } noworder=1; location[1]=(firsty-1)*xsize+firstx; way[location[1]]=1; return 1; } //////////////////////////// void print(void) { printf("\n\n可以遍历,顺序如下:\n\n"); for (int i=1;i<SIZE;i++) { printf("%3d-->",location[i]); printf("OK\n"); } } //////////////////////////// int play() { int x,y,nextlocation; //一维坐标值à二维坐标值 x=location[noworder] % xsize; if(x==0) x=xsize; y=(location[noworder]-x)/xsize+1; switch (way[location[noworder]]) { case 1 : x+=2;y-=1;break; case 2 : x+=2;y+=1;break; case 3 : x+=1;y+=2;break; case 4 : x-=1;y+=2;break; case 5 : x-=2;y+=1;break; case 6 : x-=2;y-=1;break; case 7 : x-=1;y-=2;break; case 8 : x+=1;y-=2;break; } nextlocation = xsize*(y-1)+x; if (x>xsize || y>ysize || x<=0 || y<=0 || way[nextlocation]!=0)//越界或重复 return -1; else//下棋 { noworder++; location[noworder] = nextlocation; way[location[noworder]]=1; return 1; } } //////////////////////////// int back (void) { if(noworder==1)//不能再悔棋,不能遍历 return -1; else { way[location[noworder]]=0;//注意不能搞错语句顺序 location[noworder]=0; noworder--; return 1; } }用

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值