{"id":111962,"date":"2026-01-05T07:00:00","date_gmt":"2026-01-05T15:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=111962"},"modified":"2026-01-03T08:01:34","modified_gmt":"2026-01-03T16:01:34","slug":"20260105-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20260105-00\/?p=111962","title":{"rendered":"How can you swap two non-adjacent blocks of memory using only forward iterators?"},"content":{"rendered":"<p>Last time, we looked at <a title=\"How can you swap two adjacent blocks of memory using only forward iterators?\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20260102-00\/?p=111958\"> how you can swap two adjacent blocks of memory using only forward iterators<\/a> and noted that we can try to use the same trick to develop a forward-only solution to the problem of <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\"> swapping two non-adjacent blocks of memory<\/a>.<\/p>\n<p>Our original diagram looked like this, with a block of memory of the form A1, A2, B1, B2, C1, C2, D1, D2, D3, E1, and the goal of swapping the B&#8217;s and D&#8217;s, producing A1, A2, D1, D2, D3, C1, C2, B1, B2, E1.<\/p>\n<table style=\"border-collapse: collapse; text-align: center;\" title=\"See text above\" border=\"0\" cellspacing=\"0\" cellpadding=\"1\">\n<tbody>\n<tr>\n<td style=\"width: 2em; border: solid 1px currentcolor;\">A1<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor;\">A2<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor; background: lch(from currentcolor l c h \/ .1);\">B1<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor; background: lch(from currentcolor l c h \/ .1);\">B2<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor;\">C1<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor;\">C2<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor; background-image: repeating-linear-gradient(45deg, transparent, transparent .5em, lch(from currentcolor l c h \/ .2) .5em, lch(from currentcolor l c h \/ .2) 1em);\">D1<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor; background-image: repeating-linear-gradient(45deg, lch(from currentcolor l c h \/ .2), lch(from currentcolor l c h \/ .2) .5em, transparent .5em, transparent 1em);\">D2<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor; background-image: repeating-linear-gradient(45deg, transparent, transparent .5em, lch(from currentcolor l c h \/ .2) .5em, lch(from currentcolor l c h \/ .2) 1em);\">D3<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor;\">E1<\/td>\n<\/tr>\n<tr style=\"height: 1ex;\">\n<td colspan=\"10\"><!-- --><\/td>\n<\/tr>\n<tr style=\"height: 1ex;\">\n<td colspan=\"2\"><!-- --><\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\" colspan=\"2\"><!-- --><\/td>\n<td colspan=\"2\"><!-- --><\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\" colspan=\"3\"><!-- --><\/td>\n<td colspan=\"1\"><!-- --><\/td>\n<\/tr>\n<tr>\n<td colspan=\"4\">\u00a0<\/td>\n<td colspan=\"1\">\u00a0<\/td>\n<td colspan=\"1\">\u2929<\/td>\n<td colspan=\"4\">\u00a0<\/td>\n<\/tr>\n<tr style=\"height: 1ex;\">\n<td colspan=\"2\"><!-- --><\/td>\n<td style=\"border: solid 1px currentcolor; border-bottom: none;\" colspan=\"3\"><!-- --><\/td>\n<td colspan=\"2\"><!-- --><\/td>\n<td style=\"border: solid 1px currentcolor; border-bottom: none;\" colspan=\"2\"><!-- --><\/td>\n<td colspan=\"1\"><!-- --><\/td>\n<\/tr>\n<tr style=\"height: 1ex;\">\n<td colspan=\"10\"><!-- --><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 2em; border: solid 1px currentcolor;\">A1<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor;\">A2<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor; background-image: repeating-linear-gradient(45deg, transparent, transparent .5em, lch(from currentcolor l c h \/ .2) .5em, lch(from currentcolor l c h \/ .2) 1em);\">D1<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor; background-image: repeating-linear-gradient(45deg, lch(from currentcolor l c h \/ .2), lch(from currentcolor l c h \/ .2) .5em, transparent .5em, transparent 1em);\">D2<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor; background-image: repeating-linear-gradient(45deg, transparent, transparent .5em, lch(from currentcolor l c h \/ .2) .5em, lch(from currentcolor l c h \/ .2) 1em);\">D3<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor;\">C1<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor;\">C2<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor; background: lch(from currentcolor l c h \/ .1);\">B1<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor; background: lch(from currentcolor l c h \/ .1);\">B2<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor;\">E1<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The first thing we&#8217;ll do is get rid of the A&#8217;s and E&#8217;s, since they aren&#8217;t really participants at all.<\/p>\n<table style=\"border-collapse: collapse; text-align: center;\" title=\"See text above\" border=\"0\" cellspacing=\"0\" cellpadding=\"1\">\n<tbody>\n<tr>\n<td style=\"width: 2em; border: solid 1px currentcolor; background: lch(from currentcolor l c h \/ .1);\">B1<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor; background: lch(from currentcolor l c h \/ .1);\">B2<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor;\">C1<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor;\">C2<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor; background-image: repeating-linear-gradient(45deg, transparent, transparent .5em, lch(from currentcolor l c h \/ .2) .5em, lch(from currentcolor l c h \/ .2) 1em);\">D1<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor; background-image: repeating-linear-gradient(45deg, lch(from currentcolor l c h \/ .2), lch(from currentcolor l c h \/ .2) .5em, transparent .5em, transparent 1em);\">D2<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor; background-image: repeating-linear-gradient(45deg, transparent, transparent .5em, lch(from currentcolor l c h \/ .2) .5em, lch(from currentcolor l c h \/ .2) 1em);\">D3<\/td>\n<\/tr>\n<tr style=\"height: 1ex;\">\n<td colspan=\"7\"><!-- --><\/td>\n<\/tr>\n<tr style=\"height: 1ex;\">\n<td style=\"border: solid 1px currentcolor; border-top: none;\" colspan=\"2\"><!-- --><\/td>\n<td colspan=\"2\"><!-- --><\/td>\n<td style=\"border: solid 1px currentcolor; border-top: none;\" colspan=\"3\"><!-- --><\/td>\n<\/tr>\n<tr>\n<td colspan=\"2\">\u00a0<\/td>\n<td colspan=\"1\">\u00a0<\/td>\n<td colspan=\"1\">\u2929<\/td>\n<td colspan=\"4\">\u00a0<\/td>\n<\/tr>\n<tr style=\"height: 1ex;\">\n<td style=\"border: solid 1px currentcolor; border-bottom: none;\" colspan=\"3\"><!-- --><\/td>\n<td colspan=\"2\"><!-- --><\/td>\n<td style=\"border: solid 1px currentcolor; border-bottom: none;\" colspan=\"2\"><!-- --><\/td>\n<\/tr>\n<tr style=\"height: 1ex;\">\n<td colspan=\"7\"><!-- --><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 2em; border: solid 1px currentcolor; background-image: repeating-linear-gradient(45deg, transparent, transparent .5em, lch(from currentcolor l c h \/ .2) .5em, lch(from currentcolor l c h \/ .2) 1em);\">D1<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor; background-image: repeating-linear-gradient(45deg, lch(from currentcolor l c h \/ .2), lch(from currentcolor l c h \/ .2) .5em, transparent .5em, transparent 1em);\">D2<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor; background-image: repeating-linear-gradient(45deg, transparent, transparent .5em, lch(from currentcolor l c h \/ .2) .5em, lch(from currentcolor l c h \/ .2) 1em);\">D3<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor;\">C1<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor;\">C2<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor; background: lch(from currentcolor l c h \/ .1);\">B1<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor; background: lch(from currentcolor l c h \/ .1);\">B2<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>If either the B or D block is empty, then we are left with a rotation, and <!-- backref: How can you swap two adjacent blocks of memory using only forward iterators? --> we already know how to do that using only forward iterators.<\/p>\n<p>Otherwise, start with <code>first<\/code> pointing at the start of B and <code>mid<\/code> pointing at the start of D.<\/p>\n<table style=\"border-collapse: collapse; text-align: center;\" title=\"See text\" border=\"0\" cellspacing=\"0\" cellpadding=\"1\">\n<tbody>\n<tr>\n<td style=\"width: 2em; border: solid 1px currentcolor; background: lch(from currentcolor l c h \/ .1);\">B1<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor; background: lch(from currentcolor l c h \/ .1);\">B2<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor; background: lch(from currentcolor l c h \/ .1);\">B3<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor;\">C1<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor;\">C2<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor; background-image: repeating-linear-gradient(45deg, transparent, transparent .5em, lch(from currentcolor l c h \/ .2) .5em, lch(from currentcolor l c h \/ .2) 1em);\">D1<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor; background-image: repeating-linear-gradient(45deg, lch(from currentcolor l c h \/ .2), lch(from currentcolor l c h \/ .2) .5em, transparent .5em, transparent 1em);\">D2<\/td>\n<td>&nbsp;<\/td>\n<\/tr>\n<tr style=\"text-align: left;\">\n<td style=\"width: 2em;\">\u2191<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"width: 2em;\">\u2191<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"width: 2em;\">\u2191<\/td>\n<\/tr>\n<tr style=\"text-align: left;\">\n<td style=\"width: 10em;\" colspan=\"5\">first<\/td>\n<td style=\"width: 4em;\" colspan=\"2\">mid<\/td>\n<td style=\"width: 3em;\">last<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Walk forward from <code>first<\/code> and <code>mid<\/code>, swapping the initial elements from B and D, until you either run out of B elements or run out of D elements.<\/p>\n<p>Again, there are three cases.<\/p>\n<p>If the B block is bigger than the D block, then our first pass finishes with the <code>first<\/code> pointer somewhere in the middle of the B block and the <code>mid<\/code> pointer making it all the way to the <code>last<\/code>.<\/p>\n<table style=\"border-collapse: collapse; text-align: center;\" title=\"See text\" border=\"0\" cellspacing=\"0\" cellpadding=\"1\">\n<tbody>\n<tr>\n<td style=\"width: 2em; border: solid 1px currentcolor; background-image: repeating-linear-gradient(45deg, transparent, transparent .5em, lch(from currentcolor l c h \/ .2) .5em, lch(from currentcolor l c h \/ .2) 1em);\">D1<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor; background-image: repeating-linear-gradient(45deg, lch(from currentcolor l c h \/ .2), lch(from currentcolor l c h \/ .2) .5em, transparent .5em, transparent 1em);\">D2<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor; background: lch(from currentcolor l c h \/ .1);\">B3<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor;\">C1<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor;\">C2<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor; background: lch(from currentcolor l c h \/ .1);\">B1<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor; background: lch(from currentcolor l c h \/ .1);\">B2<\/td>\n<td>&nbsp;<\/td>\n<\/tr>\n<tr style=\"text-align: left;\">\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"width: 2em;\">\u2191<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"width: 2em;\">\u2191<\/td>\n<\/tr>\n<tr style=\"text-align: left;\">\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"width: 10em;\" colspan=\"5\">first<\/td>\n<td>mid<br \/>\nlast<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The entire D block is in its final position, and getting the B3 block to the end is a rotation of [<code>first<\/code>, <code>last<\/code>) that moves C1 to the front, and we can use the existing forward-only rotation algorithm to finish the job.<\/p>\n<p>The second case is that the D block is bigger than the B block. In this case, we finish with the <code>first<\/code> pointer at the end of the original B block and the <code>mid<\/code> in the middle of the original D block.<\/p>\n<table style=\"border-collapse: collapse; text-align: center;\" title=\"See text\" border=\"0\" cellspacing=\"0\" cellpadding=\"1\">\n<tbody>\n<tr>\n<td style=\"width: 2em; border: solid 1px currentcolor; background-image: repeating-linear-gradient(45deg, transparent, transparent .5em, lch(from currentcolor l c h \/ .2) .5em, lch(from currentcolor l c h \/ .2) 1em);\">D1<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor; background-image: repeating-linear-gradient(45deg, lch(from currentcolor l c h \/ .2), lch(from currentcolor l c h \/ .2) .5em, transparent .5em, transparent 1em);\">D2<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor;\">C1<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor;\">C2<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor; background: lch(from currentcolor l c h \/ .1);\">B1<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor; background: lch(from currentcolor l c h \/ .1);\">B2<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor; background-image: repeating-linear-gradient(45deg, transparent, transparent .5em, lch(from currentcolor l c h \/ .2) .5em, lch(from currentcolor l c h \/ .2) 1em);\">D3<\/td>\n<td>&nbsp;<\/td>\n<\/tr>\n<tr style=\"text-align: left;\">\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"width: 2em;\">\u2191<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"width: 2em;\">\u2191<\/td>\n<td style=\"width: 2em;\">\u2191<\/td>\n<\/tr>\n<tr style=\"text-align: left;\">\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"width: 2em;\">\u00a0<\/td>\n<td style=\"width: 10em;\" colspan=\"4\">first<\/td>\n<td style=\"width: 2em;\">mid<\/td>\n<td>last<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Again, we can finish the job with a forward-only rotation, this time rotating the [<code>first<\/code>, <code>last<\/code>) block to put <code>mid<\/code> at the front.<\/p>\n<p>The final case is that there are exactly the same number of B&#8217;s and D&#8217;s: All of the D&#8217;s have moved to the front and all of the B&#8217;s have moved to the back.<\/p>\n<table style=\"border-collapse: collapse; text-align: center;\" title=\"See text above\" border=\"0\" cellspacing=\"0\" cellpadding=\"1\">\n<tbody>\n<tr>\n<td style=\"width: 2em; border: solid 1px currentcolor; background-image: repeating-linear-gradient(45deg, transparent, transparent .5em, lch(from currentcolor l c h \/ .2) .5em, lch(from currentcolor l c h \/ .2) 1em);\">D1<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor; background-image: repeating-linear-gradient(45deg, lch(from currentcolor l c h \/ .2), lch(from currentcolor l c h \/ .2) .5em, transparent .5em, transparent 1em);\">D2<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor;\">C1<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor;\">C2<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor; background: lch(from currentcolor l c h \/ .1);\">B1<\/td>\n<td style=\"width: 2em; border: solid 1px currentcolor; background: lch(from currentcolor l c h \/ .1);\">B2<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>In this case, we are finished.<\/p>\n<p>This final case does not need to be treated as a special case. We can just treat it as either of the first two cases, and the right thing will happen since the final forward-only rotation will realize that there is nothing to rotate. In fact, the vacuous case at the start (where either there are no B&#8217;s or no D&#8217;s) does not need to be treated as a special case either.<\/p>\n<p>This algorithm performs <var>n<\/var> swaps because we perform <var>k<\/var> swaps in the first phase, and the rotation in the second phase is known to perform <var>n<\/var>\u00a0\u2212\u00a0<var>k<\/var> swaps. You can also calculate this directly by observing that every swap moves one element to its final position.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Applying the rotation trick to our new problem.<\/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-111962","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Applying the rotation trick to our new problem.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/111962","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=111962"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/111962\/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=111962"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=111962"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=111962"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}