算法导论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 为二叉树大小。

 

posted @ 2017-08-22 17:35  miaoheping  阅读(1083)  评论(0编辑  收藏  举报