Algorithm: and check set

Source: Internet
Author: User

And check set is a widely used data structure, can quickly deal with the collection of merge and query problems, and the implementation is very convenient, in many cases have a very clever application.
In this paper, we first introduce the definition, principle and implementation of the set, and then explain its specific use by using a classical application in the minimum spanning tree algorithm.

The principle and realization of collecting and checking together

And check set is a tree-type data structure, which is used to deal with the merging and querying problems of disjoint sets.

And the collection in use is usually expressed in forest, each set organized into a tree, and the root node as the representative element. In practice, an array of father[x] is implemented to represent the parent node of node X. In addition, a variable n indicates the number of nodes. However, in order to improve performance, it is often used an array of rnk[x] to represent the depth of the subtree of node X, as explained in detail later.

const int MX = 100000 + 1; Maximum number of nodes int n;//number of nodes int FATHER[MX]; Node's father int rnk[mx];//the subtree depth of the node

And a check set typically supports three operations: Initialize, find, merge.

1. Initialization

Initialization initializes the set of each point to itself, that is, n nodes have n sets. Traversing n nodes once, each father was initialized to himself, and the subtree's depth was initialized to 0.

void MakeSet ()//Initialize {for (int i = 0; i < n; i++) Father[i] = i, rnk[i] = 0;}
2. Find

Finds the collection where the element resides, that is, the root node. Because a collection uses only the root node as a proxy, it is searched as long as it goes up and down the father array until the root node, and the root node's father is itself, and the code is:

int findsetoriginal (int x)//non-path compression lookup {if (x! = father[x]) x = Father[x];return father[x];}

In practice, however, an optimization called path compression is done. Because there may be a long path from the node x to the root node, the time complexity of the lookup is in extreme cases O (n). We can in the search process, the father of each node point to the node, so the search is completed after the original length of a path of n is a path of n length 1, these nodes find time complex corresponding to O (1). The implementation of path compression is as follows:

int findset (int x)//recursive path compression Find {if (x! = Father[x]) father[x] = Findset (father[x]); return father[x];}

But the actual recursive algorithm may cause the stack overflow problem, the following is the corresponding non-recursive algorithm. The main idea is to first find the root node of the collection and then change the parent of the node on the path to the root node.

int findsetnonrecursive (int x)///non-recursive path compression lookup {int root = x;//root node while (root = father[root]) root = father[root];int tem = x;w Hile (tem! = root)  //path compression {int temfather = father[tem];//Staging Father node Father[tem] = root;//update father for root tem = temfather;//move to Father node} return root; Returns the root node}
3. Merging

Merges the collection of two elements into a single collection. When merging, use the lookup function in 2 to find the root node of the two collection. If the root node is the same and the description belongs to the same collection, no merging is required. If different, simply point the father of one root node to another root node.

In practice, a combination of optimizations called by rank is used, because direct merging can result in a deep tree, which is not conducive to subsequent lookups. The preceding rnk[x] array represents the rank of node x, which is the depth of the nodes ' subtree. When merging, we always point the father of the node with the small rank to the rank-large node, so as to minimize the depth of the newly generated tree. When the rank of two nodes at the same time, the rank of the root node of the new tree will need to be added 1, because the subtree depth is increased by 1, otherwise the subtree depth does not change, and the rank does not need to change.

int unionset (int x, int y)//merge {x = Findset (x), y = Findset (y), if (x = = y) return 0;//belong to the same collection without merging if (Rnk[x] > Rnk[y]) Father[y] = X;else father[x] = y, rnk[y] + = rnk[x] = = Rnk[y];return 1;//belong to a different collection and have been merged successfully}

Union-find sets is a very ingenious and useful data structure, which is mainly used to deal with the merging problems of disjoint sets . Some common uses include the Kruskal algorithm for connecting sub-graphs, the minimum spanning tree, and the nearest common ancestor (Least Common ancestors, LCA).

When using and checking sets, there is a set of disjoint dynamic collections firstS={< Span id= "mathjax-span-11" class= "Msubsup" >s 1, S 2, ? ,Sk} , an integer is typically used to represent an element in the collection.

Each collection may contain one or more elements and select an element in the collection as the representative . Each collection contains exactly what elements are not cared for, and which element is chosen as the representative of the general is not concerned. What we care about is that for a given element, you can quickly find the set where the element resides, and merge the collection of two elements, and the time complexity of these operations is constant .

There are three basic operations for the check set:

    1. MakeSet (s): establishes a new and checked set that contains the s single-element collection.
    2. Unionset (x, y): Merges the set of element x and element y, requiring that the set of x and Y do not intersect, if the intersection is not merged.
    3. Find (x): Finds the representative of the collection where element x is located, which can also be used to determine whether two elements are in the same collection, as long as they compare their respective representatives.

And the realization of the principle of the set is also relatively simple, is to use the tree to represent the collection, each node of the tree represents an element of the collection, the root of the corresponding element is the representative of the collection, 1 is shown.

Note: When looking for ancestors we generally use recursive lookup, but when the elements are many or the whole tree into a chain, every time Find_set (x) is the complexity of O (n), there is no way to reduce the complexity of it?
The answer is yes, this is the path compression, that is, when we "recursive" to find the ancestor node, "backtracking" by the way, the descendant nodes are directly pointed to the ancestors, so that later again Find_set (x) when the complexity becomes O (1), as shown, the path compression facilitates the subsequent search.

Reference documents:

Http://noalgo.info/454.html

Http://www.cnblogs.com/cyjb/p/UnionFindSets.html

Http://www.ahathinking.com/archives/10.html

Algorithm: and check set

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.