I. Question
Describes how to maintain a dynamic dataset Q that supports an operational MIN-GAP so that this operation gives the minimum difference between two numbers in Q. For example, if q = {, 9, 15, 18, 22}, then the MIN-GAP (q) returns 18-15 = 3 because 15 and 18 are the last two of them. Use the insert, delete, search, and MIN-GAP operations to be as efficient as possible and analyze their runtime.
Ii. Thinking
Step 1: Basic Data Structure
The red/black tree. The values in the array are the keywords of each node.
Step 2: add information
Min-gap [x]: records the Min-gap of the tree with X as the root node. When X is the leaf node, Min-gap [x] = 0x7fffffff
Min-Val [x]: records the smallest keyword in the tree with X as the root node.
Max-Val [x]: records the largest keyword in the tree with X as the root node.
Step 3: maintain information
The added information is updated at the same time as the inserted deletion. the time complexity remains unchanged.
Step 4: design new operations
Min_gap (): returns the Min-gap value of the root node.
Iii. Code
# Include <iostream> using namespace STD; # define black 0 # define Red 1 // MIN-GAP Tree node Structure struct node {node * left; // left child node * right; // right-child node * P; // parent int key; // keyword bool color; // color, red or black int min_gap; // records the Min-gap of the tree with X as the root node. When X is the leaf node, Min-gap [x] = 0x7fffffint min_val; // records the smallest keyword int max_val in the tree with X as the root node; // record the largest keyword node (node * init, int K) in the tree with X as the root node: Left (init), right (init), P (init ), key (K), color (black), min_gap (0x7fffff), min_val (K), max_val (k) {}}; // struct min_gap_tree {node * root; // root node * nil; // sentinel min_gap_tree () {nil = new node (null,-1); root = nil ;};}; int min (int, int B, int C, int d) {A = A <B? A: B; C = C <D? C: D; return a <C? A: C;} // information maintenance void maintaining (min_gap_tree * t, node * X) {While (X! = T-> nil) {// maintenance of min_val information X-> min_val = (X-> left! = T-> nil )? X-> left-> min_val: X-> key; // maintenance of max_val information X-> max_val = (X-> right! = T-> nil )? X-> right-> max_val: X-> key; // maintenance of min_gap information int A = (X-> left! = T-> nil )? X-> left-> min_gap: 0x7fffffff; int B = (X-> right! = T-> nil )? X-> right-> min_gap: 0x7fffffff; int c = (X-> left! = T-> nil )? (X-> key-X-> left-> max_val): 0x7fffffff; int d = (X-> right! = T-> nil )? (X-> right-> min_val-X-> key): 0x7fffffff; X-> min_gap = min (A, B, C, D ); // update x = x-> P ;}// left-hand, so that Y = x-> right, left-hand rotation is based on the chain between x and y. // The involved nodes include: X, Y, Y-> left, so that node = {P, L, r }, the specific changes are as follows: // X = {X-> P, X-> left, y} is changed to {Y, X-> left, y-> left} // y = {X, Y-> left, Y-> right} is changed to {X-> P, X, y-> right} // y-> left = {Y, Y-> left, Y-> left-> right} is changed to {X, y-> left, Y-> left-> right} void left_rotate (min_gap_tree * t, node * X) {// make y = x-> rightnode * Y = x-> Right; // modify the pointer of the three nodes according to the preceding method. Note that the pointer order X-> right = Y-> left; If (Y-> left! = T-> nil) Y-> left-> P = x; y-> P = x-> P; If (X-> P = T-> nil) // special case: X is the root node T-> root = y; else if (x = x-> P-> left) x-> P-> left = y; else X-> P-> right = y; y-> left = x; X-> P = y; maintaining (t, x);} // right-hand, take y = x-> left, and the left-hand side is the axis of the chain between x and y. // The rotation process is similar to void right_rotate (min_gap_tree * t, node * X) {node * Y = x-> left; X-> left = Y-> right; if (Y-> right! = T-> nil) Y-> right-> P = x; y-> P = x-> P; If (X-> P = T-> nil) t-> root = y; else if (x = x-> P-> right) x-> P-> right = y; else X-> P-> left = y; y-> right = x; X-> P = y; maintaining (t, x );} // adjust void mg_insert_fixup (min_gap_tree * t, node * z) {node * Y; // The only situation that needs to be adjusted is the violation of nature 2, if there is no violation of nature 2, adjust the end while (Z-> P-> color = red) {// P [Z] is the left child, in three cases, if (Z-> P = z-> P-> left) {// make y the primary node of z y = z-> P-> right; // In the first case, z's uncle y is red if (Y-> color = red) {// Black P [Z] and y to solve the problem that both Z and P [Z] are red Z-> P-> color = black; y-> color = black; // place P [p [Z] in red to keep the property 5z-> P-> color = Red; // use P [p [Z] as the newly added node Z to repeat the while loop z = z-> P;} else {// The second case: z's uncle is black, and Z is the right child if (Z = z-> P-> right) {// to P [Z] left, in the third case, Z = z-> P; left_rotate (T, Z);} // In the third case, Uncle Z is black, and Z is the color of the left child // swap P [Z] and P [p [Z], and right-hand Z-> P-> color = black; z-> P-> color = Red; right_rotate (T, Z-> P) ;}// P [Z] is the right child, there are three cases, similar to the above else if (Z-> P = z-> P-> right) {Y = z-> P-> left; If (Y-> color = red) {z-> P-> color = black; y-> color = black; Z-> P-> color = Red; z = z-> P;} else {If (Z = z-> P-> left) {z = z-> P; right_rotate (t, z);} Z-> P-> color = black; Z-> P-> color = Red; left_rotate (t, z-> P) ;}}// set the root node to black T-> root-> color = black ;} // insert a node void min_gap_insert (min_gap_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; elsex = x-> right ;} z-> P = 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 mg_insert_fixup (T, Z) up ); // maintain the Information maintaining (T, Z);} // adjust the tree. X points to a red/Black node, the adjustment process is to move the extra black along the tree void mg_delete_fixup (min_gap_tree * t, node * X) {node * W; // If the extra black is on a root node or a red node, the node will suck Black to 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-> P-> left) {// Let W be the brother of X, 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-> P-> right; // first case: W is the red if (W-> color = red) {// change the color of W and P [x] W-> color = black; x-> P-> color = Red; // perform a left-handed left_rotate (t, x-> P) on P [X ); // new brother w = x-> P-> 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-> right-> color = black) {// remove the Black W and X. // w only A black layer is removed to red, and X has an extra black layer. after removal, the original color w-> color = Red is restored; // Add a black X = x-> P on P [X]; // The New X has an extra black color, transfer to for loop continue processing} // 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); // The new brother w whose W is X = x-> P-> right; // Changes to the fourth case at this time} // The fourth case: W is black, W-> left is black, w-> right is red. // modify the color of W and P [x] W-> color = x-> P-> color; x-> P-> color = black; W-> right-> color = Black; // perform a left-handed left_rotate (t, x-> P) on P [X]; // The adjustment is completed, 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-> P-> right) {// Let W be the X brother, depending on W, there are three cases: // before the delete operation is executed, X certainly has no brothers. After the delete operation is executed, X must have a sibling W = x-> P-> left; // first case: W is the red if (W-> color = red) {// change the color of W and P [x] W-> color = black; x-> P-> color = Red; // perform a left-hand right_rotate (t, x-> P) on P [X ); // new brothers W whose W is x w = x-> P-> left; // convert to one of the three situations} // Case 2: 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 has only one black layer, and the color turns red, X has an extra black layer. Remove the layer and restore the original color w-> color = Red; // Add a black layer x = x-> P on P [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-> 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; // perform a right-hand left_rotate (t, w); // The new brother w whose W is X = x-> P-> left; // Changes to the fourth case at this time} // The fourth case: W is black, W-> right is black, W-> left is red // modify the color of W and P [x] W-> color = X-> P-> color; X-> P-> color = black; W-> left-> color = black; // perform a left-hand right_rotate (t, x-> P) on P [X]; // The adjustment has ended, set X as the root node to end the loop x = T-> root ;}}// absorbs extra black X-> color = black ;} // find the minimum node * tree_minimum (min_gap_tree * t, node * X) {// if 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, the successor is the smallest node * tree_successor (min_gap_tree * t, node * X) greater than key [x] {// if there is a right child if (X-> right! = T-> nil) // return 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 successor y, then Y is the lowest ancestor node of X, and the left son of Y is also node * Y = x-> P; while (y! = NULL & X = Y-> right) {x = y; y = Y-> P;} return y ;} // delete node * min_gap_delete (min_gap_tree * t, node * z) in the red/black tree {// locate and delete the node, this part is the same as deleting the Binary Search Tree node ** X, * Y; if (Z-> left = T-> nil | Z-> right = T-> nil) y = z; else y = tree_successor (T, Z ); if (Y-> left! = T-> nil) x = Y-> left; else x = Y-> right; X-> P = Y-> P; if (Y-> P = T-> nil) T-> root = x; else if (y = Y-> P-> left) y-> P-> left = x; Elsey-> P-> right = x; // maintenance of Information maintaining (t, x); If (y! = Z) {z-> key = Y-> key; // maintenance of Information maintaining (T, Z);} // If the deleted node is black, then you need to adjust if (Y-> color = black) mg_delete_fixup (t, x); Return y;} // recursively query the Binary Search Tree node * min_gap_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 min_gap_search (X-> left, k ); // The searched node is located in the left subtree else return min_gap_search (X-> right, K) of the current node;} void print (node * X) {If (X-> key =-1) return; print (X-> left ); cout <X-> key <''<X-> color <Endl; print (X-> right);} int min_gap (node * r) {return r-> min_gap;} void print (min_gap_tree * t) {print (t-> root); cout <Endl;} int main () {// generate a MIN-GAP tree min_gap_tree * t = new min_gap_tree; int X; char ch; while (1) {cout <"enter an operation:" <Endl; cout <"I: Insert a random number to the set" <Endl; cout <"d x: delete a number with a value of X from the set" <Endl; cin> CH; Switch (CH) {// insert a keyword case 'I': {// generate a random number to be inserted x = rand () % 100; // display the number of just inserted cout <"the inserted number is" <x <Endl; node * z = new node (t-> nil, X ); min_gap_insert (T, Z); // output Min-gapcout <"Min-Gap =" <min_gap (t-> root) <Endl; break ;} // delete a keyword case 'D': {// enter the number of cells to be deleted. Cin> X; // first, find the number of node * ret = min_gap_search (t-> root, x) with the value of X from the set; // Delete the number in the set, if (ret = T-> nil) cout <"not exist" <Endl; elsemin_gap_delete (T, RET ); // output Min-gapcout <"Min-Gap =" <min_gap (t-> root) <Endl; break ;}} cout <Endl ;} return 0 ;}Iv. Test code