/** * Test if the tree is logically empty. * @return true if empty, false otherwise. */ publicbooleanisEmpty( ) { return root == null; }
/////////////// makeEmpty
/** * Make the tree logically empty. */ publicvoidmakeEmpty( ) { root = null; }
/////////////// rank
/** * Return the rank of x in the tree * @param x the element * @return the rank of x in the tree * if x is in the tree, 0 otherwise */ publicintrank(AnyType x) { return rank(root,x); }
/** * Return the element of rank r in the tree * @param r the rank * @return the element of rank r in the tree * if such element exists, null otherwise */ public AnyType element(int r) { return element(root,r); }
private AnyType element(BinaryNode t, int r) { if ( t == null ) returnnull; if ( t.sizeOfLeft + 1 == r ) return t.element; if ( r <= t.sizeOfLeft ) return element(t.left,r); return element(t.right,r - t.sizeOfLeft - 1); }
/////////////// contains
/** * Find an item in the tree. * @param x the item to search for. * @return true if not found. */ publicbooleancontains( AnyType x ) { return contains( x, root ); }
/** * Internal method to find an item in a subtree. * @param x is item to search for. * @param t the node that roots the subtree. * @return node containing the matched item. */ privatebooleancontains( AnyType x, BinaryNode t ) { if( t == null ) returnfalse;
/** * add into the tree; duplicates are ignored. * @param x the item to add. */ publicvoidadd( AnyType x ) { if ( ! contains(x) ) root = add( x, root ); }
/** * Internal method to add into a subtree. * @param x the item to add. * @param t the node that roots the subtree. * @return the new root of the subtree. */ private BinaryNode add( AnyType x, BinaryNode t ) { if( t == null ) returnnewBinaryNode( x );
intcompareResult= x.compareTo( t.element );
if( compareResult < 0 ) { t.left = add( x, t.left ); t.sizeOfLeft++; } else// WE KNOW THAT x IS NOT IN t t.right = add( x, t.right ); return t; }
/////////////// remove
/** * Remove from the tree. Nothing is done if x is not found. * @param x the item to remove. */ publicvoidremove( AnyType x ) { if ( contains(x) ) root = remove( x, root ); }
/** * Internal method to remove from a subtree. * @param x the item to remove. * @param t the node that roots the subtree. * @return the new root of the subtree. */ private BinaryNode remove( AnyType x, BinaryNode t ) { // WE KNOW THAT x IS IN t // if( t == null ) // return t; // Item not found; do nothing
/** * Internal method to find the smallest item in a subtree. * @param t the node that roots the subtree. * @return node containing the smallest item. */ private BinaryNode findMin( BinaryNode t ) { if( t == null ) returnnull; elseif( t.left == null ) return t; return findMin( t.left ); }
//////////////////////////////////////////////////// // Convenience method to print a tree ////////////////////////////////////////////////////
private String makeString(char c, int k) { StringBuildersb=newStringBuilder(k); for ( inti=0; i < k; i++ ) sb.append(c); return sb.toString(); }
//////////////////////////////////////////////////// // Inner class BinaryNode ////////////////////////////////////////////////////
// Basic node stored in unbalanced binary search trees privateclassBinaryNode { // Constructors BinaryNode( AnyType theElement ) { element = theElement; left = null; right = null; sizeOfLeft = 0; }
AnyType element; // The data in the node BinaryNode left; // Left child BinaryNode right; // Right child
int sizeOfLeft; // The size of the left subtree }
//////////////////////////////////////////////////// // Convenience methods to build a list of integer from a string ////////////////////////////////////////////////////
privatestatic List<Integer> read(String inputString) { List<Integer> list = newLinkedList<Integer>(); Scannerinput=newScanner(inputString); while ( input.hasNextInt() ) list.add(input.nextInt()); input.close(); return list; }
/** * A short main for quick testing */ publicstaticvoidmain( String [ ] args )throws EmptyTreeException { List<Integer> list = read("50 30 70 20 40 80 60"); RankedBST<Integer> bst = newRankedBST<Integer>(); for ( Integer n : list ) bst.add(n); bst.display(); System.out.println("Rank of 60: " + bst.rank(60)); System.out.println("Element of rank 6: " + bst.element(6)); } }
publicclassBinaryHeap<AnyType extendsComparable<? super AnyType>> { private AnyType[] A; // to store the heap privateint size; // the number of elements in the heap // comparator to choose private Comparator<AnyType> c = newComparator<AnyType>() { publicintcompare(AnyType e1, AnyType e2) { return e1.compareTo(e2); } }; ///////////// Constructors /** * Build a heap of capacity n. * The elements are ordered according to the * natural order on AnyType. * The heap is empty. * Complexity: THETA(1) */ publicBinaryHeap(int n) { A = (AnyType[]) newComparable[n]; size = 0; } /** * Build a heap of capacity n. * The elements are ordered according to c. * The heap is empty. * Complexity: THETA(1) */ publicBinaryHeap(int n, Comparator<AnyType> c) { this.A = (AnyType[]) newComparable[n]; this.size = 0; this.c = c; } /** * Build a heap based on array A. * The elements are ordered according to the * natural order on AnyType. * The heap is full */ publicBinaryHeap(AnyType[] A) { this.A = A; this.size = A.length; buildHeap(); }
/** * Build a heap based on array A. * The elements are ordered according to c. * The heap is full */ publicBinaryHeap(AnyType[] A, Comparator<AnyType> c) { this.A = A; this.size = A.length; this.c = c; buildHeap(); } ///////////// Private methods /** * Swap values in the array * at indexes i and j. * Complexity: THETA(1) */ privatevoidswap(int i, int j) { AnyTypetmp= A[i]; A[i] = A[j]; A[j] = tmp; } /** * Return the number of the left * node of node number n. * Complexity: THETA(1) */ privateintleft(int n) { return2*n + 1; } /** * Return the number of the right * node of node number n. * Complexity: THETA(1) */ privateintright(int n) { return2*(n + 1); } /** * Return the number of the parent * node of node number n. * Complexity: THETA(1) */ privateintparent(int n) { return (n - 1)/2; } privateintgetMaxChild(int n) { intlc= left(n); intrc= right(n); if(lc >= size && rc >= size) return -1; // 如果n是叶子节点,直接返回-1 if(lc >= size) return rc; if(rc >= size) return lc; if(c.compare(A[lc], A[rc]) > 0) return lc; return rc; } /** * @brief 对下标为n的元素做“下沉”操作 * @note Complexity: O(log(size)) * @note 这是迭代/递归操作,执行完成后,原下标为n的元素应处在正确的位置上! * @param n 要进行下沉的元素下标 */ privatevoidpercolateDown(int n) { // int g = left(n); // 左孩子的下标 // int d = right(n); // 右孩子的下标 // int k = n; // 迭代下标 // if ( g < size && c.compare(A[g],A[n]) > 0 ) // k = g; // if ( d < size && c.compare(A[d],A[k]) > 0 ) // k = d; // if ( k != n ) { // swap(k,n); // percolateDown(k); // 居然写成递归了,这样其实不太好 // } // --- 改写为非递归形式 intk= n; // 迭代变量,迭代完成后会变成A[n]应处在的位置 AnyTypee= A[n]; intmaxChildIndex= getMaxChild(k); while((maxChildIndex != -1) && (k < size) && (c.compare(e, A[maxChildIndex]) < 0)) { // ^^^ 注意,这里是按照最大堆写的,首元素是最大元素 A[k] = A[maxChildIndex]; k = maxChildIndex; maxChildIndex = getMaxChild(k); } A[k] = e; } /** * @brief 对下标为n的节点进行上浮操作 * @note Complexity: O(log(size)) * @note 这是迭代/递归操作,执行完成后,原下标为n的元素应处在正确的位置上! * @param n 下标 */ privatevoidpercolateUp(int n) { AnyTypee= A[n]; while ( n > 0 && c.compare(e,A[parent(n)]) > 0 ) { // e大则上浮,相当于写成了最大堆 A[n] = A[parent(n)]; n = parent(n); } A[n] = e; } /** * Arrange the elements in A such * that it has the heap property. * Complexity: O(size) */ privatevoidbuildHeap() { for ( inti= parent(size - 1); i >= 0; i-- ) percolateDown(i); } ///////////// Public methods /** * Return the size of the heap * (the number of elements in the heap). * Complexity: THETA(1) */ publicintsize() { return size; } /** * Check if the heap is empty. * Complexity: THETA(1) */ publicbooleanisEmpty() { return size == 0; } /** * Return the extreme element. * Complexity: THETA(1) */ public AnyType extreme()throws EmptyHeapException { if ( size == 0 ) thrownewEmptyHeapException(); return A[0]; } /** * Return and delete the extreme element. * Complexity: O(log(size)) */ public AnyType deleteExtreme()throws EmptyHeapException { if ( size == 0 ) thrownewEmptyHeapException(); AnyTypeextreme= A[0]; A[0] = A[--size]; // 把尾元素放到(原)首元素处 if ( size > 0 ) percolateDown(0); // 然后对首元素进行“下沉”操作 return extreme; } /** * Add a new element in the heap * Complexity: O(log(size)) */ publicvoidadd(AnyType e)throws FullHeapException { if ( size == A.length ) thrownewFullHeapException(); A[size++] = e; percolateUp(size-1); } ///////////// Part 3: deleting in the heap /** * Delete the element e from the heap. * Complexity: O(size) */ publicvoiddelete(AnyType e) { for ( inti=0; i < size; i++ ) if ( A[i].compareTo(e) == 0 ) { A[i] = A[--size]; percolateUp(i); percolateDown(i); } } /** * Delete all the elements e from the heap. * Complexity: O(size) */ publicvoiddeleteAll(AnyType e) { inti=0; while ( i < size ) if ( A[i].compareTo(e) == 0 ) swap(i,--size); buildHeap(); } }
publicclassDynamicMedian<AnyType extendsComparable<? super AnyType>> {
private BinaryHeap<AnyType> less; // to store values less than or equal to the median private BinaryHeap<AnyType> greater; // to store values greater than or equal to the median
/** * Build a DynamicMedian object of maximum capacity n */ publicDynamicMedian(int n) { Comparator<AnyType> c = newComparator<AnyType>() { publicintcompare(AnyType e1, AnyType e2) { return e2.compareTo(e1); } }; less = newBinaryHeap<AnyType>(n); // 最大堆 用于存放比中值小的数 greater = newBinaryHeap<AnyType>(n,c); // 最小堆 用于存放比中值大的数 }
/** * Return the size (the number of elements * currently in the DynamicMedian object) * Complexity: THETA(1) */ publicintsize() { return less.size() + greater.size(); }
/** * Add a new element e. * Complexity: O(log(size)) */ publicvoidadd(AnyType e)throws EmptyHeapException, FullHeapException { if ( less.isEmpty() || e.compareTo(less.extreme()) <= 0 ) { less.add(e); // 如果这个新数比less里最大的小,那就把它放进less if ( less.size() > greater.size() + 1 ) // 如果less与greater个数相差大于1, greater.add(less.deleteExtreme()); // 就把less里最大的放进bigger } else { greater.add(e); // 否则 把它放进greater if ( less.size() < greater.size() ) // 从这里可以看出,less与greater要么数量相等,要么greater多一个 less.add(greater.deleteExtreme()); } }
/** * Return the current median. * Complexity: THETA(1) */ public AnyType findMedian()throws EmptyHeapException { return less.extreme(); // 存疑,如果greater比less多1,那么这样获得的就不是中间值 // 如果greater比less多1,应该返回greater的extreme }
/** * Return and delete the current median * Complexity: O(log(size)) */ public AnyType deleteMedian()throws EmptyHeapException, FullHeapException { AnyTypemedian= less.deleteExtreme(); if ( less.size() < greater.size() ) less.add(greater.deleteExtreme()); return median; } }
D-Heap
排序
选择排序
从未排序的部分挑出最小的,放入已排序的部分
1 2 3 4 5 6 7 8 9 10
publicstatic <AnyType extendsComparable<AnyType>> voidselection(AnyType[] array) { for ( inti=0; i < array.length - 1; i++ ) { // i表示下一个最小值的存放位置 intk= i; // k表示从i开始的最小值下标 for ( intj= i + 1; j < array.length; j++ ) if ( array[j].compareTo(array[k]) < 0 ) k = j; // 现在k表示从i开始的最小值下标,把它放到i处 swap(array, i, k); } }
publicclassQuickSort { privatestaticfinalintCUTOFF=10; /** * Sort the array in place using the quicksort algorithm */ publicstatic <AnyType extendsComparable<AnyType>> voidsort(AnyType[] array) { sort(array,0,array.length-1); }
/** * Sort the portion array[lo,hi] in place using the quicksort algorithm */ privatestatic <AnyType extendsComparable<AnyType>> voidsort(AnyType[] array, int lo, int hi) { if ( hi - lo < CUTOFF ) insertion(array,lo,hi); // 切到小于CUTOFF时,就使用插入排序 else { intpivot= partition(array,lo,hi); sort(array,lo,pivot - 1); sort(array,pivot + 1,hi); } }
/** * Partition the portion array[lo,hi] and return the index of the pivot */ privatestatic <AnyType extendsComparable<AnyType>> intpartition(AnyType[] array, int lo, int hi) { swap(array,lo,median(array,lo,(lo + hi)/2,hi)); // 对于这样的快速排序,其不稳定性可能是这一步造成的 // 只要能保证partition中相等元素的相对位置不变,那也可以是稳定的 AnyTypepivot= array[lo]; intp= lo; // 下标p表示最后一个小于pivot的元素的下标,最终则刚好是pivot的下标 // 注意是++p,p先自增,自增后指向的元素就不一定是小于pivot的了 // 但是,交换完,p仍指向最后一个小于pivot的元素 for ( inti= lo + 1; i <= hi; i++ ) // 下标i从lo+1到hi循环 if ( array[i].compareTo(pivot) < 0 ) // 如果下标i的元素小于pivot swap(array,i,++p); // 那么,先让p后移一个,然后让p、i处的元素交换 // Note: 之前提到k(即此处的i)表示第一个未处理的元素的下标 // 此for循环结束后,i的数值刚好为hi+1,并不矛盾 // 循环结束后,p指向的是最后一个严格小于pivot的元素 // 故交换并无不妥 swap(array,lo,p); // 当然,最后要把pivot放到最终的p处, // 进行完这一步后,下标p之前的元素都严格小于pivot return p; // 最终返回 }
/** * Return the index of the median of { array[lo], array[mid], array[hi] } */ privatestatic <AnyType extendsComparable<AnyType>> intmedian(AnyType[] array, int lo, int mid, int hi) { if ( array[lo].compareTo(array[mid]) < 0 ) { if ( array[mid].compareTo(array[hi]) < 0 ) return mid; if ( array[lo].compareTo(array[hi]) < 0 ) return hi; return lo; } if ( array[lo].compareTo(array[hi]) < 0 ) return lo; if ( array[mid].compareTo(array[hi]) < 0 ) return hi; return mid; } /** * Sort array[lo, hi] in place using the insertion sort algorithm */ privatestatic <AnyType extendsComparable<AnyType>> voidinsertion(AnyType[] array, int lo, int hi) { for ( inti= lo + 1; i <= hi; i++ ) { AnyTypex= array[i]; intj= i; while ( j > lo && array[j - 1].compareTo(x) > 0 ) { array[j] = array[j - 1]; j = j - 1; } array[j] = x; } } /** * Swap array[i] and array[j] */ privatestatic <AnyType> voidswap(AnyType[] array, int i, int j) { AnyTypetmp= array[i]; array[i] = array[j]; array[j] = tmp; } }
/** * Sort the array using the recursive merge sort algorithm. * This algorithm is not in place and needs an auxiliary array of * the same size than the array to sort * Complexity: THETA( n.log(n) ) where n is the size of the array */ publicstatic <AnyType extendsComparable<AnyType>> voidsort(AnyType[] array) { AnyType[] tmp = (AnyType[]) newComparable[array.length]; sort(array,tmp,0,array.length - 1); } /** * @brief 归并排序array[lo:hi],使用tmp作为临时空间 * @note 复杂度:THETA( n.log(n) ) where n = hi - lo + 1 * @param tmp 临时空间,在merge时会用到 * @param lo * @param hi */ privatestatic <AnyType extendsComparable<AnyType>> voidsort(AnyType[] array, AnyType[] tmp, int lo, int hi) { if ( lo < hi ) { intmid= (lo + hi)/2; sort(array,tmp,lo,mid); // 递归左半部分 sort(array,tmp,mid + 1,hi); // 递归有半部分 merge(array,tmp,lo,mid,hi); // 将排序好的左半部分和右半部分合并近tmp transfer(tmp,array,lo,hi); // 从tmp拷贝回array } } /** * @brief 合并,其中array[lo:mid]是左半部分,array[mid+1:hi]是右半部分,使用tmp作为临时空间 * @note 条件:array[lo, mid] and array[mid+1, hi] are sorted * @note 复杂度:THETA( n ) where n = hi - lo + 1 * @note 注意:在merge时进行实际的排序 * @param array 数组 * @param tmp 临时空间,merge会merge到这里 */ privatestatic <AnyType extendsComparable<AnyType>> voidmerge(AnyType[] array, AnyType[] tmp, int lo, int mid, int hi) { intl= lo; intr= mid + 1; intm= lo; while ( l <= mid && r <= hi ) if ( array[l].compareTo(array[r]) < 0 ) tmp[m++] = array[l++]; // 如果array[l]更小,就写入array[l] // Note: 这里没有等于,是不是导致这种写法不是稳定的归并排序?这里应该有等于,才是稳定的归并排序 else tmp[m++] = array[r++]; // 否则写入array[r] while ( l <= mid ) tmp[m++] = array[l++]; while ( r <= hi ) tmp[m++] = array[r++]; }
/** * Copy the elements from tmp[lo, hi] into array[lo, hi] * Complexity: THETA( n ) where n = hi - lo + 1 */ privatestatic <AnyType> voidtransfer(AnyType[] tmp, AnyType[] array, int lo, int hi) { for ( inti= lo; i <= hi; i++ ) array[i] = tmp[i]; } }
publicclassMergeSort2 { /** * Sort the array using the recursive merge sort algorithm. * This algorithm is not in place and needs an auxiliary array of * the same size than the array to sort * Complexity: THETA( n.log(n) ) where n is the size of the array */ publicstatic <AnyType extendsComparable<AnyType>> voidsort(AnyType[] array) { AnyType[] tmp = (AnyType[]) newComparable[array.length]; sortInplace(array,tmp,0,array.length - 1); } /** * @brief 对array[lo:hi]原地排序 * @note 先把左右两部分排序到tmp里,然后再merge到array里 */ privatestatic <AnyType extendsComparable<AnyType>> voidsortInplace(AnyType[] array, AnyType[] tmp, int lo, int hi) { if ( lo < hi ) { intmid= (lo + hi)/2; sortTo(array,tmp,lo,mid); // 不再是直接递归自己,而是调用sortTo,然后让sortTo再调用sortInplace sortTo(array,tmp,mid + 1,hi); mergeTo(tmp,array,lo,mid,hi); // 相较于MergeSort1省去了transfer } } /** * @brief 把array[lo:hi]排序到tmp里面 * @note 先把左右两部分都“原地”排序,再合并到tmp里 * @note Complexity: THETA( n.log(n) ) where n = hi - lo + 1 */ privatestatic <AnyType extendsComparable<AnyType>> voidsortTo(AnyType[] array, AnyType[] tmp, int lo, int hi) { if ( lo < hi ) { intmid= (lo + hi)/2; sortInplace(array,tmp,lo,mid); sortInplace(array,tmp,mid + 1,hi); mergeTo(array,tmp,lo,mid,hi); } elseif ( lo == hi ) tmp[lo] = array[lo]; } /** * @brief 将from[]数组合并进to[]数组 * @note Complexity: THETA( n ) where n = hi - lo + 1 * @note Precondition: array[lo, mid] and array[mid+1, hi] are sorted * @param from * @param to * @param lo * @param mid * @param hi */ privatestatic <AnyType extendsComparable<AnyType>> voidmergeTo(AnyType[] from, AnyType[] to, int lo, int mid, int hi) { intl= lo; intr= mid + 1; intm= lo; while ( l <= mid && r <= hi ) if ( from[l].compareTo(from[r]) < 0 ) to[m++] = from[l++]; else to[m++] = from[r++]; while ( l <= mid ) to[m++] = from[l++]; while ( r <= hi ) to[m++] = from[r++]; }
publicclassPathFinder { privatestatic Graph G; privatestatic Set<Vertex> visited; /** * Returns a path as from vertex 'u' to vertex 'v' in the graph 'G' * as a list of vertices if such a path exists, the empty list otherwise */ publicstatic List<Vertex> findPath(Graph G, Vertex u, Vertex v) { PathFinder.G = G; PathFinder.visited = newHashSet<Vertex>(); List<Vertex> path = newLinkedList<Vertex>(); findPath(u,v,path); return path; } /** * If there is a path from vertex 'u' to vertex 'v' in the graph, the * vertices of this path are stored in the list 'path' and the method * returns true. Else the list 'path' remains unchanged and the method * returns false */ privatestaticbooleanfindPath(Vertex u, Vertex v, List<Vertex> path) { visited.add(u); if ( u == v ) { path.add(u); returntrue; } for ( Vertex a : G.adjacents(u) ) { if ( ! visited.contains(a) ) { if ( findPath(a,v,path) ) { path.add(0,u); returntrue; } } } returnfalse; } publicstaticvoidmain(String[] s) { DiGraphG= GraphReader.D3; System.out.println(G); System.out.println(findPath(G,G.getVertex("F"),G.getVertex("E"))); } }
publicclassMST { /** * Returns the list of edges of an MST of weighted undirected graph G * * using the Prim algorithm * Precondition: G is connected */ publicstatic List<Edge> prim(UnDiGraph G)throws FullHeapException, EmptyHeapException { List<Edge> mst = newLinkedList<Edge>(); // MST的边集合 Comparator<Edge> c = newComparator<Edge>() { // 建立最小堆 // 堆中存储与known集合相邻的边 publicintcompare(Edge e1, Edge e2) { return e2.compareTo(e1); } }; BinaryHeap<Edge> minHeap = newBinaryHeap<Edge>(G.nbEdges(),c); Set<Vertex> known = newHashSet<Vertex>(); // 存储已知节点的集合 // --- 从任意节点开始算法 Vertexu= G.getRandomVertex(); known.add(u); // 将与u相连的边加入最小堆 for ( Edge e : G.incidents(u) ) minHeap.add(e); // while not all vertices are known (i.e. connected) while ( known.size() < G.nbVertices() ) { Edgemin= minHeap.deleteExtreme(); Vertexx= notKnown(min,known); if ( x != null ) { // min是know集合与其他节点相连的边 mst.add(min); // 那么将它加入最小生成树 known.add(x); // 并将新节点加入know集合 for ( Edge e : G.incidents(x) ) { Vertexy= notKnown(e,known); if ( y != null ) minHeap.add(e); // 并将与新节点相连的、连接到其他节点的边加入堆 } } } return mst; } /** * Given the edge 'e' = (u,v) and the current set of known vertices * returns the vertex (u or v) which is not in 'know', or null if they * are both in 'known' * Precondition: if 'e' = (u,v), at least one of u and v is in 'known' */ privatestatic Vertex notKnown(Edge e, Set<Vertex> known) { Vertexv=null; if ( ! known.contains(e.origin()) ) v = e.origin(); elseif ( ! known.contains(e.destination())) v = e.destination(); return v; }
publicclassMST { /** * Returns the list of edges of an MST of weighted undirected graph G * using the Kruskal algorithm * Precondition: G is connected */ publicstatic List<Edge> kruskal(UnDiGraph G)throws FullHeapException, EmptyHeapException { List<Edge> mst = newLinkedList<Edge>(); Comparator<Edge> c = newComparator<Edge>() { publicintcompare(Edge e1, Edge e2) { return e2.compareTo(e1); } }; BinaryHeap<Edge> minHeap = newBinaryHeap<Edge>(G.nbEdges(),c); for ( Edge e : G.edges() ) // 将所有边加入堆 minHeap.add(e); // disjoint sets of all the vertices of the graph G Partition<Vertex> P = newPartition<Vertex>(); // add each vertex as a new tree in the partition for ( Vertex v : G.vertices() ) P.newTree(v); // 将每个节点初始化作为一个“孤岛” // while not all the vertices are connected while ( P.nbTrees() > 1 ) { // 只要“孤岛”的数量大于1,就表示生成树没有找完 Edgemin= minHeap.deleteExtreme(); // 1 - 寻找权重最小的边 Vertexu= min.origin(); Vertexv= min.destination(); Partition.Treeru= P.find(u); Partition.Treerv= P.find(v); if ( ru != rv ) { // 2 - 检查它是否连接两个孤岛 mst.add(min); // 如果是,就将它放入最小生成树, P.union(ru, rv); // 并将它连接的两个“孤岛”进行union操作 } } return mst; }
privateint nbTrees; // 当前并查集的分区数 private Map<AnyType,InnerTree> map; // 将每个对象映射到它所属的树 /** * Return an empty partition with no tree */ publicPartition() { nbTrees = 0; map = newHashMap<AnyType,InnerTree>(); } publicintnbTrees() { return nbTrees; } /** * Add a new one-element tree with * element 'e' in the partition */ publicvoidnewTree(AnyType e) { map.put(e,newInnerTree()); nbTrees++; } /** * Returns the tree the * element 'e' belongs to */ public Tree find(AnyType e) { return find(map.get(e)); } /** * Merge the two trees 'x' and 'y' * Precondition: 'x' != 'y' */ @SuppressWarnings("unchecked") publicvoidunion(Tree x, Tree y) { union((InnerTree) x, (InnerTree) y); } /** * Merge the two InnerTree 'x' and 'y' * Precondition: 'x' != 'y' */ privatevoidunion(InnerTree x, InnerTree y) { if ( x.size <= y.size ) { x.parent = y; y.size += x.size; } else { y.parent = x; x.size += y.size; } nbTrees--; } /** * Returns the root InnerTree the * (sub-tree) InnerTRee 'n' belongs to */ private InnerTree find(InnerTree n) { if ( n == n.parent ) return n; InnerTreeroot= find(n.parent); n.parent = root; return root; } /** * A public interface to provide the Partition.Tree type * to the client code. There is NO operation available * on Partition.Tree, except reference comparison == and != */ publicinterfaceTree {} /** * A (private) class for InnerTree */ privateclassInnerTreeimplementsTree { // the InnerTree parent InnerTree parent; // the number of elements inside this InnerTree int size; /** * Returns a single-element InnerTree */ InnerTree() { this.parent = this; this.size = 1; } } }