Question:
The definition of the Joseph's problem is as follows: Suppose n people are arranged in a ring and there is a positive integer m <= n. Starting from a specific person, the number of records along the ring will be listed for every m person and the number of records will continue. This process continues until everyone is listed. The order of columns for each person defines the (n, m)-Joseph arrangement of integers 1, 2,... and N. For example, ()-Joseph PHUs is arranged as <, 4>.
A) suppose M is an integer. Describe an O (n) Time Algorithm to arrange the output (n, m)-Joseph for the given integer n.
B) suppose M is not a constant. Describe an O (nlgn) Time Algorithm to arrange the given integers n and M, and output (n, m)-Joseph.
Thoughts:
Based on the dynamic sequence statistics in 14.1, assume that the first point in the remaining vertex is deleted (0 at the initial time), and T points are left, the next vertex to be deleted is the (start + m-1) % t vertex of the remaining vertex.
Step 1: Basic Data Structure
Red/black tree
Step 2: add information
Size [x]: The number of (internal) knots (including X itself) of the subtree rooted in X, that is, the size of the subtree. Size [nil [T] = 0
Step 3: maintain information
Size [x] = size [left [x] + size [right [x] + 1
Insert operation: Update O (lgn) from the insert node to the root node)
Rotation operation: only two vertices O (1) on the rotating axis need to be updated)
Delete operation: Update O (lgn) from the parent node of the deleted node to the root node)
Code:
# Include <iostream> using namespace STD; # define black 0 # define Red 1 // structure of the red/black tree node struct node {// structure of the red/black tree node * left; node * right; node * parent; int key; bool color; int size; // number of (internal) knots (including X itself) of the Child tree rooted in X ), node (node * init, int K): Left (init), right (init), parent (init), key (K), color (black ), size (1) {}}; // ordered statistic tree structure struct OS _tree {node * root; // root node * nil; // sensen OS _tree () {nil = new node (null,-1); nil-> size = 0; root = nil ;}; }; // Maintenance of additional information void maintaining (node * X) {While (X-> key> = 0) {X-> size = x-> left-> size + X-> right-> size + 1; X = x-> parent ;}// left-hand, y = x-> right. The left-hand side is the pivot of the chain between x and y. // The involved nodes include X, Y, Y-> left, change node = {P, L, r} as follows: // X = {X-> parent, X-> left, y} to {y, x-> left, Y-> left} // y = {X, Y-> left, Y-> right} is changed to {X-> parent, X, y-> right} // y-> left = {Y, Y-> left, Y-> left-> right} is changed to {X, y-> left, Y-> left-> right} void left_rotate (OS _tree * t, n Ode * X) {// make y = x-> rightnode * Y = x-> right; // modify the pointers of the three nodes in the preceding way, note that the order of the pointer X-> right = Y-> left; If (Y-> left! = T-> nil) Y-> left-> parent = x; y-> parent = x-> parent; If (X-> parent = T-> nil) // special case: X is the root node T-> root = y; else if (x = x-> parent-> left) x-> parent-> left = y; else X-> parent-> right = y; y-> left = x; X-> parent = y; // maintenance of additional information y-> size = x-> size; x-> size = x-> left-> size + X-> right-> size + 1;} // right-hand, y = x-> left, left-hand rotation is based on the chain between x and y. // The rotation process is similar to void right_rotate (OS _tree * t, node * X) {node * Y = x-> left; x-> left = Y-> right; if (Y -> Right! = T-> nil) Y-> right-> parent = x; y-> parent = x-> parent; If (X-> parent = T-> nil) t-> root = y; else if (x = x-> parent-> right) x-> parent-> right = y; else X-> parent-> left = y; y-> right = x; X-> parent = y; // maintenance of additional information y-> size = x-> size; x-> size = x-> left-> size + X-> right-> size + 1;} // adjust void OS _tree_insert_fixup (OS _tree * t, node * z) {node * Y; // The only condition that needs to be adjusted. This is the violation of nature 2. If it does not violate nature 2, adjust the end while (Z-> parent-> color = red) {// parent [Z] When the left child, there are three conditions if (Z-> parent = z-> parent-> left) {// set Y to the Z node y = z-> parent-> right; // In the first case, z's uncle y is red if (Y-> color = red) {// black both parent [Z] and y to solve the problem that both Z and parent [Z] are red Z-> parent-> color = black; y-> color = black; // place parent [Parent [Z] in red to keep the property 5z-> parent-> color = Red; // use parent [Parent [Z] as the newly added node Z to repeat the while loop z = z-> parent;} else {// The second case: z's uncle is black, and Z is the right child if (Z = z-> parent-> right) {// for parent [Z] Left-handed, to the third case z = z-> parent; left_rotate (T, Z);} // third case: Z's uncle is black, and Z is the color of the left child // swap parent [Z] and parent [Parent [Z], and right-hand Z-> parent-> color = black; z-> parent-> color = Red; right_rotate (T, Z-> parent) ;}// when parent [Z] is the right child, there are three cases, similar to the above else if (Z-> parent = z-> parent-> right) {Y = z-> parent-> left; If (Y-> color = red) {z-> parent-> color = black; y-> color = black; Z-> parent-> color = Red; Z = z-> Parent-> parent;} else {If (Z = z-> parent-> left) {z = z-> parent; right_rotate (T, Z );} z-> parent-> color = black; Z-> parent-> color = Red; left_rotate (T, Z-> parent );}}} // set the root node to black T-> root-> color = black;} // insert a node void OS _tree_insert (OS _tree * t, node * z) {node * Y = T-> nil, * x = T-> root; // locate the position to be inserted, which is the same as that of the binary search tree while (X! = T-> nil) {Y = x; If (Z-> key <X-> key) x = x-> left; else if (Z-> key> X-> key) x = x-> right;} Z-> parent = y; If (y = T-> nil) t-> root = z; else if (Z-> key <Y-> key) Y-> left = z; Elsey-> right = z; z-> left = T-> nil; Z-> right = T-> nil; // convert the newly inserted node into red Z-> color = Red; // start from the newly inserted node and adjust OS _tree_insert_fixup (T, Z); maintaining (z) ;}// adjust the tree. X points to a red/Black node, the adjustment process is to move the extra black along the tree void OS _tree_delete_fixup (OS _tree * t, node * X) {node * w; // if this extra black Color on a root node or a red knot, the node will absorb extra black and become a black node while (X! = T-> root & X-> color = black) {// If X is the left node of its parent node (which corresponds to the right node) if (x = x-> parent-> left) {// Let W be the X brother, depending on W, there are three cases: // before the delete operation is executed, X will certainly have no brothers. After the delete operation is executed, X will certainly have brothers W = x-> parent-> right; // first case: W is the red if (W-> color = red) {// change the color of W and parent [x] W-> color = black; x-> parent-> color = Red; // perform a left-handed left_rotate (t, x-> parent) operation on the parent [x ); // new brother w = x-> parent-> right for w x; // converts it to one of the three situations} // Case 2: W is black, both children of W are black if (W-> left-> color = Black & W-> rig Ht-> color = black) {// remove the Black W and X. // w only has one black layer. Remove the black layer and change it to Red. X has an extra black layer, remove and restore the original color w-> color = Red; // Add a black X = x-> parent on the parent [x; // now there is an extra black on the new X, which is transferred to the for loop for further processing} // In the third case, W is black, W-> left is red, w-> right is a black else {If (W-> right-> color = black) {// change the color of W and left [x] W-> left-> color = black; W-> color = Red; // perform a right-hand right_rotate (t, w); // set w to X's new brother w = x-> parent-> right; // This is the fourth case} // The fourth case: W is black, W-> left is black, W-> right is red // modify the color of W and parent [x] W-> Co Lor = x-> parent-> color; X-> parent-> color = black; W-> right-> color = black; // perform a left-handed left_rotate (t, x-> parent) operation on the parent [X]; // The adjustment has ended, set X as the root node to end the loop x = T-> root;} // If X is the left node of its parent node (the right node corresponds) else if (x = x-> parent-> right) {// the brother who makes w x different from W, there are three cases: // before the delete operation is executed, X will certainly have no brothers. After the delete operation is executed, X will certainly have brothers W = x-> parent-> left; // first case: W is the red if (W-> color = red) {// change the color of W and parent [x] W-> color = black; x-> parent-> color = Red; // perform a left-handed righ operation on the parent [X ]. T_rotate (t, x-> parent); // set w to X's new brother w = x-> parent-> left; // convert to one of the three situations} // The second case: W is black, both children of W are black if (W-> right-> color = Black & W-> left-> color = black) {// remove the black color of W and X. // w only has a black color, which turns red. X has an extra black color, and then restores the original color w-> color = Red; // Add a black X = x-> parent on the parent [X]; // now the new x has an extra black, transfer to for loop continue processing} // The third case, W is black, W-> right is red, w-> left is a black else {If (W-> left-> color = black) {// change the color of W and right [x] W-> right-> color = black; W-> color = Red; // Rows: Right-handed left_rotate (T, W); // new brother w whose W is X = x-> parent-> left; // This is the fourth case} // The fourth case: W is black, W-> right is black, w-> left is red. // modify the color of W and parent [x] W-> color = x-> parent-> color; x-> parent-> color = black; W-> left-> color = black; // perform a left-hand right_rotate (t, x-> parent) operation on the parent [x ); // now the adjustment has ended. set X as the root node to end the cycle x = T-> root ;}}} // absorbed extra black X-> color = black;} // find the minimum node * OS _tree_minimum (OS _tree * t, node * X) {// as long as there is a node smaller than the current node while (X-> left! = T-> nil) x = x-> left; return X;} // search for the successor of the x node in the middle sequence, followed by the smallest node * OS _tree_successor (OS _tree * t, node * X) greater than key [x] {// if there is a right child if (X-> right! = T-> nil) // return OS _tree_minimum (t, x-> right) at the minimum value in the right subtree; // if the right subtree of X is empty and X has a next y, then Y is the lowest ancestor node of X, and the left son of Y is also node * Y = x-> parent; while (y! = NULL & X = Y-> right) {x = y; y = Y-> parent;} return y ;} // recursively query the Binary Search Tree node * OS _tree_search (node * X, int K) {// The leaf node is not found yet, or the current node is the searched node if (X-> key =-1 | K = x-> key) return X; // The searched node is located in the left subtree of the current node if (k <X-> key) return OS _tree_search (X-> left, k ); // The searched node is located in the left subtree else return OS _tree_search (X-> right, K) of the current node;} // delete node * OS _tree_delete (OS _tree * t, node * z) {// locate the node and delete it. This part is the same as the delete node * X of the Binary Search Tree, * Y; If (Z-> left = T-> nil | Z-> right = T-> nil) y = z; else y = OS _tree_successor (t, z); If (Y-> left! = T-> nil) x = Y-> left; else x = Y-> right; X-> parent = Y-> parent; if (Y-> parent = T-> nil) T-> root = x; else if (y = Y-> parent-> left) y-> parent-> left = x; Elsey-> parent-> right = x; maintaining (Y-> parent); If (y! = Z) {z-> key = Y-> key; maintaining (z) ;}// if the deleted node is black, you need to adjust if (Y-> color = black) OS _tree_delete_fixup (t, x); Return y ;} // find the I-largest node in the tree with X as the root node * OS _tree_select (node * X, int I) {// set the number of dots in the left subtree of X as the R-1, int r = x-> left-> size + 1; // If (r = I) return X, X is the largest node in the X Tree; // The element larger than I is in X-> left else if (I <r) return OS _tree_select (X-> left, I ); // The element larger than I is in X-> right else return OS _tree_select (X-> right, I-r);} int main () {// generate a dynamic sequence statistics tree OS _tree * t = new OS _tree; int m, n, I; while (CIN> N> m) {// set 1 ., N is inserted into the tree sequentially for (I = 1; I <= N; I ++) {node * z = new node (t-> nil, I ); OS _tree_insert (T, Z);} int t = n, start = 0; // There are still remaining nodes while (t) {// calculate the position of the next node to be deleted in the remaining node start = (start + m-1) % T; // find this node * ret = OS _tree_select (t-> root, start + 1); cout <ret-> key <''; // Delete this node OS _tree_delete (T, RET); t --;} cout <Endl;} return 0 ;}