Four algorithms to solve connectivity problems

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.
recently done B-station barrage analysis of the project, Learning Jieba Chinese word segmentation dynamic programming algorithm, found their algorithm knowledge to learn the system, then read Sedgewick "algorithm C implementation of the third edition", this series of algorithm code on Github, the article will be synchronized to SF, random reprint.

Connectivity issues

Problem overview

Let's take a look at a picture:

In this network of connected and disconnected points, we can find a path from P point to Q Point. In the computer network to determine whether the two hosts are connected, in the social network to determine whether there are two users of indirect social relations, etc., can be abstracted into connectivity problems.

Problem abstraction

The point (host, person) in the network can be abstracted as an object, which p-q means that p is connected to Q, and the connected relationship is transitive: p-q & q-r => p-r ; To briefly describe the problem, two objects are marked as an integer pair, and a given integer pair sequence describes the point network.

If the node is N = 5 of the network (using 0 ~ N-1 to represent the object), a sequence of integers can be used 0-1 1-3 2-4 to describe the connectivity, where 0 and 3 are also connected, there are two connected components: {0, 1, 3} and {2, 4}

Problem: Given a sequence of integers describing a connected relationship, any of them two integers p and q to determine if they can be connected?

Example of a problem

输入     不连通    连通 3-4     3-44-9     4-98-0     8-02-3     2-35-6     5-62-9             2-3-4-9    5-9     5-97-3     7-34-8     4-85-6             5-60-2             0-8-4-3-26-1     6-1

The corresponding connectivity graph is as follows, the black line indicates the first connection to two nodes, the green lines indicate that the two nodes already have a connectivity relationship:

Algorithm one: Fast lookup algorithm

Use the id[i] value of the array storage node i for the node ordinal, which is the same as the initial state ordinal and array value:

When the first two connected relationships are entered, the id[i] changes are as follows:

As you can see, id[i] the value is the endpoint node that is connected to when the connection is complete i . If p and q are connected, then the id[p] id[q] value should be equal.

When completed 4-9 , id[3] the and id[4] values are the end point 9. At this time to determine whether 3 and 9 are connected, the direct judgment id[3] and id[9] the value is equal, the same is connected, unequal there is no connectivity. Obviously id[3] == id[9] == 9 , there is a connectivity relationship.

Algorithm implementation

