{"id":111958,"date":"2026-01-02T07:00:00","date_gmt":"2026-01-02T15:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=111958"},"modified":"2026-01-02T05:48:37","modified_gmt":"2026-01-02T13:48:37","slug":"20260102-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20260102-00\/?p=111958","title":{"rendered":"How can you swap two adjacent blocks of memory using only forward iterators?"},"content":{"rendered":"<p>Last time, we noted that the <code>std::<wbr \/>rotate<\/code> function requires only forward iterators. The algorithm we explored last time involved a clever sequence of reversals, but reversals require bidirectional iterators (one to iterator forward from the beginning and another to iterate backward from the end). <a title=\"Swapping two blocks of memory that reside inside a larger block, in constant memory\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20260101-00\/?p=111955\"> How do you do it when you can only iterate forward<\/a>?<\/p>\n<p>Let&#8217;s set up the problem again. Suppose we want to swap these two blocks A and B.<\/p>\n<table style=\"border-collapse: collapse; text-align: center;\" title=\"A large block of memory labeled A, followd a smaller one labeled B\" border=\"0\" cellspacing=\"0\" cellpadding=\"1\">\n<tbody>\n<tr>\n<td style=\"width: 10em; border: solid 1px currentcolor; background: lch(from currentcolor l c h \/ .1);\">A<\/td>\n<td style=\"width: 6em; border: solid 1px currentcolor;\">B<\/td>\n<td>&nbsp;<\/td>\n<\/tr>\n<tr style=\"text-align: left;\">\n<td style=\"width: 10em;\">\u2191<\/td>\n<td style=\"width: 6em;\">\u2191<\/td>\n<td>\u2191<\/td>\n<\/tr>\n<tr style=\"text-align: left;\">\n<td style=\"width: 10em;\">first<\/td>\n<td style=\"width: 6em;\">mid<\/td>\n<td>last<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>We can early-out in the vacuous cases where either the A or B block is empty. For those cases, we can return without doing anything.<\/p>\n<p>We start by swapping the elements at <code>first<\/code> and <code>mid<\/code>, then incrementing both pointers and repeating. Here&#8217;s what it looks after swapping a handful of items:<\/p>\n<table style=\"border-collapse: collapse; text-align: center;\" title=\"A large block of memory labeled A, followd a smaller one labeled B\" border=\"0\" cellspacing=\"0\" cellpadding=\"1\">\n<tbody>\n<tr>\n<td style=\"width: 3em; border: solid 1px currentcolor;\">B1<\/td>\n<td style=\"width: 7em; border: solid 1px currentcolor; background: lch(from currentcolor l c h \/ .1);\">A2<\/td>\n<td style=\"width: 3em; border: solid 1px currentcolor; background: lch(from currentcolor l c h \/ .1);\">A1<\/td>\n<td style=\"width: 3em; border: solid 1px currentcolor;\">B2<\/td>\n<td>&nbsp;<\/td>\n<\/tr>\n<tr style=\"text-align: left;\">\n<td style=\"width: 3em;\">\u00a0<\/td>\n<td style=\"width: 7em;\">\u2191<\/td>\n<td style=\"width: 3em;\">\u00a0<\/td>\n<td style=\"width: 3em;\">\u2191<\/td>\n<td>\u2191<\/td>\n<\/tr>\n<tr style=\"text-align: left;\">\n<td style=\"width: 3em;\">\u00a0<\/td>\n<td style=\"width: 7em;\">first<\/td>\n<td style=\"width: 3em;\">\u00a0<\/td>\n<td style=\"width: 3em;\">mid<\/td>\n<td>last<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Let&#8217;s first take the case where the A block is bigger than the B block. In that case, the entire B block gets swapped to the start of the buffer, and a B-sized chunk of the first part of the A block (let&#8217;s call it A1) got swapped to the end of the buffer. There&#8217;s still a leftover chunk of the A block, call it A2, that hasn&#8217;t moved yet.<\/p>\n<table style=\"border-collapse: collapse; text-align: center;\" title=\"\" border=\"0\" cellspacing=\"0\" cellpadding=\"1\">\n<tbody>\n<tr>\n<td style=\"width: 6em; border: solid 1px currentcolor;\">B<\/td>\n<td style=\"width: 4em; border: solid 1px currentcolor; background: lch(from currentcolor l c h \/ .1);\">A2<\/td>\n<td style=\"width: 6em; border: solid 1px currentcolor; background: lch(from currentcolor l c h \/ .1);\">A1<\/td>\n<td>&nbsp;<\/td>\n<\/tr>\n<tr style=\"text-align: left;\">\n<td style=\"width: 6em;\">\u00a0<\/td>\n<td style=\"width: 4em;\">\u2191<\/td>\n<td style=\"width: 6em;\">\u00a0<\/td>\n<td>\u2191<\/td>\n<\/tr>\n<tr style=\"text-align: left;\">\n<td style=\"width: 6em;\">\u00a0<\/td>\n<td style=\"width: 4em;\">first<\/td>\n<td style=\"width: 6em;\">\u00a0<\/td>\n<td>mid<br \/>\nlast<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Okay, so the B block is in its final position, but the A1 and A2 blocks need to be swapped. Hey, I know how to swap two adjacent blocks: I call <code>std::<wbr \/>rotate<\/code> on myself recursively! Since this is a tail recursive call, I can just move <code>mid<\/code> back to its original position at the start of the function and restart the algorithm.<\/p>\n<table style=\"border-collapse: collapse; text-align: center;\" title=\"\" border=\"0\" cellspacing=\"0\" cellpadding=\"1\">\n<tbody>\n<tr>\n<td style=\"width: 6em; border: solid 1px currentcolor;\">B<\/td>\n<td style=\"width: 4em; border: solid 1px currentcolor; background: lch(from currentcolor l c h \/ .1);\">A2<\/td>\n<td style=\"width: 6em; border: solid 1px currentcolor; background: lch(from currentcolor l c h \/ .1);\" colspan=\"2\">A1<\/td>\n<td>&nbsp;<\/td>\n<\/tr>\n<tr style=\"text-align: left;\">\n<td style=\"width: 6em;\">\u00a0<\/td>\n<td style=\"width: 4em;\">\u2191<\/td>\n<td style=\"width: 6em;\" colspan=\"2\">\u2191<\/td>\n<td>\u2191<\/td>\n<\/tr>\n<tr style=\"text-align: left;\">\n<td style=\"width: 6em;\">\u00a0<\/td>\n<td style=\"width: 4em;\">first<\/td>\n<td style=\"width: 6em;\" colspan=\"2\">mid<\/td>\n<td>last<\/td>\n<\/tr>\n<tr style=\"text-align: left;\">\n<td style=\"width: 6em;\">\u00a0<\/td>\n<td style=\"width: 4em;\">\u00a0<\/td>\n<td style=\"width: 6em;\" colspan=\"2\">\u2929<\/td>\n<td>recursive rotate to swap A1 and A2<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 6em; border: solid 1px currentcolor;\">B<\/td>\n<td style=\"width: 6em; border: solid 1px currentcolor; background: lch(from currentcolor l c h \/ .1);\" colspan=\"2\">A1<\/td>\n<td style=\"width: 4em; border: solid 1px currentcolor; background: lch(from currentcolor l c h \/ .1);\">A2<\/td>\n<td>&nbsp;<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The other case is where the A block is smaller than the B block.<\/p>\n<table style=\"border-collapse: collapse; text-align: center;\" title=\"A small block of memory labeled A, followd a larger one labeled B\" border=\"0\" cellspacing=\"0\" cellpadding=\"1\">\n<tbody>\n<tr>\n<td style=\"width: 6em; border: solid 1px currentcolor; background: lch(from currentcolor l c h \/ .1);\">A<\/td>\n<td style=\"width: 10em; border: solid 1px currentcolor;\">B<\/td>\n<td>&nbsp;<\/td>\n<\/tr>\n<tr style=\"text-align: left;\">\n<td style=\"width: 6em;\">\u2191<\/td>\n<td style=\"width: 10em;\">\u2191<\/td>\n<td>\u2191<\/td>\n<\/tr>\n<tr style=\"text-align: left;\">\n<td style=\"width: 6em;\">first<\/td>\n<td style=\"width: 10em;\">mid<\/td>\n<td>last<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>In this case, we swap until we have used up all of the A elements. The entire A block gets swapped to the middle of the buffer, and an A-sized chunk of the start of the B block (call it B1) goes to the start of the buffer, with the leftover part of B (call it B2) stays at the end of the buffer.<\/p>\n<table style=\"border-collapse: collapse; text-align: center;\" title=\"\" border=\"0\" cellspacing=\"0\" cellpadding=\"1\">\n<tbody>\n<tr>\n<td style=\"width: 6em; border: solid 1px currentcolor;\">B1<\/td>\n<td style=\"width: 6em; border: solid 1px currentcolor; background: lch(from currentcolor l c h \/ .1);\">A<\/td>\n<td style=\"width: 4em; border: solid 1px currentcolor;\">B2<\/td>\n<td>&nbsp;<\/td>\n<\/tr>\n<tr style=\"text-align: left;\">\n<td style=\"width: 6em;\">\u00a0<\/td>\n<td style=\"width: 6em;\">\u2191<\/td>\n<td style=\"width: 4em;\">\u2191<\/td>\n<td>\u2191<\/td>\n<\/tr>\n<tr style=\"text-align: left;\">\n<td style=\"width: 6em;\">\u00a0<\/td>\n<td style=\"width: 6em;\">first<\/td>\n<td style=\"width: 4em;\">mid<\/td>\n<td>last<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Again, we can finish with a recursive rotate call, this time to swap A and B2.<\/p>\n<table style=\"border-collapse: collapse; text-align: center;\" title=\"\" border=\"0\" cellspacing=\"0\" cellpadding=\"1\">\n<tbody>\n<tr>\n<td style=\"width: 6em; border: solid 1px currentcolor;\">B1<\/td>\n<td style=\"width: 6em; border: solid 1px currentcolor; background: lch(from currentcolor l c h \/ .1);\" colspan=\"2\">A<\/td>\n<td style=\"width: 4em; border: solid 1px currentcolor;\">B2<\/td>\n<td>&nbsp;<\/td>\n<\/tr>\n<tr style=\"text-align: left;\">\n<td style=\"width: 6em;\">\u00a0<\/td>\n<td style=\"width: 4em;\">\u00a0<\/td>\n<td style=\"width: 2em; text-align: center;\">\u2929<\/td>\n<td style=\"width: 4em;\">\u00a0<\/td>\n<td>recursive rotate to swap A and B2<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 6em; border: solid 1px currentcolor;\">B1<\/td>\n<td style=\"width: 4em; border: solid 1px currentcolor;\">B2<\/td>\n<td style=\"width: 6em; border: solid 1px currentcolor; background: lch(from currentcolor l c h \/ .1);\" colspan=\"2\">A<\/td>\n<td>&nbsp;<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>In both cases, the recursive call is strictly smaller than the original call because we know that both A and B are nonempty: If either was empty, we would have performed a nop early-exit. Therefore, at least one element will be swapped before we reach the recursive call, and we consequently know that the recursion will eventually terminate.<\/p>\n<p>The final case is where the A and B blocks are the same size. In that case, we have swapped all the B elements to the first half and all the A elements to the second half.<\/p>\n<table style=\"border-collapse: collapse; text-align: center;\" title=\"A large block of memory labeled A, followed a smaller one labeled B\" border=\"0\" cellspacing=\"0\" cellpadding=\"1\">\n<tbody>\n<tr>\n<td style=\"width: 6em; border: solid 1px currentcolor;\">B<\/td>\n<td style=\"width: 6em; border: solid 1px currentcolor; background: lch(from currentcolor l c h \/ .1);\">A<\/td>\n<td>&nbsp;<\/td>\n<\/tr>\n<tr style=\"text-align: left;\">\n<td style=\"width: 6em;\">\u00a0<\/td>\n<td style=\"width: 6em;\">\u2191<\/td>\n<td style=\"width: 6em;\">\u2191<\/td>\n<\/tr>\n<tr style=\"text-align: left;\">\n<td style=\"width: 6em;\">\u00a0<\/td>\n<td style=\"width: 7em;\">first<\/td>\n<td style=\"width: 6em;\">mid<br \/>\nlast<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>If we are lucky to get here, then we are done!<\/p>\n<p>Note that we don&#8217;t need a special case handler for the equal-sized blocks case. We can treat as either the first or second case and let the early-out in the recursive call realize that there is nothing to do.<\/p>\n<p>The number of swaps is <var>n<\/var>. You can calculate this recursively, since we perform <var>k<\/var> swaps to move the smaller block, and the recursive call (by induction) performs <var>n<\/var> \u2212 <var>k<\/var> swaps, for a total of <var>n<\/var>. You can also calculate this directly by observing that at each step, one element gets swapped into its final position (namely, at <code>*first<\/code>, just before we increment it).<\/p>\n<p>Even though this algorithm and the bidirectional-iterator version both perform <var>n<\/var> swaps, the bidirectional-iterator version has better locality of reference, so it is preferred if available.<\/p>\n<p>Next time, we&#8217;ll apply this to our original problem.<\/p>\n<p><b>Bonus chatter<\/b>: You don&#8217;t need to do a preliminary <code>std::<wbr \/>distance<\/code> to figure out whether block A or block B is smaller. You can just start swapping elements, and make a note of which happens first: Does <code>first<\/code> reach the original <code>mid<\/code> (which means that the A block is smaller) or does <code>mid<\/code> reach <code>last<\/code> (which means that the B block is smaller). This &#8220;figure it out as you go&#8221; doesn&#8217;t change the complexity, but it does lower the constant a little bit because you don&#8217;t have to iterate through all of the larger block just to realize that it&#8217;s took big.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A different algorithm, employing a different kind of cleverness.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-111958","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>A different algorithm, employing a different kind of cleverness.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/111958","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=111958"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/111958\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=111958"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=111958"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=111958"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}