重学数据结构系列之——图的储存
2016-04-09 11:41
501 查看
1.什么是图
比如说我们的关系网络,就来微信来说,我们把用户看成是一个点,是好友的我们就把这两个点连起来。如下面的就是一个简单的图
2.图的分类
有向图和无向图,上图就是无向图,有向图是单向的,边用箭头来表示,如下:3.图的常用概念
顶点:就是那些点咯边:就是连接两个顶点的线,分为有向边和无线边
下面一般是指有向图
入度:该顶点有多少个箭头指着
出度:该顶点有多少条边箭头指着别人
顶点的度为入度与出度之和
3.图一般的储存方式
邻接矩阵和邻接表4.邻接矩阵储存的实现
其实就是用一个二维数组来储存,比如说是二维数组mat,mat[1][2]=1 ,就说明编号为1,2的两个顶点有边(这里编号从0开始)#include <iostream> #include <cstring> using namespace std; class Graph{ private: int **mat; //邻接矩阵,其实就是二维数组 int n; //顶点个数 public: Graph(int input_n){ n= input_n; //先分配n个int*的指针,再对每个指针再循环分配 mat = new int* ; for (int i = 0; i < n; i++) { mat[i] = new int ; //将内存中mat[i]的sizeof(int)*n个字节的内容全部设置为那个字符的ASCII值(这里的字符好似0) //它是对较大的结构体或数组进行清零操作的一种最快方法 memset(mat[i], 0, sizeof(int)*n);//Sets buffers to a specified character. } } ~Graph(){ //析构时注意先析构里面的,再外层的 for (int i = 0; i < n; i++) { delete[] mat[i]; } delete[] mat; } //插入边,直接将对于的位置置为1就可以了 void insert(int x, int y){ mat[x][y] = 1; } //输出邻接矩阵 void output(){ for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { cout<<mat[i][j]<<" "; } cout<<endl; } } }; int main(){ //n:顶点个数 m:有向边个数 //x,y: 表示插入一条x连向y的有向边 int n, m, x, y; cin >> n >> m; Graph g(n); for (int i = 0; i< m; i++) { cin >> x >> y; g.insert(x, y); } g.output(); return 0; }
对memset的理解: 通过调试,可以看到内存的地址的值全都变成了00000000,因为int是四个字节嘛,那int指针也是。
运行结果:
5.邻接表的储存实现
#include <iostream> using namespace std; //链表结点 class LinkedListNode{ public: //vertex:链表结点的值 int vertex; //指向下一个结点的指针 LinkedListNode *next; LinkedListNode(int vertex_input){ vertex = vertex_input; next = NULL; } }; //链表 class LinkedList{ public: LinkedListNode *head; LinkedList(){ head = NULL; } ~LinkedList(){ //顺着链析构 while (head != NULL) { LinkedListNode *delete_node = head; head = head->next; delete delete_node; } } //插入函数,这里直接插到头的前面了 void insert(int vertex){ LinkedListNode *node = new LinkedListNode(vertex); node->next = head; head = node; } }; //图 class Graph{ private: //储存链表的指针 LinkedList *edges; //n:顶点数目 int n; public: Graph(int input_n){ n = input_n; edges = new LinkedList ; } ~Graph(){ delete[] edges; } //插入就调用链表的插入 void insert(int x, int y) { edges[x].insert(y); } //循环输出每个链表的每个结点的值即可 void output() { for (int i = 0; i < n; i++) { cout<<i<<":"; //auto 是 C++11 的新特性,在定义变量时无需指定类型,编译器会通过类型推导得到实际的类型 //但我用vc++6.0,所以不支持 //for (auto* j = edges[i].head; j != NULL; j = j->next) { for (LinkedListNode* j = edges[i].head; j != NULL; j = j->next) { cout<<j->vertex<<" "; } cout<<endl; } } }; int main(){ int n, m, x, y; cin >> n >> m; Graph g(n); for (int i = 0; i < m; ++i) { cin >> x >> y; g.insert(x, y); } g.output(); return 0; }
运行结果:(可以看到结果非常直观,那个顶点有没有指向谁的边都一眼看出来)
相关文章推荐
- 时间复杂度和空间复杂度[数据结构]
- 数据结构--二叉树的线索化
- 【数据结构】FibonacciHeap 斐波那契堆(更新时间:2016-04-07)
- js--数据结构--树
- 数据结构-线性表的顺序结构
- 数据结构杂谈(一)浅谈基本排序算法
- PostgreSQL异步客户端(并模拟redis 数据结构)
- [Java8 Collection源码+算法+数据结构]-List(二)
- 数据结构——树
- 数据结构(线段树):BZOJ 1018: [SHOI2008]堵塞的交通traffic
- 数据结构实用概念
- 【学习笔记----数据结构07-队列】
- 【学习笔记----数据结构06-栈的应用】
- 数据结构-堆
- 【学习笔记----数据结构05-栈与队列】
- 【学习笔记----数据结构04-单循环链表】
- 位运算-Number of 1 Bits(求一个十进制数字,它的二进制表示中有多少个 1(bit))
- 【学习笔记----数据结构03--线性链表】
- 数组分段查找
- 栈-Min Stack(实现一个栈,用常数级时间找出栈中的最小值)