/** file:1.1-quick_find.go */package mainimport ... const N = 10var ID [n]intfunc main () {reader: = Bufio. Newreader (OS. Stdin)//Initialize ID array, element value equal to node ordinal for I: = 0; i < N; i++ {Id[i] = i}//read command line input for {data, _, _: = Reader.            ReadLine () str: = string (data) if str = = "\ n" {continue} if str = = "#" { Break} values: = Strings. Split (str, "") p, _: = StrConv. Atoi (values[0]) Q, _: = StrConv. Atoi (values[1]) if Connected (p, q) {FMT. Printf ("Already Connected nodes:%d-%d\n", p, Q) Continue} Union (P, q)}}//determines whether the nodes of the integers p and q are connected. Pass func Connected (p, q int) bool {return id[p] = = id[q]}//connected p-q node func Union (p, q int) {pid: = id[p] qid: = id[ Q]//Iterate through the ID array and replace all nodes with a value of id[p] with Id[q] for I: = 0; i < N; i++ {if id[i] = = pid {id[i] = qid}} fmt. Printf ("Unconnected nodes:%d-%d\n", p, Q)}

Operation effect: Can judge 2-9 existing connectivity relationship

Complexity of

The fast lookup algorithm can determine whether p and Q are connected, only to determine id[p] and be id[q] equal. However, when P and Q are not connected, they are merged, and each merge needs to traverse the entire array. Features: Fast lookup, slow merge

Algorithm two: Fast merging algorithm

Overview

The fast lookup algorithm each time the merge iterates through the array causes inefficiency. We would like to not be able to traverse each time id[] , optimized to only iterate through the array of partial values, the complexity will be reduced.

At this point should think of the tree structure, in the transitivity of the connectivity relationship, p->r & q->r => p->q R can be treated as a root, p and Q as a sub-node, because P and Q have the same root r, so p and Q are connected. The tree here is the abstraction of the connected relationship.

Data

Use an array as the implementation of the tree:

    • Node array id[N] , id[i] i parent node of the store
    • iThe root node is the id[id[...id[i]...]] parent node of the parent node that keeps looking up ... Until the root node (the parent node is itself).

Advantages of using Trees

Change the representation of an integer pair of sequences from an array to a tree, where each node stores its parent node location, which has 2 benefits:

    1. Determine if p and Q are connected: Have the same root node
    2. Merge p to Q: Change the root node of p to the root node of q (no full traversal, fast merging)

Example:

For the upper integer pair sequence, the find, merge process is as follows, Orange is the merge action, Gray is connected, and green is an array of storage trees.

Note that the red 2-3 , not directly 2 as the 3 sub-node, but found 3 of the root node 9, merged 2-3 with 3-4-9 , generated2-9

Algorithm implementation:

/** file: 1.2-quick_union.go */// p 和 q 有相同的根结点,则是连通的func Connected(p, q int) bool {    return getRoot(p) == getRoot(q)}// 连通 p-q 结点func Union(p, q int) {    pRoot := getRoot(p)    qRoot := getRoot(q)    id[pRoot] = qRoot        // q 树的根此时有了父结点(p 树的根),完成合并    fmt.Printf("Unconnected nodes: %d-%d\n", p, q)}// 获取结点 i 的根结点func getRoot(i int) int {    // 没到根结点就继续向上寻找    for i != id[i] {        i = id[i]    }    return i}

Algorithm three: Fast merging algorithm with weighted weights

Overview

There is a flaw in the fast merging algorithm: When the data is large, arbitrarily merging subtrees will cause the tree to become taller, and it will still be very slow to find the most values of the group when looking for the root node. To determine whether P, Q is connected, you need to find 13 nodes:

If the tree is still relatively short after merging, the sub-tree balance, then find the root node will be less traversal many nodes, and then determine whether P, Q is connected, only need to find 7 nodes:

The construction of the balance tree

Building a balanced tree requires merging small trees into large trees to ensure that the merged tree grows slowly or does not increase, so that most of the merging needs to traverse the nodes greatly reduced. Distinguish small trees, trees use the weight of the tree: subtree contains the number of nodes.

Data

The storage of the tree nodes is still used id[i] , but an extra array size[i] is required to record the nodes of node I.

Algorithm implementation

/**file: 1.3-weighted_version.go在快速合并算法的基础上,只需要在合并操作中,将小树合并到大树上即可*/var id [N]intvar size [N]intfunc main() {     // 初始化 id 数组,元素值与结点序号相等    for i := 0; i < N; i++ {        id[i] = i        size[i] = i    }       ...}  ...// 连通 p-q 结点func Union(p, q int) {    pRoot := getRoot(p)    qRoot := getRoot(q)    // p 树是大树    if size[pRoot] < size[qRoot] {        id[pRoot] = qRoot        size[qRoot] += size[pRoot]    } else {        id[qRoot] = id[pRoot]        size[pRoot] += size[qRoot]    }    id[pRoot] = qRoot // q 树的根此时有了父结点(p 树的根),完成合并    fmt.Printf("Unconnected nodes: %d-%d\n", p, q)}

Algorithm four: Weighted fast merging algorithm for path compression

Overview

Weighted fast merging algorithm when most integer pairs are directly connected, the resulting tree is still relatively high, such as a sequence:

10-8 8-6 11-9 12-9 9-6 6-3 7-3 3-1 4-1 5-1 1-0 2-0

The resulting tree is as follows:

At this point 9-2 , we need to find the root node of 9 and 2, respectively, to determine the connectivity. In the search for 9 of the root node through 6, 3, 1 trees, because 6, 3, 1 tree nodes and 9, the root node is 0, so directly 6, 3, 1 tree into a subtree of 0. As follows:

Optimization

Each time a node is evaluated for its root node, the nodes that are checked along the road also point to the root node. Flattening the tree as much as possible will significantly reduce the number of nodes that are traversed when checking the connected state.

Algorithm implementation

/**file: 1.4-path_compression_by_halving.go改动的代码很少,但很精妙*/// 获取结点 i 的根结点func getRoot(i int) int {    // 没到根结点就继续向上寻找    for i != id[i] {        id[i] = id[id[i]]        // 将结点、结点的父结点不断往上挪动,直到都连接上了根结点        i = id[i]    }    return i}

Complexity of

N is the size of the node collection, and T is the height of the tree.

algorithm the complexity of initialization Merge Complexity Find Complexity
Quick Find N N (full traversal) 1 (array value comparison)
Quick Merge N T (Traversal tree) T (Traversal tree)
Quick Merge with Right N LG N LG N
Fast merge with right of path compression N Close to 1 (the height of the tree is almost 2) Close to 1

Summarize

The above introduces 4 algorithms to solve the connectivity problem, from the low-efficiency to complete the basic functions of fast search, to continuously optimize the reduction of the complexity of nearly 1 of the path compression belt right rapid merger. You can learn the approximate steps of the algorithmic solution problem: Complete the basic functions first, and then optimize the reduction of complexity for inefficient operations.

Original: Https://wuyin.io/2018/01/27/c ...

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.