Longjingrap

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

1.学习总结(2分)

1.1图的思维导图

1.2 图结构学习体会

深度遍历

  • 深度优先遍历的策略就是首先访问第一个邻接结点,然后再以这个被访问的邻接结点作为初始结点,访问它的第一个邻接结点。总结起来可以这样说:每次都在访问完当前结点后首先访问当前结点的第一个邻接结点。

广度遍历

  • 访问图中的一个点之后,一次访问v的各个未曾访问过的邻接点,然后分别从这些邻接点出发,依次访问它们的邻接点,并且使“先被访问的顶点的邻接点”先于“后被访问的顶点的邻接点”被访问。所以广度遍历要用队列来完成。

Prim和Kruscal算法

  • Prim算法首先以一个结点作为最小生成树的初始结点,然后以迭代的方式找出最小生成树中各结点权重最小的边,并加到最小生成树中。(加入之后如果产生回路了就要跳过这条边,选择下一个结点。)当所有的结点都加入到最小生成树中后,就找出了这个连通图的最小生成树
  • Kruskal算法在找最小生成树结点之前,需要对权重从小到大进行排序。将排序好的权重边依次加入到最小生成树中,(如果加入时产生回路就跳过这条边,加入下一条边)。当所有的结点都加入到最小生成树中后,就找到了这个连通图的最小生成树。

Dijkstra算法

  • 算法思想:设G=(V,E)是一个带权有向图,把图中顶点集合V分成两组,第一组为已求出最短路径的顶点集合(用S表示,初始时S中只有一个源点,以后每求得一条最短路径 , 就将加入到集合S中,直到全部顶点都加入到S中,算法就结束了),第二组为其余未确定最短路径的顶点集合(用U表示),按最短路径长度的递增次序依次把第二组的顶点加入S中。在加入的过程中,总保持从源点v到S中各顶点的最短路径长度不大于从源点v到U中任何顶点的最短路径长度。此外,每个顶点对应一个距离,S中的顶点的距离就是从v到此顶点的最短路径长度,U中的顶点的距离,是从v到此顶点只包括S中的顶点为中间顶点的当前最短路径长度。

拓扑排序算法

  • 1.找到一个没有后继的顶点;2.从图中删除这个顶点,在列表中插入顶点的标记。 然后重复1和2,直到所有顶点都从图中删除,这时候列表显示的顶点顺序就是拓扑排序的结果了,有向图就不能使用拓扑排序。

2.PTA实验作业

2.1题目1:7-2 排座位

1.设计思路

建图,宾客的关系放到图中。
对visited[][]进行初始化为0
若friends[a][b]==1,则为朋友关系,直接输出“No problem”
定义一个变量flag=0;
将vitited中相应宾客的值置为1;
对宾客a,b进行VIS函数调用,类似于图的深度遍历
对a,b检查是否存在共同的朋友
存在,flag=1
不存在,则flag=0;
if(宾客是敌人关系){
存在共同朋友,输出"OK but..."
否则输出“No way”
}
else(不是朋友也不是敌人){
存在共同朋友,输出"No problem"
否则输出“OK”
}

2.代码截图

3.PTA提交列表说明

  • 一开始不小心将函数中(iy)便返回写成了(ix),导致falg的返回值错误,既只对了(friends[a][b]==1)直接输出的部分,朋友的朋友的情况判断错误。

题目二:7-3 六度空间

1.设计思路

先建图和对visited[]初始化为0
从顶点v=1开始对图进行广度遍历
将v进队列
while(队列不为空){
      将number置为队列头元素,删除队列头元素;
             遍历顶点i=0 to  i<N{
         若visited[i]==0且G[number][i]==1;
                  将i进队,visited[i]置为1,记录节点数,同时记录i的数值
                            }
}
       若访问到该层的最后一个节点
            层数加一,改变这一层访问的最后一个节点 
        层数达到6便结束,返回记录的节点数

2.代码截图

3.PTA提交列表说明

  • 忘记将进队的i的visited[i]置为1,导致节点数错误。格式错误是没把分子乘1.0,没能保留小数点后两位。

2.1题目1:7-4 公路村村通

1.设计思路

给G[][]和lowcost[]数组赋初值;
找出N-1个顶点  i=1 to i=N{
    在(V-U)中找出离U中最近的顶点
          用k记录最近顶点的编号
      累加顶点间最短路径的数值
      给lowcost[k]赋值-1,标记k已经加入U
             for j=1 to j=N
                  修改lowcost[]中的值
                }
        判断输入数据是否以保证畅通  
             不能则返回-1
                 否则返回最短路径的总和sum

2.代码截图

3.PTA提交列表说明

  • 这道题是用最小生成树中Prim()算法计算的,书中有类似代码,但一直写一直是部分正确,怎么改都是,去网上查了下代码,思路基本也一样,然后提交网上的代码就全对了,而自己的还不知道哪错了,然后根据网上对的代码一直改自己代码中认为错误的地方,在PTA上反复提交,找了半小时才发现是因为我给G[][]的赋的初值太小了,网上是999999,虽然知道错在哪里了,但还是一脸懵逼,为什么G[][]=999999能全对。。。。。。

