Thinking and analysis:
If M is a constant, you can use a circular linked list and head or tail pointer to indicate the loop structure easily. After cyclic output, the node is deleted n times. During each outer loop, the inner layer is fixed for m times. Therefore, the running time is O (Mn) = O (n ).
M is not a constant. The size attribute can be used to record the location of each node in the current tree. After a remainder process, each node can be correctly found and output to delete each node. After N cycles, each cycle needs to find a node output and delete it, therefore, it takes O (lgn) Time for each loop. The total running time is O (nlgn ).
The Code is as follows:
When M is a constant:
#include <iostream>using namespace std;#define n 10#define m 3#define LEN sizeof(struct circular_list)struct circular_list{ int key; struct circular_list* next;};struct circular_list*tail=NULL;struct circular_list*Insert(struct circular_list*&head,int k){struct circular_list*z=new struct circular_list[LEN];z->key=k; if (head==NULL) {head=tail=z;head->next=tail; }else{tail->next=z;z->next=head;tail=z;}return head;}struct circular_list* Delete(struct circular_list*&head,struct circular_list*z){ struct circular_list*p=head; while (p->next!=z) { p=p->next; } if (head==tail) { p->next=NULL; } else { if (head==p->next) { head=p->next->next; } else if (tail==p->next) { tail=p; } p->next=p->next->next; } return p->next;}void n_m_Josephus(struct circular_list*&head){ struct circular_list*p=head; while (p) { int i=0; while (i!=m-1) { p=p->next; i++; } struct circular_list*z=p; cout<<z->key<<" "; p=Delete(head,z); }}void main(){ int a[n]={0};for (int i=0;i<n;i++){a[i]=i+1;}int j=0;struct circular_list*head=NULL; while (j!=n) {head=Insert(head,a[j]);j++;; } struct circular_list*p=head;do {cout<<p->key;p=p->next;} while (p!=head);cout<<endl;n_m_Josephus(head);}
When M is not a constant:
# Include <iostream> # include <time. h> using namespace STD; # define black 0 # define Red 1 # define nil-1 # define Len sizeof (struct OS _tree) struct OS _tree {struct OS _tree * right, * left; struct OS _tree * parent; int key, color, size; // size indicates the number of knots in the subtree .}; Struct OS _tree * root = NULL, * nil = NULL; void left_rotate (struct OS _tree * X) {// left rotation: Describes the rotation code in three steps ① ③. Struct OS _tree * Y = x-> right; // set the y node. X-> right = Y-> left; // the code in this line and the IF structure below indicate that "the left child of Y becomes the right child of X ". ① If (Y-> left! = Nil) {Y-> left-> parent = x;} y-> parent = x-> parent; // The line of code and the following if-else structure expression process is "Y becomes the new root of the subtree ". ② If (X-> parent = nil) {root = y;} else if (x = x-> parent-> left) {X-> parent-> left = y;} else X-> parent-> right = y; y-> left = X; // This line of code and the following line both express "X is the left child of Y ". ③ X-> parent = y; y-> size = x-> size; // maintenance of additional information X-> size = x-> left-> size + X-> right-> size + 1;} void right_rotate (struct OS _tree * X) {// right rotation: Describes the rotation code in three steps (①) (③. Struct OS _tree * Y = x-> left; // set the y node. X-> left = Y-> right; // This line of code and the IF structure below indicate that "the left child of Y becomes the right child of X ". ① If (Y-> right! = Nil) {Y-> right-> parent = x;} y-> parent = x-> parent; // The line of code and the following if-else structure expression process is "Y becomes the new root of the subtree ". ② If (X-> parent = nil) {root = y;} else if (x = x-> parent-> right) {X-> parent-> right = y;} else X-> parent-> left = y; y-> right = X; // This line of code and the following line both express "X is the left child of Y ". ③ X-> parent = y; y-> size = x-> size; // maintenance of additional information X-> size = x-> left-> size + X-> right-> size + 1;} void rb_insert_fixup (struct OS _tree * z) {While (Z-> parent-> color = red) {If (Z-> parent = z-> parent-> left) {struct OS _tree * Y = z-> parent-> right; // If (Y-> color = red) // scenario 1: the primary node is red {// color P1, y, and P2 to keep the property 5. And solved the problem that the parent node of Z and Z are both red nodes Z-> parent-> color = black; y-> color = black; z-> parent-> color = Red; Z = z-> parent; // take z's grandfather node as the new node Z into the next loop} else {If (Z = z-> parent-> right) // Scenario 2: check whether Z is a right child and the primary node is black, provided that the P1 node is not a leaf node {// use a left-hand node to convert case 2 to case 3 Z = z-> parent; left_rotate (z); // after entering the if statement, we can see that the rotating node cannot be a leaf node, so we don't have to judge whether Z is a leaf node.} Z-> parent-> color = black; // Case 3: Z is a left child and the uncle node is black, change the color of the parent and grandfather node of Z and perform a right-hand operation to keep the properties 5 Z-> parent-> color = Red; right_rotate (Z-> parent); // Since P2 may be a leaf node, it is best to use an if to judge} else // The else branch below is similar to the above, note that the rotation in Case 2 and Case 3 of the else branch is exactly the inverse of the IF branch. {Struct OS _tree * Y = z-> parent-> left; If (Y-> color = red) {z-> parent-> color = black; y-> color = black; Z-> parent-> color = Red; Z = z-> parent ;} else {If (Z = z-> parent-> left) {z = z-> parent; right_rotate (z);} Z-> parent-> color = black; z-> parent-> color = Red; left_rotate (Z-> parent) ;}} root-> color = black; // Finally, the root point is black .} Void rb_insert (struct OS _tree * z) {struct OS _tree * Y = nil; struct OS _tree * x = root; while (X! = Nil) {X-> size ++; y = x; If (Z-> key <X-> key) {x = x-> left ;} else x = x-> right;} Z-> parent = y; If (y = nil) {root = z ;} else if (Z-> key <Y-> key) {Y-> left = z;} else y-> right = z; Z-> left = nil; // assign a blank value to the left and right children of the inserted node. Z-> right = nil; Z-> color = Red; // The insert node is red. Z-> size = 1; Z-> left-> size = 0; Z-> right-> size = 0; rb_insert_fixup (z );} void rb_transplant (struct OS _tree * u, struct OS _tree * V) {If (u-> parent = nil) root = V; else if (u = u-> parent-> left) U-> parent-> left = V; else u-> parent-> right = V; v-> parent = u-> parent;} struct OS _tree * tree_minimum (struct OS _tree * X) // calculates the minimum value of the current node of the Binary Search Tree {While (X! = Nil & X-> left! = Nil) {x = x-> left;} return X;} struct OS _tree * tree_maxinum (struct OS _tree * X) // calculates the maximum value of the current node of the Binary Search Tree {While (X! = Nil & X-> right! = Nil) {x = x-> right;} return X;} struct OS _tree * tree_predecessor (struct OS _tree * X) // search for the front of the Binary Search Tree {If (X-> left! = Nil) {return tree_maxinum (X-> left);} struct OS _tree * Y = x-> parent; while (y! = Nil & X = Y-> left) {x = y; y = Y-> parent;} return y;} struct OS _tree * tree_successor (struct OS _tree * X) // find the successor of the Binary Search Tree {If (X-> right! = Nil) {return tree_minimum (X-> right);} struct OS _tree * Y = x-> parent; while (y! = Nil & X = Y-> right) {x = y; y = Y-> parent;} return y ;} // non-recursive Binary Search Tree lookup function struct OS _tree * iterative_tree_search (struct OS _tree * X, int K) {While (X! = Nil & K! = X-> key) {If (k <X-> key) {x = x-> left;} else x = x-> right;} return X ;} void rb_delete_fixup (struct OS _tree * X) {struct OS _tree * w = NULL; // W is the sibling node of X while (X! = Root & X-> color = black) // If X is black and is not the root node, the loop is executed. {// X is a node with dual colors. The purpose of adjustment is to move the black attribute of X up. If (x = x-> parent-> left) {W = x-> parent-> right; if (W-> color = red) // scenario 1: x's sibling node W is red. {// Change the color of W and X. P + one rotation to Case 2, 3, and 4. W-> color = black; X-> parent-> color = Red; left_rotate (X-> parent); W = x-> parent-> right ;} if (W-> left-> color = Black & W-> right-> color = black) // Case 2: X's sibling node W is black, in addition, both child nodes of W are black. {W-> color = Red; // remove a heavy black from X and W. X is black, and W is red. X = x-> parent; // The x node moves up to become the new node to be adjusted.} Else {If (W-> right-> color = black) // Case 3: The sibling node W of X is black, and the left child of W is red, w's right child is black. {// Switch the color + rotation of W and W. Left to case 4. W-> left-> color = black; W-> color = Red; right_rotate (w); W = x-> parent-> right ;} w-> color = x-> parent-> color; // The following is the case 4: The sibling node W of X is black, and the right child of W is red. X-> parent-> color = black; // set X. P and W. Right to black + rotate to remove the extra black of X. W-> right-> color = black; left_rotate (X-> parent); X = root; // X becomes the root node and ends the loop.} The following else // is similar to the IF branch above. {W = x-> parent-> left; If (W-> color = red) {w-> color = black; X-> parent-> color = Red; right_rotate (X-> parent); W = x-> parent-> left ;} if (W-> left-> color = Black & W-> right-> color = black) {w-> color = Red; X = x-> parent;} else {If (W-> left-> color = black) {w-> right-> color = black; w-> color = Red; left_rotate (w); W = x-> parent-> left;} w-> color = x-> parent-> color; x-> parent-> color = black; W-> left-> color = black; right_rot Ate (X-> parent); X = root; }}x-> color = black;} void rb_delete (struct OS _tree * z) {struct OS _tree * Y = Z, * X; // y indicates the node to be deleted or moved. Int y_original_color = Y-> color; // saves the original color of Y to prepare for the final adjustment. Struct OS _tree * t = z-> parent; If (Z-> left = nil) {While (T! = Nil) {T-> size --; t = T-> parent;} X = z-> right; // X points to the unique subnode or leaf node of Y, save the trace of x and move it to the original position of Y. rb_transplant (z, Z-> right); // set the path to Z. replace the subtree with Z as the root of right .} Else if (Z-> right = nil) {While (T! = Nil) {T-> size --; t = T-> parent;} X = z-> left; // X points to the unique subnode or leaf node of Y, save the trace of x and move it to the original position of Y. replace left with the child tree with Z as the root .} Else {Y = tree_minimum (Z-> right); // find the successor of Z. Right. Struct OS _tree * t = Y-> parent; y-> size = z-> size-1; // y replaces the original position of Z, therefore, the size attribute is-1 while (T! = Nil) {T-> size --; t = T-> parent;} The new original node of y_original_color = Y-> color; // y is reset. X = Y-> right; // X points to the unique subnode or leaf node of Y, save the trace of x and move it to the original position of Y. If (Y-> parent = z) {X-> parent = y; // because the parent node of Z is the node to be deleted, it cannot be directed to it, so it points to y} else {rb_transplant (Y, Y-> right); // set Y. replace the subtree with Y as the root of right. Y-> right = z-> right; y-> right-> parent = y;} rb_transplant (z, y ); // Replace the subtree rooted in Y with the subtree rooted in Z. Y-> left = z-> left; y-> left-> parent = y; y-> color = z-> color; // assign the color of the deleted node to Y to ensure that the color of the tree structure above y remains the same .} If (y_original_color = black) // The original color of Y is black, indicating that you need to adjust the red and black colors. Rb_delete_fixup (x);} // traverse void inodertraverse (struct OS _tree * P) {If (P! = Nil) {inodertraverse (p-> left); cout <p-> key <"<p-> color <" <"rank: "<p-> size <Endl; inodertraverse (p-> right) ;}} struct OS _tree * OS _select (struct OS _tree * & X, int I) // find the element of the given rank in the sequence statistics tree {int r = x-> left-> size + 1; if (I = r) {return X ;} else if (I <r) {return OS _select (X-> left, I);} else return OS _select (X-> right, I-r );} int iterative_ OS _rank (struct OS _tree * & T, struct OS _tree * X) // determine the rank of the sequence statistics tree {int r = x-> left-> size + 1; Struct OS _tree * Y = x; while (y! = Root) {If (y = Y-> parent-> right) {r = R + Y-> parent-> left-> size + 1 ;} y = Y-> parent;} return r;} void n_m_joseph PHUs (struct OS _tree * X, int M, int N) {x = root; Int J = 0, I = n, T = 1; while (root! = Nil) {J = (t + m-1) % I; If (j = 0) J = I; struct OS _tree * Y1 = OS _select (root, J ); // Y1 indicates the cout <Y1-> key <""; // output node rb_delete (Y1); // Delete T = J after the output node; I -- ;}} void main () {srand (unsigned) Time (null); int m = 0, n = 0; cout <"Enter the M and N values in the n_m_joseph us Arrangement" <Endl; cout <"m ="; CIN> m; cout <"n ="; CIN> N; int * array1 = new int [N]; for (Int J = 0; j <n; j ++) {array1 [J] = J + 1; cout <array1 [J] <"" ;}cout <Endl; nil = new struct OS _tree [Len]; nil-> Key = nil; nil-> color = black; root = nil; int I = 0; struct OS _tree * root = new struct OS _tree [Len]; root-> key = array1 [I ++]; rb_insert (Root); root = root; while (I! = N) {struct OS _tree * z = new struct OS _tree [Len]; Z-> key = array1 [I]; rb_insert (z); I ++ ;} inodertraverse (Root); cout <"Joseph arrangement:"; n_m_joseph PHUs (root, m, n );}
SummaryPart A of Joseph's arrangement uses chapter 1, while Part B uses the knowledge of this chapter. This is a simple application of learned knowledge. I think this program is quite interesting.