//! <b>Effects</b>: Moves the first n nodes starting at p to the end of the list. //! //! <b>Returns</b>: A pair containing the new first and last node of the list or //! if there has been any movement, a null pair if n leads to no movement. //! //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Linear to the number of elements plus the number moved positions. static std::pair<node_ptr, node_ptr> move_first_n_backwards(node_ptr p, std::size_t n) { std::pair<node_ptr, node_ptr> ret(node_ptr(0), node_ptr(0)); //Null shift, or count() == 0 or 1, nothing to do if(!n || !p || !NodeTraits::get_next(p)){ return ret; } node_ptr first = p; bool end_found = false; node_ptr new_last(0); node_ptr old_last(0); //Now find the new last node according to the shift count. //If we find 0 before finding the new last node //unlink p, shortcut the search now that we know the size of the list //and continue. for(std::size_t i = 1; i <= n; ++i){ new_last = first; first = NodeTraits::get_next(first); if(first == 0){ //Shortcut the shift with the modulo of the size of the list n %= i; if(!n) return ret; old_last = new_last; i = 0; //Unlink p and continue the new first node search first = p; //unlink_after(new_last); end_found = true; } } //If the p has not been found in the previous loop, find it //starting in the new first node and unlink it if(!end_found){ old_last = base_t::get_previous_node(first, node_ptr(0)); } //Now link p after the new last node NodeTraits::set_next(old_last, p); NodeTraits::set_next(new_last, node_ptr(0)); ret.first = first; ret.second = new_last; return ret; }
//! <b>Effects</b>: Moves the first n nodes starting at p to the beginning of the list. //! //! <b>Returns</b>: A pair containing the new first and last node of the list or //! if there has been any movement, a null pair if n leads to no movement. //! //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Linear to the number of elements plus the number moved positions. static std::pair<node_ptr, node_ptr> move_first_n_forward(node_ptr p, std::size_t n) { std::pair<node_ptr, node_ptr> ret(node_ptr(0), node_ptr(0)); //Null shift, or count() == 0 or 1, nothing to do if(!n || !p || !NodeTraits::get_next(p)) return ret; node_ptr first = p; //Iterate until p is found to know where the current last node is. //If the shift count is less than the size of the list, we can also obtain //the position of the new last node after the shift. node_ptr old_last(first), next_to_it, new_last(p); std::size_t distance = 1; while(!!(next_to_it = node_traits::get_next(old_last))){ if(distance++ > n) new_last = node_traits::get_next(new_last); old_last = next_to_it; } //If the shift was bigger or equal than the size, obtain the equivalent //forward shifts and find the new last node. if(distance <= n){ //Now find the equivalent forward shifts. //Shortcut the shift with the modulo of the size of the list std::size_t new_before_last_pos = (distance - (n % distance))% distance; //If the shift is a multiple of the size there is nothing to do if(!new_before_last_pos) return ret; for( new_last = p ; --new_before_last_pos ; new_last = node_traits::get_next(new_last)){ //empty } } //Get the first new node node_ptr new_first(node_traits::get_next(new_last)); //Now put the old beginning after the old end NodeTraits::set_next(old_last, p); NodeTraits::set_next(new_last, node_ptr(0)); ret.first = new_first; ret.second = new_last; return ret; }
//! <b>Effects</b>: Moves the node p n positions towards the beginning of the list. //! //! <b>Returns</b>: The previous node of p after the function if there has been any movement, //! Null if n leads equals to no movement. //! //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Linear to the number of elements plus the number moved positions. static node_ptr move_forward(node_ptr p, std::size_t n) { //Null shift, nothing to do if(!n) return 0; node_ptr first = node_traits::get_next(p); //count() == 1 or 2, nothing to do if(node_traits::get_next(first) == p) return 0; //Iterate until p is found to know where the current last node is. //If the shift count is less than the size of the list, we can also obtain //the position of the new last node after the shift. node_ptr old_last(first), next_to_it, new_last(p); std::size_t distance = 1; while(p != (next_to_it = node_traits::get_next(old_last))){ if(++distance > n) new_last = node_traits::get_next(new_last); old_last = next_to_it; } //If the shift was bigger or equal than the size, obtain the equivalent //forward shifts and find the new last node. if(distance <= n){ //Now find the equivalent forward shifts. //Shortcut the shift with the modulo of the size of the list std::size_t new_before_last_pos = (distance - (n % distance))% distance; //If the shift is a multiple of the size there is nothing to do if(!new_before_last_pos) return 0; for( new_last = p ; new_before_last_pos-- ; new_last = node_traits::get_next(new_last)){ //empty } } //Now unlink p and link it after the new last node base_t::unlink_after(old_last); base_t::link_after(new_last, p); return new_last; }