zoukankan      html  css  js  c++  java
  • 算法导论22.1图的表示 练习总结 (转载)

    转自:http://blog.csdn.net/chan15/article/details/49620221

    22.1-1 给定有向图的邻接链表,需要多长时间才能计算出每个结点的出度(发出的边的条数)?多长时间才能计算出每个结点的入度(进入的边的条数)?

    ANSWER:① 出度:O(V+E),因为计算 n 个结点的链表长度为 O(n),所以需要计算 O(V) 个链表长度时间为 O(V+E)。② 入度:O(V+E),同理。

    22.1-2 给定一棵有 7 个结点的完全二叉树的邻接链表,请给出等价的邻接矩阵表示。这里假设结点的编号为从 1~7。

    ANSWER:


    22.1-3 有向图 G = (V,E) 的转置是图 G^T = (V,E^T),这里 E^T = {(v,u) ∈ V * V : (u,v) ∈ E}。因此,图 G^T 就是将有向图 G 中所有边的方向反过来而形成的图。对于邻接链表和邻接矩阵两种表示方法,请给出从图G 计算出 G^T 的有效算法,并分析算法的运行时间。

    ANSWER:

    邻接链表:用 O(V+E) 时间遍历链表,获取所有结点。对结点为 i 的链表,将结点 i 放在以该链表的数组 Adj 为结点的链表中;时间为 O(V+E)。

    邻接矩阵:返回原矩阵的转置,时间为 O(V^2)。

    22.1-4 给定多图 G = (V,E) 的邻接链表(多图允许重复边和自循环边的图),请给出一个时间为 O(V+E) 的算法,用来计算该图的“等价”无向图 G‘ = (V,E') 的邻接链表表示。这里 E' 是将 E 中的冗余边和自循环边删除后余下的边。删除冗余边指的是将两个节点之间的多条边替换为一条边。

    ANSWER:遍历多图 G 的每个链表,并复制链表;若链表的 Adj 元素与链表头节点重复,则不复制该元素;若链表中 Adj 元素重复多次出现,则只复制一次。复制完成后,新的邻接链表若出现只有头结点的链表,则删除该链表。

    22.1-5 有向图 G = (V,E) 的平方图是图 G2 = (V,E2),这里,边 (u, v) ∈ E2 当且仅当图 G 包含一条最多由两条边构成的从 u 到 v 的路径。请给出一个有效算法来计算图 G 的平方图 G2。这里图 G 既可以以邻接链表表示,也可以以邻接矩阵表示。请分析算法的运行时间。

    ANSWER:邻接矩阵,时间复杂度:O(V^3)。

    for i = 1 to n
        for j = 1 to n
            if G[i][j] == 1
                G2[i][j] = 1
            else
                for k = 1 to n
                    if G[i][k] == 1 and G[k][j] == 1
                        G2[i][j] = 1
                    else
                        G2[i][j] = 0
    View Code

    22.1-6 多数以邻接矩阵作为输入的图算法的运行时间为 Ω(V^2),但也有例外。给定图 G 的邻接矩阵表示,请给出一个 O(V) 时间的算法来判断有向图 G 是否存在一个通用汇点。通用汇点指的是入度为 |V| - 1 但出度为 0 的结点。

    ANSWER:若结点 i 满足题意,则在邻接矩阵中,第 i 行全为 0,第 i 列全为 1(第 i 行第 i 列除外)。

    按结点编号由大到小(从邻接矩阵右下角向左上方向)检测,当检测结点 i 时,若结点 x 与结点 i 的关系满足题意(即 x 指向 i,i 不指向 x),则 x 一定不满足题意。所以,向上检测某结点的同时,也在检测其它结点。执行一次 while 循环后筛选出唯一一个可能成立的 ans 值,再用 O(V) 时间检测其是否成立。

    伪代码:

    SEARCH_USPOINT(G):
        i = v
        j = 1
        while i - j > 0
            ans = v
            if G[i][i-j] == 0 and G[i-j][i] == 1    //结点入度加 1,出度为 0
                j = j + 1
            else    //检测下一结点
                i = i - j
                ans = i
                j = 1
        if CHECK(ans)
            return true
        else
            return false
    
    CHECK(ans):
        for i = 1 to V
            if G[i][ans] != 1 or G[ans][i] != 0
                return false
            else
                return true
    View Code

    22.1-7 有向无环图 G = (V, E) 的关联矩阵是一个满足下述条件的 |V| * |E| 矩阵 B = (bij):

    bij = -1 (如果边 j 从结点 i 发出);1 (如果边 j 进入结点 i);0 (其他)。

    请说明矩阵乘积 B*B^T 里的每一个元素代表什么意思。这里 B^T 是矩阵 B 的转置。

    ANSWER:

    当 i = j 时,B*B^T(i, j) = i 的入度 + i 的出度。

    当 i ≠ j 时,B*B^T(i, j) = (i → k → j) 边数 + (i ← k ← j) 边数 - (i ← k → j) 边数 - (i → k ← j)边数;k ∈[1, V]。

    22.1-8 假定数组 Adj[u] 的每个记录项不是链表,而是一个散列表,里面包含的是 (u, v) ∈ E 的结点 v。如果每条边被查询的概率相同,则判断一条边是否在图中的期望时间值是多少?这种表示方式的缺陷是什么?请为每条边链表给出一个不同的数据结构来解决这个问题。与散列表相比较,你所给出的新方法存在什么缺陷吗?

    ANSWER:

    ① 搜索期望时间为 O(1),先找到 Adj[u],然后用 O(1) 时间在 u 中找到 v。

    ② 缺陷:会比邻接链表使用更多空间。

    ③ 利用二叉搜索树存放每条边链表的值。

    ④ 新方法缺陷:搜索时间会变成 O(lgn),n 为二叉树大小。

  • 相关阅读:
    渗透测试中的文件传输通道1- cmd下下载文件
    内网渗透常用命令
    技术剖析中国菜刀原理
    win8 iis安装及网站发布
    C++与C的区别一
    C语言实现单链表,并完成链表常用API函数
    C语言实现数组及链表的快速排序
    使用C语言封装数组,动态实现增删改查
    C语言中静态断言的使用
    二分查找法C语言实现
  • 原文地址:https://www.cnblogs.com/mhpp/p/7412726.html
Copyright © 2011-2022 走看看