C Assignment2 知识总结

任务:用户输入点的个数,然后输入哪些点之间有边。通过这些信息找用户输入的某两个点之间的最短路径。注:本例中图是undirected。所以如果用户specify一条边<2,8>,则<8,2>这条边也要加进去。(2,8代表点的名字)

方法:用adjacency list来表示图,用广度优先搜索(BFS)来找最短路径。(为何选adjacency list,详见algorithm design这本书还有introduction to algorithm这本书)

1. 关于Input

用getchar()一个字符一个字符读用户输入,同时将每个字符存入一个字符串。判断是否到了EOF(通常被定义为-1)的时候,应用int inputCom; 然后 while((inputCom = getchar()) != EOF)。 

2.字符转数字

用atoi。包含在头文件<stdlib.h>中。比如用户输入V 15,这个本来存到了一个字符串中。现在我想把15提出来转化成数字,就先把字符'1'和'5'存到一个char的字符串中,比如叫char token; 然后int n = atoi(token); 即可。

3.数据结构

Adjacency list:图片来自Introduction to Algorithm:


最左边的竖着的那列1-5我们用结构体数组来代替,结构体叫list,比如结构体数组声明为:list adjarr[SIZE](size是预定义的常量)。结构体数组的第一个元素(adjarr[0])表示的是点0(上图的点1)(在本次assignment中是点0),这个结构体中含有一个node* 类型的指针first(用来给每一行的列表添加元素,并且能够知道是第几行,用adjarr[i]来确定,i是几就是第几行:adjarr[i].first就是第i行的first指针)(还要注意,结构体数组的每个元素都必须初始化,让first指向NULL,不然后面可能出问题)。后面的node是与点1有边的node,是用另一种结构体类型表示,这个结构体类型叫node,包含一个v_no表示点的名字,还有一个node*类型的指针next用于构造链表。 所以上图中的第一行的1相当于一个空壳,只是标记一下现在是在说点1。后面的2和5,才是实实在在的node。2和5是一个单链表。

//For adjacency list
typedef struct node{
	int v_no;
	struct node *next;
}node; 


typedef struct list{
	//int count;
	struct node *first;
}list;


然后在实现BFS查找最短路径的时候用的也是这个路子,但是不能在上述的已经构造好的adjacency list上直接进行操作,这样会破坏这个list,然后用户如果再接着输入s来查找另一条最短路径的时候就不行了。所以需要重新构造一个类似的东西。 在应用BFS的过程中,实际上在构造一个BFS tree,把不必要的边都cut掉,最后的tree中从某点到某点的shortest path只有一条。 我们定义另一个结构体数组叫layerarr[SIZE]; 每一个元素代表的是每一个layer。然后每个layer中的treeNode是与他上一层的点之间有边的点,每一个layer的treenode连起来也是一个链表。只不过在treeNode这个结构体中多加了一个指针叫treeNode* up;,用来找他上一层的点。这样就能连出一条最短路径了。

//For shortest path(BFS tree)
typedef struct treeNode{
	int treeNode_no;
	struct treeNode *next;
	struct treeNode *up;
}treeNode;

typedef struct layer{
	struct treeNode *first;
	int length;
}layer;


注:BFS算法的伪代码见Algorithm design这本书。

4.关于指针和malloc分配空间,free释放空间。

每当有一个新的node需要链接在链表上的时候,都要分配个空间给他。用malloc,最后不用的时候,要用free(node)释放掉。这里还有一个tricky的地方是比如在构造BFS tree的时候,我添加第一个根 treenode的时候,可以先treeNode* treenode = (treeNode*)malloc(sizeof(treeNode)); 然后当后面又要添加treeNode的时候,可以treenode = (treeNode*)malloc(sizeof(treeNode));多分配块空间出来就行了,不用再重新用treeNode* 声明一遍。 还有一个地方是我们可能需要借助别的指针来定位链表中的node。这个”别的指针“不用分配空间给他,直接node* temp;就好,因为他不是个结构体,只是一个结构体的指针,用来指东西就行了。

当释放空间的时候,需要把之前开过的每一块空间都free掉。可以定义两个新的指针node* temp; 和node* temp1。temp用来指向起始节点,然后让temp1 = temp;,temp1开始遍历,找到一个就free一个掉,free完再指向NULL(详见代码),然后temp再指向下一个adjarr(或者layerarr)元素的first,再让temp1去遍历+free。


另附:

1.关于char、char*、char**:http://blog.sina.com.cn/s/blog_65db99840100lwhs.html

2.这里有一个graph的implementation in C,其中包含adjacency list:http://simplestcodings.blogspot.ca/2013/09/graphs.html

3.另一个adjacency list的实现:http://iamsoftwareengineer.blogspot.ca/2012/06/c-graph-implementation-with-adjacency.html

4. Makefile:http://blog.csdn.net/koches/article/details/7609361,http://bbs.csdn.net/topics/10040739(只有一个source文件),http://www.chinaunix.net/old_jh/23/408225.html



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值