.3.截图本周题目集的PTA最后排名

3.1 PTA排名

3.2 我的总分:2.5

4. 阅读代码

    #ifndef __GRAPH_H__
    #define __GRAPH_H__

    typedef struct graph *Graph;

    Graph graph_create(int n);
    void graph_destroy(Graph);
    void graph_add_edge(Graph, int source, int sink);
    int graph_vertex_count(Graph);
    int graph_edge_count(Graph);
    int graph_out_degree(Graph, int source);
    int graph_has_edge(Graph, int source, int sink);
    void graph_foreach(Graph g, int source,
        void (*f)(Graph g, int source, int sink, void *data),
        void *data);

    #endif
    /* basic directed graph type */
    /* the implementation uses adjacency lists
     * represented as variable-length arrays */
    /* these arrays may or may not be sorted: if one gets long enough
    /* and you call graph_has_edge on its source, it will be */
    struct graph {
       int n;                                                                              /* number of vertices */
       int m;                                                                              /* number of edges */
       struct successors {
              int d;                                                                       /* number of successors */
              int len;                                                                  /* number of slots in array */
              char is_sorted;                                                        /* true if list is already sorted */
              int list[1];                                                           
                                                                                              /* actual list of successors */
       } *alist[1];
};
/* create a new graph with n vertices labeled 0..n-1 and no edges */
Graph
graph_create(int n)
{
       Graph g;
       int i;
       g = malloc(sizeof(struct graph) + sizeof(struct successors *) * (n-1));
       assert(g);
       g->n = n;
       g->m = 0;
       for(i = 0; i < n; i++) {
              g->alist[i] = malloc(sizeof(struct successors));
              assert(g->alist[i]);
              g->alist[i]->d = 0;
              g->alist[i]->len = 1;
              g->alist[i]->is_sorted= 1;
       }
       return g;
}
/* free all space used by graph */
void
graph_destroy(Graph g)
{
       int i;
       for(i = 0; i < g->n; i++) free(g->alist[i]);
       free(g);
}
/* add an edge to an existing graph */
void
graph_add_edge(Graph g, int u, int v)
{
       assert(u >= 0);
       assert(u < g->n);
       assert(v >= 0);
       assert(v < g->n);
       /* do we need to grow the list? */
       while(g->alist[u]->d >= g->alist[u]->len) {
              g->alist[u]->len *= 2;
              g->alist[u] =
                     realloc(g->alist[u], 
                            sizeof(struct successors) + sizeof(int) * (g->alist[u]->len - 1));
       }
       /* now add the new sink */
       g->alist[u]->list[g->alist[u]->d++] = v;
       g->alist[u]->is_sorted = 0;
       /* bump edge count */
       g->m++;
}
/* return the number of vertices in the graph */
int
graph_vertex_count(Graph g)
{
       return g->n;
}
/* return the number of vertices in the graph */
int
graph_edge_count(Graph g)
{
       return g->m;
}
/* return the out-degree of a vertex */
int
graph_out_degree(Graph g, int source)
{
       assert(source >= 0);
       assert(source < g->n);

       return g->alist[source]->d;
}
/* when we are willing to call bsearch */
#define BSEARCH_THRESHOLD (10)
static int
intcmp(const void *a, const void *b)
{
       return *((const int *) a) - *((const int *) b);
}
/* return 1 if edge (source, sink) exists), 0 otherwise */
int
graph_has_edge(Graph g, int source, int sink)
{
       int i;
       assert(source >= 0);
       assert(source < g->n);
       assert(sink >= 0);
       assert(sink < g->n);
       if(graph_out_degree(g, source) >= BSEARCH_THRESHOLD) {
              /* make sure it is sorted */
              if(! g->alist[source]->is_sorted) {
                     qsort(g->alist[source]->list,
                                   g->alist[source]->d,
                                   sizeof(int),
                                   intcmp);
              }             
              /* call bsearch to do binary search for us */
              return 
                     bsearch(&sink,
                                   g->alist[source]->list,
                                   g->alist[source]->d,
                                   sizeof(int),
                                   intcmp)
                     != 0;
       } else {
              /* just do a simple linear search */
              /* we could call lfind for this, but why bother? */
              for(i = 0; i < g->alist[source]->d; i++) {
                     if(g->alist[source]->list[i] == sink) return 1;
              }
              /* else */
              return 0;
       }
}
/* invoke f on all edges (u,v) with source u */
/* supplying data as final parameter to f */
void
graph_foreach(Graph g, int source,
       void (*f)(Graph g, int source, int sink, void *data),
       void *data)
{
       int i;
       assert(source >= 0);
       assert(source < g->n);
       for(i = 0; i < g->alist[source]->d; i++) {
              f(g, source, g->alist[source]->list[i], data);
       }
}
  • 这段代码有动态分配的数组来存放邻接节点,这是一份PineWiki网站里面提供的一份图的表示的代码,实现的很优美吧?动态分配数组,长度可以扩展,既不浪费空间,又不会带来性能损失,它告诉我们鱼和熊掌也是可以兼得的。

5. 代码Git提交记录截图

posted on 2018-06-17 21:33  Longjingrap  阅读(148)  评论(0编辑  收藏  举报