{"id":31056,"date":"2026-10-08T11:06:13","date_gmt":"2026-10-08T11:06:13","guid":{"rendered":"https:\/\/www.codemonkey.com\/?page_id=31056"},"modified":"2026-10-29T16:55:21","modified_gmt":"2026-10-29T16:55:21","slug":"sorting-algorithms","status":"publish","type":"page","link":"https:\/\/www.codemonkey.com\/ru\/interactive-cs-tools\/sorting-algorithms\/","title":{"rendered":"\u0410\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u044b \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0438"},"content":{"rendered":"\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>Sorting Visualizer<\/title>\n<link rel=\"preconnect\" href=\"https:\/\/fonts.googleapis.com\">\n<link rel=\"preconnect\" href=\"https:\/\/fonts.gstatic.com\" crossorigin>\n<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Poppins:wght@400;500;600;700;800\" rel=\"stylesheet\">\n<link href=\"https:\/\/fonts.googleapis.com\/css2?family=JetBrains+Mono:wght@400;600\" rel=\"stylesheet\">\n<style>\n  :root{\n    --brown-dark:#39261F; --brown:#795535; --tan:#BF8653; --yellow:#FFC62F;\n    --lime:#9BB33F; --green:#4B571A; --gray:#54595F; --blue:#79ABCB;\n    --sky:#B0D1E5; --purple:#7A6796; --pink:#C64F61; --red:#B2372A;\n    --white:#ffffff;\n    --tint:rgba(176,209,229,.22);\n    --yellow-tint:rgba(255,198,47,.16);\n  }\n  *{box-sizing:border-box}\n  body{margin:0;font-family:'Poppins',system-ui,sans-serif;color:var(--brown-dark);background:var(--white);line-height:1.55;-webkit-font-smoothing:antialiased}\n  h1,h2,h3{font-family:'Poppins',sans-serif;margin:0}\n  [hidden]{display:none !important}\n\n  \/* ---------- Hero ---------- *\/\n  .hero{position:relative;overflow:hidden;color:var(--white);text-align:center;padding:52px 16px 110px}\n  .eyebrow{position:relative;display:inline-block;font-size:12px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;background:rgba(255,255,255,.14);padding:6px 14px;border-radius:999px;margin-bottom:14px}\n  .hero h1{position:relative;font-weight:800;text-transform:uppercase;letter-spacing:.01em;font-size:clamp(30px,5.4vw,52px);line-height:1.08;color:var(--yellow)}\n  .hero p{position:relative;max-width:600px;margin:12px auto 0;font-size:16px;opacity:.95}\n  .wave{position:absolute;left:0;right:0;bottom:-1px;width:100%;height:60px;display:block}\n\n  .hero{background-color:var(--green);background-image:radial-gradient(ellipse 460px 150px at 50% 50%,#4B571A 55%,rgba(75,87,26,0) 100%),url(\"data:image\/svg+xml,%3Csvg xmlns='http:\/\/www.w3.org\/2000\/svg' width='280' height='280' viewBox='0 0 280 280'%3E%3Cdefs%3E%3Cg id='b'%3E%3Cpath d='M262 572 C330 605 400 618 470 616 C560 612 650 560 712 500 C750 465 785 430 810 402 L843 406 C853 462 851 560 791 630 C731 700 621 748 506 748 C401 748 311 680 258 592 Z' fill='%23E6B94A'\/%3E %3Cpath d='M268 578 C340 612 410 622 470 620 C565 616 655 562 712 505 C750 467 790 428 812 405 C790 470 730 560 640 610 C590 638 540 650 480 652 C400 652 322 622 266 592 Z' fill='%23CDA144'\/%3E %3Cpath d='M262 572 C330 605 400 618 470 616 C560 612 650 560 712 500 C750 465 785 430 810 402 L843 406 C853 462 851 560 791 630 C731 700 621 748 506 748 C401 748 311 680 258 592 Z' fill='none' stroke='%23231F20' stroke-width='10' stroke-linejoin='round'\/%3E %3Cg fill='none' stroke='%23231F20' stroke-width='10' stroke-linecap='butt'%3E %3Cpath d='M302 618 C360 655 420 690 505 692 C620 694 730 610 812 518'\/%3E %3Cpath d='M562 648 C660 610 760 530 815 418'\/%3E %3Cpath d='M780 516 C795 485 808 452 818 420'\/%3E %3C\/g%3E %3Cpath d='M808 405 L826 340 L848 345 L843 408 C835 420 818 422 808 405 Z' fill='%23644E37' stroke='%23231F20' stroke-width='10' stroke-linejoin='round'\/%3E %3Cpath d='M249 555 C246 570 251 584 259 594 C269 588 277 580 282 572 Z' fill='%23644E37' stroke='%23231F20' stroke-width='10' stroke-linejoin='round'\/%3E%3C\/g%3E%3C\/defs%3E%3Cg opacity='.85'%3E%3Cuse href='%23b' transform='translate(55 60) rotate(-15) scale(0.11) translate(-540 -545)'\/%3E%3Cuse href='%23b' transform='translate(185 150) rotate(25) scale(0.09) translate(-540 -545)'\/%3E%3Cuse href='%23b' transform='translate(80 215) rotate(160) scale(0.1) translate(-540 -545)'\/%3E%3Cuse href='%23b' transform='translate(230 40) rotate(-50) scale(0.08) translate(-540 -545)'\/%3E%3C\/g%3E%3C\/svg%3E\");background-size:auto,280px;background-position:center,0 0;background-repeat:no-repeat,repeat}\n  .hero .bb{position:absolute;pointer-events:none}\n  .hero .bb svg{width:100%;height:auto;display:block}\n  .hero .bb.l{width:160px;left:max(16px,calc(50% - 630px));top:92px;transform:rotate(-12deg)}\n  .hero .bb.r{width:125px;right:max(16px,calc(50% - 610px));top:28px;transform:scaleX(-1) rotate(-18deg)}\n  @media (max-width:1180px){.hero .bb.l{width:96px;top:150px}.hero .bb.r{width:80px;top:14px}}\n  @media (max-width:640px){.hero .bb.l{width:58px;left:6px;top:36px}.hero .bb.r{width:50px;right:6px;top:8px}}\n  .eyebrow{text-decoration:none;color:var(--white);transition:background .15s}\n  .eyebrow:hover{background:rgba(255,255,255,.24)}\n\n\n  \/* ---------- Layout ---------- *\/\n  .wrap{max-width:1120px;margin:-64px auto 48px;padding:0 16px;position:relative}\n  .card{background:var(--white);border-radius:24px;box-shadow:0 12px 34px rgba(57,38,31,.13);padding:24px}\n  .topline{display:flex;flex-wrap:wrap;gap:14px 20px;align-items:flex-start;justify-content:space-between}\n  .main-grid{display:grid;grid-template-columns:minmax(0,1fr) 320px;gap:24px;margin-top:20px}\n  @media (max-width:900px){.main-grid{grid-template-columns:1fr}}\n\n  \/* ---------- Controls ---------- *\/\n  .label{display:block;font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.07em;color:var(--gray);margin-bottom:8px}\n  .chips{display:flex;flex-wrap:wrap;gap:8px}\n  .chip{font:600 14px 'Poppins',sans-serif;color:var(--brown-dark);background:var(--white);border:2px solid var(--sky);border-radius:999px;padding:8px 16px;cursor:pointer;transition:background .15s,border-color .15s,transform .08s}\n  .chip:hover{border-color:var(--blue)}\n  .chip[aria-pressed=\"true\"]{background:var(--yellow);border-color:var(--yellow);box-shadow:0 3px 0 var(--tan)}\n  .chip:active{transform:translateY(2px)}\n\n  .level{display:inline-flex;background:var(--tint);border-radius:999px;padding:4px;gap:4px}\n  .level button{font:700 14px 'Poppins',sans-serif;border:none;background:transparent;color:var(--gray);border-radius:999px;padding:8px 18px;cursor:pointer}\n  .level button[aria-pressed=\"true\"]{background:var(--brown-dark);color:var(--yellow)}\n  .level-note{font-size:12px;color:var(--gray);margin-top:6px;text-align:right}\n  @media (max-width:640px){.lvl{order:-1}.lvl .label,.lvl .level-note{text-align:left !important}}\n\n  .settings{display:flex;flex-wrap:wrap;gap:20px 28px;align-items:flex-end;margin-top:20px}\n  .field{min-width:150px}\n  .field .val{font-weight:700;color:var(--brown)}\n  select{font:600 14px 'Poppins',sans-serif;color:var(--brown-dark);background:var(--white) url(\"data:image\/svg+xml,%3Csvg xmlns='http:\/\/www.w3.org\/2000\/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%2339261F' stroke-width='2' fill='none' stroke-linecap='round'\/%3E%3C\/svg%3E\") no-repeat right 16px center;border:2px solid var(--sky);border-radius:999px;padding:9px 40px 9px 16px;appearance:none;-webkit-appearance:none;cursor:pointer}\n  select:focus-visible,.chip:focus-visible,.btn:focus-visible,.level button:focus-visible,input[type=range]:focus-visible,.eyebrow:focus-visible{outline:3px solid var(--purple);outline-offset:2px}\n  input[type=range]{-webkit-appearance:none;appearance:none;width:100%;height:8px;border-radius:999px;background:var(--sky);cursor:pointer}\n  input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;width:22px;height:22px;border-radius:50%;background:var(--yellow);border:3px solid var(--brown-dark)}\n  input[type=range]::-moz-range-thumb{width:16px;height:16px;border-radius:50%;background:var(--yellow);border:3px solid var(--brown-dark)}\n\n  .btn{font:700 15px 'Poppins',sans-serif;border:none;border-radius:999px;padding:12px 22px;cursor:pointer;background:var(--yellow);color:var(--brown-dark);box-shadow:0 4px 0 var(--tan);display:inline-flex;align-items:center;justify-content:center;gap:8px;transition:transform .08s,box-shadow .08s}\n  .btn:active{transform:translateY(3px);box-shadow:0 1px 0 var(--tan)}\n  .btn.secondary{background:var(--white);border:2px solid var(--sky);box-shadow:0 4px 0 var(--sky);padding:10px 18px}\n  .btn.secondary:active{box-shadow:0 1px 0 var(--sky)}\n  .btn.icon{width:48px;height:48px;padding:0}\n  .btn.play{min-width:132px;text-transform:uppercase;letter-spacing:.04em}\n  .btn:disabled{opacity:.4;cursor:not-allowed;transform:none}\n  .btn svg{width:18px;height:18px;fill:currentColor}\n\n  \/* ---------- Stage ---------- *\/\n  .stage{background:var(--tint);border-radius:20px;padding:30px 16px 10px;display:flex;flex-direction:column}\n  .bars{display:flex;align-items:flex-end;height:320px;gap:var(--gap,4px)}\n  .bar{flex:1 1 0;min-width:2px;background:var(--blue);border-radius:6px 6px 0 0;position:relative;transition:height .12s ease,background-color .12s ease}\n  .bar span{position:absolute;bottom:100%;left:50%;transform:translateX(-50%);margin-bottom:4px;font-size:11px;font-weight:700;color:var(--gray);white-space:nowrap}\n  .bar.dim{background:var(--sky);opacity:.55}\n  .bar.done{background:var(--lime)}\n  .bar.cmp{background:var(--yellow)}\n  .bar.piv{background:var(--purple)}\n  .bar.swp{background:var(--pink)}\n  .bar.cmp span,.bar.swp span,.bar.piv span{color:var(--brown-dark)}\n  .ptrs{display:flex;gap:var(--gap,4px);height:26px;margin-top:6px;border-top:3px solid var(--brown-dark);padding-top:5px}\n  .ptrs div{flex:1 1 0;min-width:2px;text-align:center;position:relative}\n  .ptrs b{display:inline-block;font-family:'JetBrains Mono',monospace;font-size:11px;font-weight:600;background:var(--brown-dark);color:var(--yellow);border-radius:6px;padding:0 5px;line-height:17px;white-space:nowrap;position:relative;z-index:1}\n  .ptrs.tight b{font-size:9px;padding:0 3px;line-height:14px}\n  @media (max-width:600px){.bars{height:220px}.stage{padding:26px 10px 8px}.bar span{font-size:9px}}\n\n  .legend{display:flex;flex-wrap:wrap;gap:6px 16px;margin:12px 2px 0;font-size:13px;color:var(--gray)}\n  .legend i{display:inline-block;width:14px;height:14px;border-radius:4px;vertical-align:-2px;margin-right:6px}\n\n  .transport{display:flex;flex-wrap:wrap;align-items:center;gap:12px 14px;margin-top:16px}\n  .transport .speed{display:flex;align-items:center;gap:10px;margin-left:auto;min-width:200px;flex:0 1 260px}\n  .transport .speed .label{margin:0;white-space:nowrap}\n  .transport .speed .val{font-weight:700;color:var(--brown)}\n  @media (max-width:600px){.transport .speed{margin-left:0;flex:1 1 100%}}\n  .scrub{display:flex;align-items:center;gap:12px;margin-top:14px}\n  .scrub .count{font-size:13px;font-weight:600;color:var(--gray);white-space:nowrap;min-width:72px;text-align:right}\n\n  .narration{margin-top:14px;border:2px dashed var(--sky);border-radius:16px;padding:14px 18px;font-weight:500;min-height:56px;display:flex;gap:12px;align-items:flex-start}\n  .narration .dot{flex:none;width:12px;height:12px;border-radius:50%;background:var(--yellow);margin-top:7px;box-shadow:0 0 0 4px var(--yellow-tint)}\n\n  \/* ---------- Side panel ---------- *\/\n  .side h3{font-weight:700;font-size:15px;text-transform:uppercase;letter-spacing:.06em;margin-bottom:10px}\n  .side h3 + *{margin-bottom:18px}\n  .code{background:var(--brown-dark);color:rgba(255,255,255,.82);border-radius:18px;padding:12px 0;font-family:'JetBrains Mono',ui-monospace,monospace;font-size:12px;overflow-x:auto}\n  .code .ln{padding:3px 14px 3px 10px;white-space:pre;border-left:4px solid transparent;transition:background .1s}\n  .code .ln.active{background:rgba(255,198,47,.16);border-left-color:var(--yellow);color:var(--yellow);font-weight:600}\n  .recipe{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px;counter-reset:r}\n  .recipe li{counter-increment:r;display:flex;gap:10px;align-items:flex-start;background:var(--tint);border-radius:14px;padding:9px 12px;font-size:14px;font-weight:500;transition:background .15s}\n  .recipe li::before{content:counter(r);flex:none;width:24px;height:24px;border-radius:50%;background:var(--white);font-weight:800;font-size:13px;display:flex;align-items:center;justify-content:center}\n  .recipe li.active{background:var(--yellow);box-shadow:0 3px 0 var(--tan)}\n  .recipe li.active::before{background:var(--brown-dark);color:var(--yellow)}\n  .vars{background:var(--tint);border-radius:16px;padding:6px 14px;min-height:46px}\n  .vars .row{display:flex;justify-content:space-between;gap:12px;padding:6px 0;border-bottom:1px solid var(--white);font-size:14px}\n  .vars .row:last-child{border-bottom:none}\n  .vars .row .k{font-weight:600;color:var(--gray)}\n  .vars .row .v{font-weight:800}\n  .vars.adv .row{font-family:'JetBrains Mono',monospace;font-size:13px}\n  .vars.adv .row .k{color:var(--purple)}\n  .vars .row.changed .v{background:var(--yellow);border-radius:6px;padding:0 6px}\n  .vars .none{font-size:13px;color:var(--gray);padding:8px 0}\n  .stats{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}\n  .stat{background:var(--tint);border-radius:16px;padding:12px 8px;text-align:center}\n  .stat b{display:block;font-weight:800;font-size:24px;line-height:1.1}\n  .stat small{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--gray)}\n  .stat.c b{color:var(--brown)} .stat.m b{color:var(--pink)} .stat.s b{color:var(--green)}\n\n  \/* ---------- Info ---------- *\/\n  .info{display:grid;grid-template-columns:1.3fr 1fr;gap:24px;margin-top:24px}\n  @media (max-width:800px){.info{grid-template-columns:1fr}}\n  .info h2{font-weight:800;font-size:clamp(22px,3vw,28px);text-transform:uppercase;margin-bottom:10px}\n  .info h2 em{font-style:normal;color:var(--tan)}\n  .bullets{list-style:none;padding:0;margin:14px 0 0}\n  .bullets li{padding-left:28px;position:relative;margin-bottom:8px;font-weight:500}\n  .bullets li::before{content:\"\";position:absolute;left:0;top:7px;width:14px;height:14px;border-radius:50%;background:var(--yellow);box-shadow:0 0 0 4px var(--yellow-tint)}\n  table{width:100%;border-collapse:collapse;font-size:14px}\n  td{padding:10px 4px;border-bottom:1px solid var(--sky)}\n  td:last-child{text-align:right;font-family:'JetBrains Mono',monospace;font-weight:600}\n  tr:last-child td{border-bottom:none}\n  .meter{display:flex;gap:6px;margin:6px 0 10px}\n  .meter span{width:44px;opacity:.22;filter:grayscale(1)}\n  .meter span.on{opacity:1;filter:none}\n  .meter svg{width:100%;height:auto;display:block}\n  .speedword{font-weight:800;font-size:20px;text-transform:uppercase}\n  .explain{margin-top:14px;background:var(--tint);border-radius:16px;padding:12px 16px;font-size:14px}\n  .explain b{font-family:'JetBrains Mono',monospace}\n  .tip{margin-top:18px;background:var(--yellow-tint);border-radius:16px;padding:14px 18px;border-left:6px solid var(--yellow)}\n  .tip strong{display:block;font-weight:700;text-transform:uppercase;font-size:12px;letter-spacing:.08em;color:var(--brown);margin-bottom:2px}\n\n  footer{text-align:center;font-size:13px;color:var(--gray);padding:0 16px 32px}\n<\/style>\n<\/head>\n<body>\n\n<header class=\"hero\">\n  <div class=\"bb l\"><svg viewBox=\"215 325 650 470\" aria-hidden=\"true\"><path d=\"M225 640 C240 628 255 650 265 648 C330 645 410 700 520 718 C610 728 690 705 725 688 C690 740 610 782 505 778 C400 774 300 745 262 705 C242 685 214 662 225 640 Z\" fill=\"#000\" fill-opacity=\".2\"\/><path d=\"M262 572 C330 605 400 618 470 616 C560 612 650 560 712 500 C750 465 785 430 810 402 L843 406 C853 462 851 560 791 630 C731 700 621 748 506 748 C401 748 311 680 258 592 Z\" fill=\"#E6B94A\"\/> <path d=\"M268 578 C340 612 410 622 470 620 C565 616 655 562 712 505 C750 467 790 428 812 405 C790 470 730 560 640 610 C590 638 540 650 480 652 C400 652 322 622 266 592 Z\" fill=\"#CDA144\"\/> <path d=\"M262 572 C330 605 400 618 470 616 C560 612 650 560 712 500 C750 465 785 430 810 402 L843 406 C853 462 851 560 791 630 C731 700 621 748 506 748 C401 748 311 680 258 592 Z\" fill=\"none\" stroke=\"#231F20\" stroke-width=\"10\" stroke-linejoin=\"round\"\/> <g fill=\"none\" stroke=\"#231F20\" stroke-width=\"10\" stroke-linecap=\"butt\"> <path d=\"M302 618 C360 655 420 690 505 692 C620 694 730 610 812 518\"\/> <path d=\"M562 648 C660 610 760 530 815 418\"\/> <path d=\"M780 516 C795 485 808 452 818 420\"\/> <\/g> <path d=\"M808 405 L826 340 L848 345 L843 408 C835 420 818 422 808 405 Z\" fill=\"#644E37\" stroke=\"#231F20\" stroke-width=\"10\" stroke-linejoin=\"round\"\/> <path d=\"M249 555 C246 570 251 584 259 594 C269 588 277 580 282 572 Z\" fill=\"#644E37\" stroke=\"#231F20\" stroke-width=\"10\" stroke-linejoin=\"round\"\/><\/svg><\/div><div class=\"bb r\"><svg viewBox=\"215 325 650 470\" aria-hidden=\"true\"><path d=\"M225 640 C240 628 255 650 265 648 C330 645 410 700 520 718 C610 728 690 705 725 688 C690 740 610 782 505 778 C400 774 300 745 262 705 C242 685 214 662 225 640 Z\" fill=\"#000\" fill-opacity=\".2\"\/><path d=\"M262 572 C330 605 400 618 470 616 C560 612 650 560 712 500 C750 465 785 430 810 402 L843 406 C853 462 851 560 791 630 C731 700 621 748 506 748 C401 748 311 680 258 592 Z\" fill=\"#E6B94A\"\/> <path d=\"M268 578 C340 612 410 622 470 620 C565 616 655 562 712 505 C750 467 790 428 812 405 C790 470 730 560 640 610 C590 638 540 650 480 652 C400 652 322 622 266 592 Z\" fill=\"#CDA144\"\/> <path d=\"M262 572 C330 605 400 618 470 616 C560 612 650 560 712 500 C750 465 785 430 810 402 L843 406 C853 462 851 560 791 630 C731 700 621 748 506 748 C401 748 311 680 258 592 Z\" fill=\"none\" stroke=\"#231F20\" stroke-width=\"10\" stroke-linejoin=\"round\"\/> <g fill=\"none\" stroke=\"#231F20\" stroke-width=\"10\" stroke-linecap=\"butt\"> <path d=\"M302 618 C360 655 420 690 505 692 C620 694 730 610 812 518\"\/> <path d=\"M562 648 C660 610 760 530 815 418\"\/> <path d=\"M780 516 C795 485 808 452 818 420\"\/> <\/g> <path d=\"M808 405 L826 340 L848 345 L843 408 C835 420 818 422 808 405 Z\" fill=\"#644E37\" stroke=\"#231F20\" stroke-width=\"10\" stroke-linejoin=\"round\"\/> <path d=\"M249 555 C246 570 251 584 259 594 C269 588 277 580 282 572 Z\" fill=\"#644E37\" stroke=\"#231F20\" stroke-width=\"10\" stroke-linejoin=\"round\"\/><\/svg><\/div>\n  <a class=\"eyebrow\" href=\"https:\/\/www.codemonkey.com\/interactive-cs-tools\" target=\"_top\">Interactive CS Tools<\/a>\n  <h1>Sorting Visualizer<\/h1>\n  <p>Watch five classic algorithms put a list in order, one step at a time. Pause, rewind and follow every move.<\/p>\n  <svg class=\"wave\" viewBox=\"0 0 1440 60\" preserveAspectRatio=\"none\" aria-hidden=\"true\"><path d=\"M0,32 C240,64 480,0 720,24 C960,48 1200,8 1440,30 L1440,60 L0,60 Z\" fill=\"#ffffff\"\/><\/svg>\n<\/header>\n\n<main class=\"wrap\">\n  <section class=\"card\" aria-label=\"Sorting controls and visualization\">\n    <div class=\"topline\">\n      <div>\n        <span class=\"label\" id=\"algoLabel\">Algorithm<\/span>\n        <div class=\"chips\" id=\"algoChips\" role=\"group\" aria-labelledby=\"algoLabel\"><\/div>\n      <\/div>\n      <div class=\"lvl\">\n        <span class=\"label\" style=\"text-align:right\">Level<\/span>\n        <div class=\"level\" role=\"group\" aria-label=\"Level\">\n          <button type=\"button\" data-level=\"easy\" aria-pressed=\"true\">Easy<\/button>\n          <button type=\"button\" data-level=\"adv\" aria-pressed=\"false\">Advanced<\/button>\n        <\/div>\n        <div class=\"level-note\" id=\"levelNote\"><\/div>\n      <\/div>\n    <\/div>\n\n    <div class=\"settings\">\n      <div class=\"field\">\n        <label class=\"label\" for=\"dataSel\">Starting data<\/label>\n        <select id=\"dataSel\">\n          <option value=\"random\">Random<\/option>\n          <option value=\"nearly\">Nearly sorted<\/option>\n          <option value=\"reversed\">Reversed<\/option>\n          <option value=\"few\">Few unique values<\/option>\n        <\/select>\n      <\/div>\n      <div class=\"field\" style=\"flex:1;max-width:240px\">\n        <label class=\"label\" for=\"sizeIn\"><span id=\"sizeWord\">Bars<\/span>: <span class=\"val\" id=\"sizeVal\">12<\/span><\/label>\n        <input type=\"range\" id=\"sizeIn\" min=\"5\" max=\"60\" value=\"12\">\n      <\/div>\n      <button class=\"btn secondary\" id=\"shuffleBtn\" type=\"button\">\n        <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M17 3l4 4-4 4V8h-2.6l-2.1 2.6-1.3-1.6L13.4 6H17V3zM3 6h4.6l8 10H17v-3l4 4-4 4v-3h-2.6l-8-10H3V6zm0 10h3.4l2.4-3 1.3 1.6L7.4 18H3v-2z\"\/><\/svg>\n        New data\n      <\/button>\n    <\/div>\n\n    <div class=\"main-grid\">\n      <div>\n        <div class=\"stage\">\n          <div class=\"bars\" id=\"bars\" aria-hidden=\"true\"><\/div>\n          <div class=\"ptrs\" id=\"ptrs\" aria-hidden=\"true\"><\/div>\n        <\/div>\n        <div class=\"legend\" id=\"legend\"><\/div>\n\n        <div class=\"transport\">\n          <button class=\"btn secondary icon\" id=\"resetBtn\" type=\"button\" aria-label=\"Back to start\" title=\"Back to start\">\n            <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M6 5h2v14H6zM20 5v14L9 12z\"\/><\/svg>\n          <\/button>\n          <button class=\"btn secondary icon\" id=\"backBtn\" type=\"button\" aria-label=\"Step back\" title=\"Step back (left arrow)\">\n            <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M15 5v14L5 12z\"\/><\/svg>\n          <\/button>\n          <button class=\"btn play\" id=\"playBtn\" type=\"button\" title=\"Play \/ pause (space)\">\n            <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\" id=\"playIcon\"><path d=\"M7 4v16l13-8z\"\/><\/svg>\n            <span id=\"playTxt\">Play<\/span>\n          <\/button>\n          <button class=\"btn secondary icon\" id=\"fwdBtn\" type=\"button\" aria-label=\"Step forward\" title=\"Step forward (right arrow)\">\n            <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 5v14l10-7z\"\/><\/svg>\n          <\/button>\n          <div class=\"speed\">\n            <label class=\"label\" for=\"speedIn\">Speed <span class=\"val\" id=\"speedVal\">5<\/span><\/label>\n            <input type=\"range\" id=\"speedIn\" min=\"1\" max=\"10\" value=\"5\">\n          <\/div>\n        <\/div>\n\n        <div class=\"scrub\">\n          <input type=\"range\" id=\"scrub\" min=\"0\" max=\"1\" value=\"0\" aria-label=\"Jump to step\">\n          <span class=\"count\" id=\"stepCount\">Step 0<\/span>\n        <\/div>\n\n        <div class=\"narration\" aria-live=\"polite\"><span class=\"dot\"><\/span><span id=\"msg\"><\/span><\/div>\n      <\/div>\n\n      <aside class=\"side\">\n        <h3 id=\"howTitle\">How it works<\/h3>\n        <div id=\"howBox\"><\/div>\n        <h3 id=\"varsTitle\">What the computer remembers<\/h3>\n        <div class=\"vars\" id=\"vars\"><\/div>\n        <h3 id=\"statsTitle\">Counters<\/h3>\n        <div class=\"stats\">\n          <div class=\"stat c\"><b id=\"sComp\">0<\/b><small id=\"lComp\">Checks<\/small><\/div>\n          <div class=\"stat m\"><b id=\"sMove\">0<\/b><small id=\"lMove\">Swaps<\/small><\/div>\n          <div class=\"stat s\"><b id=\"sDone\">0<\/b><small id=\"lDone\">Done<\/small><\/div>\n        <\/div>\n      <\/aside>\n    <\/div>\n  <\/section>\n\n  <section class=\"info\">\n    <div class=\"card\">\n      <h2>How <em id=\"infoName\">Bubble Sort<\/em> works<\/h2>\n      <p id=\"infoHow\"><\/p>\n      <ul class=\"bullets\" id=\"infoBullets\"><\/ul>\n    <\/div>\n    <div class=\"card\">\n      <div id=\"speedEasy\">\n        <h2>Fast or <em>slow?<\/em><\/h2>\n        <div class=\"meter\" id=\"meter\"><\/div>\n        <div class=\"speedword\" id=\"speedWord\"><\/div>\n        <p id=\"speedText\" style=\"margin:6px 0 0\"><\/p>\n      <\/div>\n      <div id=\"speedAdv\" hidden>\n        <h2>Complexity<\/h2>\n        <table>\n          <tr><td>Best case<\/td><td id=\"cBest\"><\/td><\/tr>\n          <tr><td>Average case<\/td><td id=\"cAvg\"><\/td><\/tr>\n          <tr><td>Worst case<\/td><td id=\"cWorst\"><\/td><\/tr>\n          <tr><td>Extra memory<\/td><td id=\"cSpace\"><\/td><\/tr>\n          <tr><td>Stable<\/td><td id=\"cStable\"><\/td><\/tr>\n        <\/table>\n        <div class=\"explain\" id=\"explain\"><\/div>\n      <\/div>\n      <div class=\"tip\"><strong>Try this in class<\/strong><span id=\"infoTip\"><\/span><\/div>\n    <\/div>\n  <\/section>\n<\/main>\n\n<footer>Keyboard: <b>Space<\/b> play \/ pause \u00b7 <b>Left<\/b> and <b>Right<\/b> arrows step back \/ forward<\/footer>\n\n<script>\n\/\/ Each step: {t, ..., line (Python line), r (Easy recipe line), msg (Easy), adv (Advanced), vars:[[name, advValue, easyLabel, easyValue]], ptr:[[label, index]]}\nfunction V(name, adv, easyLabel, easyVal){ return [name, adv, easyLabel, easyVal===undefined?adv:easyVal]; }\n\nfunction bubbleSteps(a){\n  const s=[], n=a.length;\n  for(let i=0;i<n-1;i++){\n    let swapped=false;\n    const base=()=>[V('i',i,'Pass number',i+1), V('swapped',swapped?'True':'False','Swapped this pass?',swapped?'Yes':'No')];\n    s.push({t:'note',line:3,r:0,vars:base(),ptr:[],\n      msg:'Pass '+(i+1)+': walk along the bars and swap any neighbours that are in the wrong order.',\n      adv:'Start pass i = '+i+'. swapped = False. The last '+i+' bar'+(i===1?' is':'s are')+' already in place.'});\n    for(let j=0;j<n-i-1;j++){\n      const vars=[V('i',i,'Pass number',i+1), V('j',j,'Looking at position',j), V('a[j]',a[j],'Left bar',a[j]), V('a[j + 1]',a[j+1],'Right bar',a[j+1]), V('swapped',swapped?'True':'False','Swapped this pass?',swapped?'Yes':'No')];\n      s.push({t:'cmp',i:j,j:j+1,line:5,r:0,vars:vars,ptr:[['j',j],['j+1',j+1]],\n        msg:'Is '+a[j]+' bigger than '+a[j+1]+'?',\n        adv:'a[j] > a[j + 1]  \u2192  '+a[j]+' > '+a[j+1]+'  \u2192  '+(a[j]>a[j+1]?'True':'False')});\n      if(a[j]>a[j+1]){\n        s.push({t:'swap',i:j,j:j+1,line:6,r:1,vars:[V('i',i,'Pass number',i+1), V('j',j,'Looking at position',j), V('a[j]',a[j+1],'Left bar',a[j+1]), V('a[j + 1]',a[j],'Right bar',a[j]), V('swapped','True','Swapped this pass?','Yes')],ptr:[['j',j],['j+1',j+1]],\n          msg:'Yes! '+a[j]+' is bigger, so swap them.',\n          adv:'Swap a['+j+'] and a['+(j+1)+']. swapped = True.'});\n        const t=a[j]; a[j]=a[j+1]; a[j+1]=t; swapped=true;\n      }\n    }\n    s.push({t:'sorted',idx:[n-1-i],line:2,r:2,vars:base(),ptr:[],\n      msg:a[n-1-i]+' has bubbled up to its final spot.',\n      adv:'End of pass '+i+'. a['+(n-1-i)+'] = '+a[n-1-i]+' is in its final position.'});\n    if(!swapped){\n      const rest=[]; for(let k=0;k<n-1-i;k++) rest.push(k);\n      s.push({t:'sorted',idx:rest,line:9,r:3,vars:base(),ptr:[],\n        msg:'No swaps in this whole pass, so everything is already in order. Stop early!',\n        adv:'swapped is still False, so the list is sorted. break.'});\n      return s;\n    }\n  }\n  s.push({t:'sorted',idx:[0],line:2,r:2,vars:[],ptr:[],msg:'Only '+a[0]+' is left, so it is already in place.',adv:'The loop ends. a[0] = '+a[0]+' is in place.'});\n  return s;\n}\n\nfunction selectionSteps(a){\n  const s=[], n=a.length;\n  for(let i=0;i<n-1;i++){\n    let min=i;\n    const vv=(j)=>{ const r=[V('i',i,'Filling position',i)]; if(j!==undefined) r.push(V('j',j,'Looking at position',j)); r.push(V('min_idx',min,'Smallest so far',a[min])); if(j!==undefined) r.push(V('a[j]',a[j],'Bar being checked',a[j])); return r; };\n    const pp=(j)=>{ const r=[['i',i]]; if(j!==undefined) r.push(['j',j]); r.push(['min',min]); return r; };\n    s.push({t:'piv',idx:i,line:3,r:0,vars:vv(),ptr:pp(),\n      msg:'Pass '+(i+1)+': look for the smallest bar from here on. Start by guessing '+a[i]+'.',\n      adv:'i = '+i+'. min_idx = i = '+i+' (value '+a[i]+').'});\n    for(let j=i+1;j<n;j++){\n      s.push({t:'cmp',i:j,j:min,line:5,r:0,vars:vv(j),ptr:pp(j),\n        msg:'Is '+a[j]+' smaller than the smallest so far, '+a[min]+'?',\n        adv:'a[j] < a[min_idx]  \u2192  '+a[j]+' < '+a[min]+'  \u2192  '+(a[j]<a[min]?'True':'False')});\n      if(a[j]<a[min]){ min=j; s.push({t:'piv',idx:min,line:6,r:1,vars:vv(j),ptr:pp(j),msg:'Yes! '+a[min]+' is the new smallest.',adv:'min_idx = j = '+j+'.'}); }\n    }\n    if(min!==i){\n      s.push({t:'swap',i:i,j:min,piv:i,line:7,r:2,vars:vv(),ptr:pp(),msg:'Swap '+a[i]+' with the smallest, '+a[min]+'.',adv:'Swap a['+i+'] = '+a[i]+' and a['+min+'] = '+a[min]+'.'});\n      const t=a[i]; a[i]=a[min]; a[min]=t;\n    } else {\n      s.push({t:'note',line:7,r:2,vars:vv(),ptr:pp(),msg:a[i]+' is already the smallest, so it stays put.',adv:'min_idx == i, so the swap changes nothing.'});\n    }\n    s.push({t:'sorted',idx:[i],line:2,r:3,vars:[V('i',i,'Filling position',i)],ptr:[['i',i]],msg:a[i]+' is locked in place.',adv:'a['+i+'] = '+a[i]+' is in its final position.'});\n  }\n  s.push({t:'sorted',idx:[n-1],line:2,r:3,vars:[],ptr:[],msg:'The last bar, '+a[n-1]+', must be the biggest.',adv:'The loop ends. a['+(n-1)+'] is the maximum.'});\n  return s;\n}\n\nfunction insertionSteps(a){\n  const s=[], n=a.length;\n  s.push({t:'sorted',idx:[0],soft:true,line:1,r:0,vars:[],ptr:[],msg:'The first bar on its own counts as a sorted list. Start with the second bar.',adv:'a[0:1] is trivially sorted. Start at i = 1.'});\n  for(let i=1;i<n;i++){\n    const key=a[i];\n    let j=i;\n    s.push({t:'piv',idx:i,line:2,r:0,vars:[V('i',i,'Next bar to place',i),V('key',key,'Holding',key),V('j',i-1,'Comparing with position',i-1)],ptr:[['i',i],['key',i],['j',i-1]],\n      msg:'Pick up '+key+' and slide it left into the sorted part.',adv:'key = a['+i+'] = '+key+'. j = '+(i-1)+'.'});\n    while(j>0){\n      s.push({t:'cmp',i:j-1,j:j,piv:j,line:4,r:1,vars:[V('i',i,'Next bar to place',i),V('key',key,'Holding',key),V('j',j-1,'Comparing with position',j-1),V('a[j]',a[j-1],'Bar on the left',a[j-1])],ptr:[['j',j-1],['key',j]],\n        msg:'Is '+a[j-1]+' bigger than '+key+'?',adv:'j >= 0 and a[j] > key  \u2192  '+a[j-1]+' > '+key+'  \u2192  '+(a[j-1]>key?'True':'False')});\n      if(a[j-1]>key){\n        s.push({t:'swap',i:j-1,j:j,piv:j-1,line:5,r:2,vars:[V('i',i,'Next bar to place',i),V('key',key,'Holding',key),V('j',j-2,'Comparing with position',j-2)],ptr:[['key',j-1]],\n          msg:'Yes, so slide '+a[j-1]+' one place to the right.',adv:'a[j + 1] = a[j] (shift '+a[j-1]+' right). j = '+(j-2)+'.'});\n        const t=a[j-1]; a[j-1]=a[j]; a[j]=t; j--;\n      } else break;\n    }\n    s.push({t:'note',piv:j,line:7,r:3,vars:[V('i',i,'Next bar to place',i),V('key',key,'Holding',key),V('j',j-1,'Comparing with position',j-1)],ptr:[['key',j]],\n      msg: j===0 ? key+' is the smallest so far, so it goes to the front.' : 'No, so '+key+' drops into place right here.',\n      adv:'a[j + 1] = key  \u2192  a['+j+'] = '+key+'. a[0:'+(i+1)+'] is now sorted.'});\n  }\n  return s;\n}\n\nfunction mergeSteps(a){\n  const s=[];\n  function ms(lo,hi){\n    if(lo>=hi) return;\n    const mid=(lo+hi)>>1;\n    s.push({t:'range',lo:lo,hi:hi,line:2,r:0,vars:[V('lo',lo,'Group starts at',lo),V('mid',mid,'Split after',mid),V('hi',hi,'Group ends at',hi)],ptr:[['lo',lo],['mid',mid],['hi',hi]],\n      msg:'Split these '+(hi-lo+1)+' bars into two halves.',adv:'merge_sort(a, '+lo+', '+hi+'): mid = '+mid+'. Sort a['+lo+'..'+mid+'] and a['+(mid+1)+'..'+hi+'].'});\n    ms(lo,mid); ms(mid+1,hi);\n    let i=lo, j=mid+1, m=mid;\n    s.push({t:'range',lo:lo,hi:hi,line:8,r:1,vars:[V('i',i,'Left front',a[i]),V('j',j,'Right front',a[j]),V('mid',m,'Left half ends at',m)],ptr:[['i',i],['j',j]],\n      msg:'Both halves are sorted. Now merge these '+(hi-lo+1)+' bars.',adv:'merge(a, '+lo+', '+mid+', '+hi+'): i = '+i+', j = '+j+'.'});\n    while(i<=m){\n      if(j>hi) break;\n      const vv=()=>[V('i',i,'Left front',a[i]),V('j',j,'Right front',a[j]),V('mid',m,'Left half ends at',m)];\n      if(a[i]<=a[j]){\n        s.push({t:'cmp',i:i,j:j,line:10,r:2,vars:vv(),ptr:[['i',i],['j',j]],msg:'Compare '+a[i]+' (left) with '+a[j]+' (right). '+a[i]+' is smaller, so it stays first.',adv:'a[i] <= a[j]  \u2192  '+a[i]+' <= '+a[j]+'  \u2192  True. i += 1.'});\n        i++;\n      } else {\n        s.push({t:'cmp',i:i,j:j,line:10,r:2,vars:vv(),ptr:[['i',i],['j',j]],msg:'Compare '+a[i]+' (left) with '+a[j]+' (right).',adv:'a[i] <= a[j]  \u2192  '+a[i]+' <= '+a[j]+'  \u2192  False.'});\n        const v=a[j];\n        s.push({t:'rotate',from:j,to:i,line:13,r:2,vars:vv(),ptr:[['i',i],['j',j]],msg:v+' is smaller, so it moves in front of '+a[i]+'.',adv:'a.insert(i, a.pop(j)): move '+v+' from position '+j+' to '+i+'. Then i, mid, j all += 1.'});\n        a.splice(j,1); a.splice(i,0,v);\n        i++; m++; j++;\n      }\n    }\n  }\n  ms(0,a.length-1);\n  return s;\n}\n\nfunction quickSteps(a){\n  const s=[];\n  function qs(lo,hi){\n    if(lo>hi) return;\n    if(lo===hi){ s.push({t:'sorted',idx:[lo],line:1,r:3,vars:[V('lo',lo,'Group starts at',lo),V('hi',hi,'Group ends at',hi)],ptr:[['lo',lo]],msg:'A single bar ('+a[lo]+') is already sorted.',adv:'quick_sort(a, '+lo+', '+hi+'): lo >= hi, return.'}); return; }\n    const pv=a[hi];\n    s.push({t:'range',lo:lo,hi:hi,line:0,r:0,vars:[V('lo',lo,'Group starts at',lo),V('hi',hi,'Group ends at',hi)],ptr:[['lo',lo],['hi',hi]],msg:'Work on these '+(hi-lo+1)+' bars.',adv:'quick_sort(a, '+lo+', '+hi+').'});\n    let i=lo;\n    s.push({t:'piv',idx:hi,line:2,r:0,vars:[V('pivot',pv,'Pivot',pv),V('i',i,'Small side ends before',i)],ptr:[['i',i],['pivot',hi]],msg:'Pick the last bar, '+pv+', as the pivot.',adv:'pivot = a['+hi+'] = '+pv+'. i = lo = '+lo+'.'});\n    for(let j=lo;j<hi;j++){\n      const vv=()=>[V('pivot',pv,'Pivot',pv),V('i',i,'Small side ends before',i),V('j',j,'Looking at position',j),V('a[j]',a[j],'Bar being checked',a[j])];\n      s.push({t:'cmp',i:j,j:hi,line:5,r:1,vars:vv(),ptr:[['i',i],['j',j],['pivot',hi]],msg:'Is '+a[j]+' smaller than the pivot, '+pv+'?',adv:'a[j] < pivot  \u2192  '+a[j]+' < '+pv+'  \u2192  '+(a[j]<pv?'True':'False')});\n      if(a[j]<pv){\n        if(i!==j){\n          s.push({t:'swap',i:i,j:j,line:6,r:1,vars:vv(),ptr:[['i',i],['j',j],['pivot',hi]],msg:'Yes, so move '+a[j]+' over to the small side.',adv:'Swap a['+i+'] and a['+j+']. i += 1.'});\n          const t=a[i]; a[i]=a[j]; a[j]=t;\n        } else {\n          s.push({t:'note',line:7,r:1,vars:vv(),ptr:[['i',i],['j',j],['pivot',hi]],msg:'Yes, and it is already on the small side.',adv:'i == j, so the swap changes nothing. i += 1.'});\n        }\n        i++;\n      }\n    }\n    if(i!==hi){ s.push({t:'swap',i:i,j:hi,piv:i,line:8,r:2,vars:[V('pivot',pv,'Pivot',pv),V('i',i,'Pivot goes to position',i)],ptr:[['i',i],['pivot',hi]],msg:'Put the pivot '+pv+' between the small and big bars.',adv:'Swap a['+i+'] and a['+hi+']: the pivot lands at position '+i+'.'}); const t=a[i]; a[i]=a[hi]; a[hi]=t; }\n    s.push({t:'sorted',idx:[i],line:8,r:2,vars:[V('pivot',pv,'Pivot',pv),V('i',i,'Pivot is at position',i)],ptr:[['i',i]],msg:'Pivot '+pv+' is in its final spot.',adv:'a['+i+'] = '+pv+' is in its final position. Recurse on both sides.'});\n    qs(lo,i-1); qs(i+1,hi);\n  }\n  qs(0,a.length-1);\n  return s;\n}\n\nconst ALGOS = {\n  bubble:{\n    name:'Bubble Sort', gen:bubbleSteps,\n    code:['def bubble_sort(a):','    n = len(a)','    for i in range(n - 1):','        swapped = False','        for j in range(n - 1 - i):','            if a[j] > a[j + 1]:','                a[j], a[j + 1] = a[j + 1], a[j]','                swapped = True','        if not swapped:','            break'],\n    recipe:['Look at two neighbours at a time.','If the left one is bigger, swap them.','After each pass, the biggest bar is in place.','If a pass makes no swaps, stop. You are done!'],\n    best:'O(n)', avg:'O(n\u00b2)', worst:'O(n\u00b2)', space:'O(1)', stable:'Yes', stars:1, word:'Slow',\n    speed:'Fine for a handful of items, but slow on big lists. 100 jumbled bars can take almost 5,000 checks.',\n    how:{easy:'Bubble Sort walks along the list again and again, comparing neighbours and swapping any pair in the wrong order. After each pass, the biggest unsorted bar has \"bubbled\" to the end.',\n         adv:'Bubble Sort repeatedly scans the unsorted prefix, swapping adjacent out-of-order pairs. After pass i, the largest i + 1 elements sit in their final positions. A swapped flag lets it stop early when a pass makes no swaps.'},\n    bullets:{easy:['Easy to understand','Slow on long lists','Can stop early when the list is already sorted'],\n             adv:['In-place: needs only O(1) extra memory','Stable: equal values keep their order','Adaptive: best case O(n) on sorted input, thanks to the swapped flag']},\n    tip:{easy:'Switch the data to Nearly sorted. How many passes does Bubble Sort need now? Why?',\n         adv:'Compare the swap counter on Random and Reversed data. Can you predict the number of swaps for Reversed data with n bars? (Hint: n(n \u2212 1) \/ 2.)'}\n  },\n  selection:{\n    name:'Selection Sort', gen:selectionSteps,\n    code:['def selection_sort(a):','    n = len(a)','    for i in range(n - 1):','        min_idx = i','        for j in range(i + 1, n):','            if a[j] < a[min_idx]:','                min_idx = j','        a[i], a[min_idx] = a[min_idx], a[i]'],\n    recipe:['Search the unsorted part for the smallest bar.','Every time you find a smaller one, remember it.','Swap the smallest bar to the front.','That bar is done. Repeat with the rest.'],\n    best:'O(n\u00b2)', avg:'O(n\u00b2)', worst:'O(n\u00b2)', space:'O(1)', stable:'No', stars:1, word:'Slow',\n    speed:'Always slow on big lists. It makes about 5,000 checks for 100 bars, even if they are already sorted. But it makes very few swaps.',\n    how:{easy:'Selection Sort looks through the unsorted bars to find the smallest one, then swaps it to the front. The sorted part grows by one bar each pass.',\n         adv:'Selection Sort finds the minimum of the unsorted suffix a[i..n\u22121] with a linear scan, then swaps it into position i. It always performs n(n \u2212 1) \/ 2 comparisons, but at most n \u2212 1 swaps.'},\n    bullets:{easy:['Always does the same number of checks','Makes very few swaps','Equal bars can swap places'],\n             adv:['In-place: O(1) extra memory','Not stable: a long-distance swap can reorder equal values','Not adaptive: sorted input still costs O(n\u00b2) comparisons']},\n    tip:{easy:'Run Selection Sort and Bubble Sort on the same data. Which one makes fewer swaps? Which makes fewer checks?',\n         adv:'Why might Selection Sort be a good choice when writing to memory is expensive, such as on flash storage?'}\n  },\n  insertion:{\n    name:'Insertion Sort', gen:insertionSteps,\n    code:['def insertion_sort(a):','    for i in range(1, len(a)):','        key = a[i]','        j = i - 1','        while j >= 0 and a[j] > key:','            a[j + 1] = a[j]','            j -= 1','        a[j + 1] = key'],\n    recipe:['Pick up the next bar (the key).','Compare it with the bar on its left.','If that bar is bigger, slide it right.','Drop the key into the gap.'],\n    best:'O(n)', avg:'O(n\u00b2)', worst:'O(n\u00b2)', space:'O(1)', stable:'Yes', stars:2, word:'It depends',\n    speed:'Very fast when the list is almost sorted, but slow when it is jumbled or reversed.',\n    how:{easy:'Insertion Sort works like sorting playing cards in your hand: pick up the next card and slide it left until it fits.',\n         adv:'Insertion Sort grows a sorted prefix a[0..i\u22121]. Each new key is shifted left past every larger element. The work done equals the number of inversions in the input, so nearly sorted data is very cheap.'},\n    bullets:{easy:['Super quick on nearly sorted lists','Great for small lists','Works the way many people sort cards'],\n             adv:['In-place and stable','Adaptive: O(n + inversions) time','Used inside faster sorts (such as Timsort) for small chunks']},\n    tip:{easy:'Try Reversed data. This is the hardest case for Insertion Sort. Can you explain why?',\n         adv:'Count the swaps on Nearly sorted data. How does that relate to the number of out-of-order pairs (inversions)?'}\n  },\n  merge:{\n    name:'Merge Sort', gen:mergeSteps,\n    code:['def merge_sort(a, lo, hi):','    if lo >= hi: return','    mid = (lo + hi) \/\/ 2','    merge_sort(a, lo, mid)','    merge_sort(a, mid + 1, hi)','    merge(a, lo, mid, hi)','','def merge(a, lo, mid, hi):','    i, j = lo, mid + 1','    while i <= mid and j <= hi:','        if a[i] <= a[j]:','            i += 1','        else:','            a.insert(i, a.pop(j))','            i += 1; mid += 1; j += 1'],\n    recipe:['Split the list in half, again and again.','Merge two sorted halves back together.','Compare the front bars. The smaller one goes first.','Keep merging until the whole list is one sorted piece.'],\n    best:'O(n log n)', avg:'O(n log n)', worst:'O(n log n)', space:'O(n)', stable:'Yes', stars:4, word:'Fast',\n    speed:'Fast, and always fast. It needs fewer than 700 checks for 100 bars, whatever order they start in.',\n    how:{easy:'Merge Sort splits the list in half, sorts each half, then merges the two sorted halves back together. It keeps splitting until each piece holds just one bar.',\n         adv:'Merge Sort is divide and conquer: split, sort each half recursively, then merge two sorted runs in linear time. The recursion is log\u2082 n levels deep, and each level does O(n) work.'},\n    bullets:{easy:['Splits the big problem into small ones','Always fast, even on tricky data','Keeps equal bars in order'],\n             adv:['Guaranteed O(n log n) comparisons','Normally needs O(n) extra memory. This demo merges in place with insert\/pop so every move stays visible','Stable, so it is used for sorting records by several keys']},\n    tip:{easy:'Set the bars to 60 and compare the Checks counter with Bubble Sort on the same data.',\n         adv:'Draw the recursion tree for 8 bars. How many levels does it have, and how many comparisons happen on each level?'}\n  },\n  quick:{\n    name:'Quick Sort', gen:quickSteps,\n    code:['def quick_sort(a, lo, hi):','    if lo >= hi: return','    pivot = a[hi]','    i = lo','    for j in range(lo, hi):','        if a[j] < pivot:','            a[i], a[j] = a[j], a[i]','            i += 1','    a[i], a[hi] = a[hi], a[i]','    quick_sort(a, lo, i - 1)','    quick_sort(a, i + 1, hi)'],\n    recipe:['Pick a pivot: the last bar in the group.','Move every bar smaller than the pivot to the left.','Put the pivot between the small and big bars. It is done!','Do the same to the left side and the right side.'],\n    best:'O(n log n)', avg:'O(n log n)', worst:'O(n\u00b2)', space:'O(log n)', stable:'No', stars:5, word:'Very fast',\n    speed:'Usually the fastest of the five: under 1,000 checks for 100 jumbled bars. But it gets slow if the list is already sorted or reversed.',\n    how:{easy:'Quick Sort picks a pivot, moves every smaller bar to its left and every bigger bar to its right, then sorts each side the same way.',\n         adv:'This is Quick Sort with Lomuto partitioning. The last element is the pivot, and i marks the end of the \"smaller than pivot\" region. After partitioning, the pivot is final and both sides are sorted recursively.'},\n    bullets:{easy:['One of the fastest sorts in real life','Choosing the pivot matters a lot','Equal bars can swap places'],\n             adv:['Average O(n log n), with small constant factors','Worst case O(n\u00b2) when the pivot is always the min or max','In-place, but not stable. The recursion uses O(log n) stack space on average']},\n    tip:{easy:'Try Reversed data. With the last bar as the pivot, Quick Sort has a very bad day!',\n         adv:'How could a better pivot choice (random, or median of three) avoid the O(n\u00b2) worst case on reversed data?'}\n  }\n};\n\nconst EXPLAIN={\n  'O(n\u00b2)':'<b>O(n\u00b2)<\/b> means the work grows with the square of the list size. Double the bars, and it takes about 4 times as long.',\n  'O(n log n)':'<b>O(n log n)<\/b> means the work grows only a little faster than the list. Double the bars, and it takes just over twice as long.'\n};\nconst LEVEL_TXT={\n  easy:{note:'Plain words, no code', howTitle:'The plan', varsTitle:'What the computer remembers', comp:'Checks', move:'Swaps', done:'Done', size:'Bars',\n        legend:[['var(--blue)','Not sorted yet'],['var(--yellow)','Checking'],['var(--pink)','Moving'],['var(--purple)','Special bar'],['var(--lime)','Done']]},\n  adv:{note:'Python code, variables and Big-O', howTitle:'Python code', varsTitle:'Variables', comp:'Comparisons', move:'Swaps', done:'Sorted', size:'n',\n       legend:[['var(--blue)','Unsorted'],['var(--yellow)','Compared'],['var(--pink)','Written \/ swapped'],['var(--purple)','Pivot \/ key \/ min'],['var(--lime)','In final position']]}\n};\nconst BANANA='<svg viewBox=\"240 330 620 430\" aria-hidden=\"true\"><path d=\"M262 572 C330 605 400 618 470 616 C560 612 650 560 712 500 C750 465 785 430 810 402 L843 406 C853 462 851 560 791 630 C731 700 621 748 506 748 C401 748 311 680 258 592 Z\" fill=\"#E6B94A\"\/> <path d=\"M268 578 C340 612 410 622 470 620 C565 616 655 562 712 505 C750 467 790 428 812 405 C790 470 730 560 640 610 C590 638 540 650 480 652 C400 652 322 622 266 592 Z\" fill=\"#CDA144\"\/> <path d=\"M262 572 C330 605 400 618 470 616 C560 612 650 560 712 500 C750 465 785 430 810 402 L843 406 C853 462 851 560 791 630 C731 700 621 748 506 748 C401 748 311 680 258 592 Z\" fill=\"none\" stroke=\"#231F20\" stroke-width=\"10\" stroke-linejoin=\"round\"\/> <g fill=\"none\" stroke=\"#231F20\" stroke-width=\"10\" stroke-linecap=\"butt\"> <path d=\"M302 618 C360 655 420 690 505 692 C620 694 730 610 812 518\"\/> <path d=\"M562 648 C660 610 760 530 815 418\"\/> <path d=\"M780 516 C795 485 808 452 818 420\"\/> <\/g> <path d=\"M808 405 L826 340 L848 345 L843 408 C835 420 818 422 808 405 Z\" fill=\"#644E37\" stroke=\"#231F20\" stroke-width=\"10\" stroke-linejoin=\"round\"\/> <path d=\"M249 555 C246 570 251 584 259 594 C269 588 277 580 282 572 Z\" fill=\"#644E37\" stroke=\"#231F20\" stroke-width=\"10\" stroke-linejoin=\"round\"\/><\/svg>';\n\nconst $ = id => document.getElementById(id);\nconst DELAYS=[900,600,380,240,150,95,55,30,14,4];\n\nlet algo='bubble', level='easy', base=[], steps=[], pos=0, view=null, timer=null, playing=false, bars=[], cells=[];\n\nfunction makeData(n, kind){\n  let a = Array.from({length:n},(_,i)=>Math.round(5+95*(i+1)\/n));\n  if(kind==='few'){ const vals=[25,50,75,100]; return a.map(()=>vals[Math.floor(Math.random()*4)]); }\n  if(kind==='reversed') return a.reverse();\n  if(kind==='nearly'){\n    const swaps=Math.max(1,Math.round(n\/8));\n    for(let k=0;k<swaps;k++){ const i=Math.floor(Math.random()*(n-1)); const t=a[i]; a[i]=a[i+1]; a[i+1]=t; }\n    return a;\n  }\n  for(let i=n-1;i>0;i--){ const j=Math.floor(Math.random()*(i+1)); const t=a[i]; a[i]=a[j]; a[j]=t; }\n  return a;\n}\n\nfunction freshView(){\n  return {a:base.slice(), sorted:new Set(), soft:new Set(), cmp:null, swp:null, piv:null, range:null, comps:0, moves:0, line:-1, r:-1, vars:[], ptr:[], msg:null, adv:null};\n}\n\nfunction apply(v, st){\n  v.cmp=null; v.swp=null;\n  if(st.line!==undefined) v.line=st.line;\n  if(st.r!==undefined) v.r=st.r;\n  v.msg=st.msg; v.adv=st.adv||st.msg;\n  v.prevVars=v.vars; v.vars=st.vars||[]; v.ptr=st.ptr||[];\n  if(st.piv!==undefined) v.piv=st.piv;\n  switch(st.t){\n    case 'cmp': v.cmp=[st.i,st.j]; v.comps++; break;\n    case 'swap': { const t=v.a[st.i]; v.a[st.i]=v.a[st.j]; v.a[st.j]=t; v.swp=[st.i,st.j]; v.moves++; break; }\n    case 'rotate': { const val=v.a.splice(st.from,1)[0]; v.a.splice(st.to,0,val); v.swp=[st.to]; v.moves++; break; }\n    case 'piv': v.piv=st.idx; break;\n    case 'sorted': if(st.soft){ st.idx.forEach(k=>v.soft.add(k)); } else { st.idx.forEach(k=>v.sorted.add(k)); v.piv=null; } break;\n    case 'range': v.range=[st.lo,st.hi]; v.piv=null; break;\n    case 'done': v.a.forEach((_,k)=>v.sorted.add(k)); v.range=null; v.piv=null; v.ptr=[]; v.vars=[]; break;\n  }\n}\n\nfunction buildBars(){\n  const box=$('bars'), pbox=$('ptrs'); box.innerHTML=''; pbox.innerHTML=''; bars=[]; cells=[];\n  const n=base.length, gap= n>40?'2px':(n>24?'3px':'6px');\n  box.style.setProperty('--gap',gap); pbox.style.setProperty('--gap',gap);\n  pbox.classList.toggle('tight', n>20);\n  for(let k=0;k<n;k++){\n    const b=document.createElement('div'); b.className='bar'; b.appendChild(document.createElement('span')); box.appendChild(b); bars.push(b);\n    const c=document.createElement('div'); pbox.appendChild(c); cells.push(c);\n  }\n}\n\nfunction render(){\n  const v=view, n=v.a.length, showVals=n<=24;\n  for(let k=0;k<n;k++){\n    const b=bars[k];\n    b.style.height=v.a[k]+'%';\n    b.firstChild.textContent=showVals?v.a[k]:'';\n    let c='bar';\n    if(v.range ? ((k<v.range[0]||k>v.range[1]) ? !v.sorted.has(k) : false) : false) c+=' dim';\n    if(v.sorted.has(k)) c+=' done';\n    if(v.piv===k) c+=' piv';\n    if(v.cmp ? v.cmp.includes(k) : false) c+=' cmp';\n    if(v.swp ? v.swp.includes(k) : false) c+=' swp';\n    b.className=c;\n  }\n  const lab={};\n  v.ptr.forEach(p=>{ if(p[1]>=0 ? p[1]<n : false){ (lab[p[1]]=lab[p[1]]||[]).push(p[0]); } });\n  cells.forEach((c,k)=>{ c.innerHTML= lab[k] ? '<b>'+lab[k].join(' ')+'<\/b>' : ''; });\n\n  if(level==='adv') document.querySelectorAll('#howBox .ln').forEach((el,i)=>el.classList.toggle('active',i===v.line));\n  else document.querySelectorAll('#howBox li').forEach((el,i)=>el.classList.toggle('active',i===v.r));\n\n  $('msg').textContent= pos===0 ? (level==='adv' ? 'Press Play or step through. The highlighted line shows what Python is running.' : 'Press Play to start, or step through one move at a time.') : (level==='adv' ? v.adv : v.msg);\n  renderVars();\n  $('sComp').textContent=v.comps; $('sMove').textContent=v.moves; $('sDone').textContent=v.sorted.size;\n  $('stepCount').textContent='Step '+pos;\n  $('scrub').value=pos;\n  $('backBtn').disabled=pos===0;\n  $('fwdBtn').disabled=pos>=steps.length;\n  $('resetBtn').disabled=pos===0;\n}\n\nfunction renderVars(){\n  const box=$('vars'), v=view;\n  box.className='vars'+(level==='adv'?' adv':'');\n  if(!v.vars.length){ box.innerHTML='<div class=\"none\">'+(pos===0?'Nothing yet. Press Play!':(pos>=steps.length?'All done!':'Nothing to remember right now.'))+'<\/div>'; return; }\n  const prev={}; (v.prevVars||[]).forEach(x=>{ prev[x[0]]=x[1]; });\n  box.innerHTML=v.vars.map(x=>{\n    const changed= pos>0 ? (prev[x[0]]!==undefined ? prev[x[0]]!==x[1] : false) : false;\n    const k= level==='adv' ? x[0] : x[2], val= level==='adv' ? x[1] : x[3];\n    return '<div class=\"row'+(changed?' changed':'')+'\"><span class=\"k\">'+k+'<\/span><span class=\"v\">'+val+'<\/span><\/div>';\n  }).join('');\n}\n\nfunction buildSteps(){\n  pause();\n  const A=ALGOS[algo];\n  steps=A.gen(base.slice());\n  const comps=steps.filter(s=>s.t==='cmp').length;\n  const moves=steps.filter(s=>s.t==='swap'||s.t==='rotate').length;\n  steps.push({t:'done',line:-1,r:-1,\n    msg:'All sorted! '+A.name+' needed '+comps+' checks and '+moves+' '+(algo==='merge'?'moves':'swaps')+' for '+base.length+' bars.',\n    adv:'Sorted. '+comps+' comparisons and '+moves+' '+(algo==='merge'?'moves':'swaps')+' for n = '+base.length+'.'});\n  $('scrub').max=steps.length;\n  seek(0);\n}\n\nfunction seek(p){ view=freshView(); for(let i=0;i<p;i++) apply(view,steps[i]); pos=p; render(); }\nfunction stepFwd(){ if(pos<steps.length){ apply(view,steps[pos]); pos++; render(); } }\nfunction stepBack(){ if(pos>0) seek(pos-1); }\n\nfunction setPlayUI(){\n  $('playTxt').textContent=playing?'Pause':(pos>=steps.length?'Replay':(pos>0?'Resume':'Play'));\n  $('playIcon').innerHTML=playing?'<path d=\"M6 4h4v16H6zM14 4h4v16h-4z\"\/>':'<path d=\"M7 4v16l13-8z\"\/>';\n}\nfunction tick(){ if(pos>=steps.length){ pause(); return; } stepFwd(); timer=setTimeout(tick, DELAYS[$('speedIn').value-1]); }\nfunction play(){ if(pos>=steps.length) seek(0); playing=true; setPlayUI(); tick(); }\nfunction pause(){ playing=false; clearTimeout(timer); setPlayUI(); }\n\nfunction newData(){ base=makeData(+$('sizeIn').value,$('dataSel').value); buildBars(); buildSteps(); }\n\nfunction renderHow(){\n  const A=ALGOS[algo], box=$('howBox');\n  box.innerHTML='';\n  if(level==='adv'){\n    const c=document.createElement('div'); c.className='code';\n    A.code.forEach(l=>{ const d=document.createElement('div'); d.className='ln'; d.textContent=l||' '; c.appendChild(d); });\n    box.appendChild(c);\n  } else {\n    const ol=document.createElement('ol'); ol.className='recipe';\n    A.recipe.forEach(l=>{ const li=document.createElement('li'); li.textContent=l; ol.appendChild(li); });\n    box.appendChild(ol);\n  }\n}\n\nfunction renderInfo(){\n  const A=ALGOS[algo], L=level;\n  $('infoName').textContent=A.name;\n  $('infoHow').textContent=A.how[L];\n  $('infoBullets').innerHTML=A.bullets[L].map(b=>'<li>'+b+'<\/li>').join('');\n  $('infoTip').textContent=A.tip[L];\n  $('speedEasy').hidden= L!=='easy'; $('speedAdv').hidden= L!=='adv';\n  $('meter').innerHTML=[1,2,3,4,5].map(k=>'<span class=\"'+(k<=A.stars?'on':'')+'\">'+BANANA+'<\/span>').join('');\n  $('meter').setAttribute('aria-label','Speed: '+A.stars+' out of 5 bananas');\n  $('speedWord').textContent=A.word; $('speedText').textContent=A.speed;\n  $('cBest').textContent=A.best; $('cAvg').textContent=A.avg; $('cWorst').textContent=A.worst;\n  $('cSpace').textContent=A.space; $('cStable').textContent=A.stable;\n  const ex=[]; [A.avg,A.worst].forEach(o=>{ if(EXPLAIN[o] ? !ex.includes(EXPLAIN[o]) : false) ex.push(EXPLAIN[o]); });\n  $('explain').innerHTML=ex.join('<br><br>');\n}\n\nfunction applyLevel(){\n  const T=LEVEL_TXT[level];\n  document.querySelectorAll('.level button').forEach(b=>b.setAttribute('aria-pressed',b.dataset.level===level));\n  $('levelNote').textContent=T.note;\n  $('howTitle').textContent=T.howTitle; $('varsTitle').textContent=T.varsTitle;\n  $('lComp').textContent=T.comp; $('lMove').textContent=(algo==='merge'?'Moves':T.move); $('lDone').textContent=T.done;\n  $('sizeWord').textContent=T.size;\n  $('legend').innerHTML=T.legend.map(l=>'<span><i style=\"background:'+l[0]+'\"><\/i>'+l[1]+'<\/span>').join('');\n  renderHow(); renderInfo(); render();\n}\n\nfunction setLevel(l){\n  level=l;\n  try{ localStorage.setItem('cm-cs-level',l); }catch(e){}\n  applyLevel();\n}\n\nfunction selectAlgo(key){\n  algo=key;\n  document.querySelectorAll('.chip').forEach(c=>c.setAttribute('aria-pressed',c.dataset.key===key));\n  buildSteps(); applyLevel();\n}\n\n\/\/ ----- wire up -----\nObject.entries(ALGOS).forEach(([k,A])=>{\n  const b=document.createElement('button');\n  b.className='chip'; b.type='button'; b.dataset.key=k; b.textContent=A.name;\n  b.addEventListener('click',()=>selectAlgo(k));\n  $('algoChips').appendChild(b);\n});\ndocument.querySelectorAll('.level button').forEach(b=>b.addEventListener('click',()=>setLevel(b.dataset.level)));\n$('playBtn').addEventListener('click',()=>playing?pause():play());\n$('fwdBtn').addEventListener('click',()=>{pause();stepFwd();setPlayUI();});\n$('backBtn').addEventListener('click',()=>{pause();stepBack();setPlayUI();});\n$('resetBtn').addEventListener('click',()=>{pause();seek(0);setPlayUI();});\n$('shuffleBtn').addEventListener('click',newData);\n$('dataSel').addEventListener('change',newData);\n$('sizeIn').addEventListener('input',e=>{$('sizeVal').textContent=e.target.value;newData();});\n$('speedIn').addEventListener('input',e=>{$('speedVal').textContent=e.target.value;});\n$('scrub').addEventListener('input',e=>{pause();seek(+e.target.value);setPlayUI();});\ndocument.addEventListener('keydown',e=>{\n  const tag=(e.target.tagName||'').toUpperCase();\n  if(tag==='SELECT'||tag==='INPUT'||tag==='TEXTAREA'||tag==='BUTTON'||tag==='A') return;\n  if(e.code==='Space'){ e.preventDefault(); playing?pause():play(); }\n  else if(e.key==='ArrowRight'){ e.preventDefault(); pause(); stepFwd(); setPlayUI(); }\n  else if(e.key==='ArrowLeft'){ e.preventDefault(); pause(); stepBack(); setPlayUI(); }\n});\n\n(function init(){\n  let l=null;\n  try{ const q=new URLSearchParams(location.search).get('level'); if(q==='advanced'||q==='adv') l='adv'; else if(q==='easy') l='easy'; }catch(e){}\n  if(!l){ try{ const s=localStorage.getItem('cm-cs-level'); if(s==='adv'||s==='easy') l=s; }catch(e){} }\n  level=l||'easy';\n  base=makeData(12,'random'); buildBars(); selectAlgo('bubble');\n})();\n<\/script>\n<\/body>\n<\/html>\n","protected":false},"excerpt":{"rendered":"<p>Sorting Visualizer Interactive CS Tools Sorting Visualizer Watch five classic algorithms put a list in order, one step at a time. Pause, rewind and follow &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/www.codemonkey.com\/ru\/interactive-cs-tools\/sorting-algorithms\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Sorting Algorithms&#8221;<\/span><\/a><\/p>","protected":false},"author":55,"featured_media":0,"parent":31237,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-31056","page","type-page","status-publish","hentry"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO Pro 5.0.4 - aioseo.com -->\n\t<meta name=\"description\" content=\"Sorting Visualizer Interactive CS Tools Sorting Visualizer Watch five classic algorithms put a list in order, one step at a time. Pause, rewind and follow every move. Algorithm Level Easy Advanced Starting data Random Nearly sorted Reversed Few unique values Bars: 12 New data Play Speed 5 Step 0 How it works What the computer\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<link rel=\"canonical\" href=\"https:\/\/www.codemonkey.com\/ru\/interactive-cs-tools\/sorting-algorithms\/\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO Pro (AIOSEO) 5.0.4\" \/>\n\t\t<meta property=\"og:locale\" content=\"ru_RU\" \/>\n\t\t<meta property=\"og:site_name\" content=\"CodeMonkey -\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"Sorting Algorithms - CodeMonkey\" \/>\n\t\t<meta property=\"og:description\" content=\"Sorting Visualizer Interactive CS Tools Sorting Visualizer Watch five classic algorithms put a list in order, one step at a time. Pause, rewind and follow every move. Algorithm Level Easy Advanced Starting data Random Nearly sorted Reversed Few unique values Bars: 12 New data Play Speed 5 Step 0 How it works What the computer\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/www.codemonkey.com\/ru\/interactive-cs-tools\/sorting-algorithms\/\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/d3sujgifhk94se.cloudfront.net\/wp-content\/uploads\/2020\/06\/21143425\/codemonkey_logo.png\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/d3sujgifhk94se.cloudfront.net\/wp-content\/uploads\/2020\/06\/21143425\/codemonkey_logo.png\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2026-10-08T11:06:13+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2026-10-29T16:55:21+00:00\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n\t\t<meta name=\"twitter:title\" content=\"Sorting Algorithms - CodeMonkey\" \/>\n\t\t<meta name=\"twitter:description\" content=\"Sorting Visualizer Interactive CS Tools Sorting Visualizer Watch five classic algorithms put a list in order, one step at a time. Pause, rewind and follow every move. Algorithm Level Easy Advanced Starting data Random Nearly sorted Reversed Few unique values Bars: 12 New data Play Speed 5 Step 0 How it works What the computer\" \/>\n\t\t<meta name=\"twitter:image\" content=\"https:\/\/d3sujgifhk94se.cloudfront.net\/wp-content\/uploads\/2020\/06\/21143425\/codemonkey_logo.png\" \/>\n\t\t<script type=\"application\/ld+json\" class=\"aioseo-schema\">\n\t\t\t{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.codemonkey.com\\\/ru\\\/interactive-cs-tools\\\/sorting-algorithms\\\/#breadcrumblist\",\"itemListElement\":[{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.codemonkey.com\\\/ru\\\/#listItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.codemonkey.com\\\/ru\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.codemonkey.com\\\/ru\\\/interactive-cs-tools\\\/#listItem\",\"name\":\"Free Teacher Tools for Computer Science\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.codemonkey.com\\\/ru\\\/interactive-cs-tools\\\/#listItem\",\"position\":2,\"name\":\"Free Teacher Tools for Computer Science\",\"item\":\"https:\\\/\\\/www.codemonkey.com\\\/ru\\\/interactive-cs-tools\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.codemonkey.com\\\/ru\\\/interactive-cs-tools\\\/sorting-algorithms\\\/#listItem\",\"name\":\"Sorting Algorithms\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.codemonkey.com\\\/ru\\\/#listItem\",\"name\":\"Home\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.codemonkey.com\\\/ru\\\/interactive-cs-tools\\\/sorting-algorithms\\\/#listItem\",\"position\":3,\"name\":\"Sorting Algorithms\",\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.codemonkey.com\\\/ru\\\/interactive-cs-tools\\\/#listItem\",\"name\":\"Free Teacher Tools for Computer Science\"}}]},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.codemonkey.com\\\/ru\\\/#organization\",\"name\":\"CodeMonkey\",\"url\":\"https:\\\/\\\/www.codemonkey.com\\\/ru\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https:\\\/\\\/d3sujgifhk94se.cloudfront.net\\\/wp-content\\\/uploads\\\/2020\\\/06\\\/21143425\\\/codemonkey_logo.png\",\"@id\":\"https:\\\/\\\/www.codemonkey.com\\\/ru\\\/interactive-cs-tools\\\/sorting-algorithms\\\/#organizationLogo\",\"width\":200,\"height\":31,\"caption\":\"Codemonkey Coding for Kids\"},\"image\":{\"@id\":\"https:\\\/\\\/www.codemonkey.com\\\/ru\\\/interactive-cs-tools\\\/sorting-algorithms\\\/#organizationLogo\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.codemonkey.com\\\/ru\\\/interactive-cs-tools\\\/sorting-algorithms\\\/#webpage\",\"url\":\"https:\\\/\\\/www.codemonkey.com\\\/ru\\\/interactive-cs-tools\\\/sorting-algorithms\\\/\",\"name\":\"Sorting Algorithms - CodeMonkey\",\"description\":\"Sorting Visualizer Interactive CS Tools Sorting Visualizer Watch five classic algorithms put a list in order, one step at a time. Pause, rewind and follow every move. Algorithm Level Easy Advanced Starting data Random Nearly sorted Reversed Few unique values Bars: 12 New data Play Speed 5 Step 0 How it works What the computer\",\"inLanguage\":\"ru-RU\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.codemonkey.com\\\/ru\\\/#website\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.codemonkey.com\\\/ru\\\/interactive-cs-tools\\\/sorting-algorithms\\\/#breadcrumblist\"},\"datePublished\":\"2026-10-08T11:06:13+00:00\",\"dateModified\":\"2026-10-29T16:55:21+00:00\"},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.codemonkey.com\\\/ru\\\/#website\",\"url\":\"https:\\\/\\\/www.codemonkey.com\\\/ru\\\/\",\"name\":\"CodeMonkey\",\"inLanguage\":\"ru-RU\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.codemonkey.com\\\/ru\\\/#organization\"}}]}\n\t\t<\/script>\n\t\t<!-- All in One SEO Pro -->\r\n\t\t<title>Sorting Algorithms - CodeMonkey<\/title>\n\n","aioseo_head_json":{"title":"Sorting Algorithms - CodeMonkey","description":"Sorting Visualizer Interactive CS Tools Sorting Visualizer Watch five classic algorithms put a list in order, one step at a time. Pause, rewind and follow every move. Algorithm Level Easy Advanced Starting data Random Nearly sorted Reversed Few unique values Bars: 12 New data Play Speed 5 Step 0 How it works What the computer","canonical_url":"https:\/\/www.codemonkey.com\/ru\/interactive-cs-tools\/sorting-algorithms\/","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"BreadcrumbList","@id":"https:\/\/www.codemonkey.com\/ru\/interactive-cs-tools\/sorting-algorithms\/#breadcrumblist","itemListElement":[{"@type":"ListItem","@id":"https:\/\/www.codemonkey.com\/ru\/#listItem","position":1,"name":"Home","item":"https:\/\/www.codemonkey.com\/ru\/","nextItem":{"@type":"ListItem","@id":"https:\/\/www.codemonkey.com\/ru\/interactive-cs-tools\/#listItem","name":"Free Teacher Tools for Computer Science"}},{"@type":"ListItem","@id":"https:\/\/www.codemonkey.com\/ru\/interactive-cs-tools\/#listItem","position":2,"name":"Free Teacher Tools for Computer Science","item":"https:\/\/www.codemonkey.com\/ru\/interactive-cs-tools\/","nextItem":{"@type":"ListItem","@id":"https:\/\/www.codemonkey.com\/ru\/interactive-cs-tools\/sorting-algorithms\/#listItem","name":"Sorting Algorithms"},"previousItem":{"@type":"ListItem","@id":"https:\/\/www.codemonkey.com\/ru\/#listItem","name":"Home"}},{"@type":"ListItem","@id":"https:\/\/www.codemonkey.com\/ru\/interactive-cs-tools\/sorting-algorithms\/#listItem","position":3,"name":"Sorting Algorithms","previousItem":{"@type":"ListItem","@id":"https:\/\/www.codemonkey.com\/ru\/interactive-cs-tools\/#listItem","name":"Free Teacher Tools for Computer Science"}}]},{"@type":"Organization","@id":"https:\/\/www.codemonkey.com\/ru\/#organization","name":"CodeMonkey","url":"https:\/\/www.codemonkey.com\/ru\/","logo":{"@type":"ImageObject","url":"https:\/\/d3sujgifhk94se.cloudfront.net\/wp-content\/uploads\/2020\/06\/21143425\/codemonkey_logo.png","@id":"https:\/\/www.codemonkey.com\/ru\/interactive-cs-tools\/sorting-algorithms\/#organizationLogo","width":200,"height":31,"caption":"Codemonkey Coding for Kids"},"image":{"@id":"https:\/\/www.codemonkey.com\/ru\/interactive-cs-tools\/sorting-algorithms\/#organizationLogo"}},{"@type":"WebPage","@id":"https:\/\/www.codemonkey.com\/ru\/interactive-cs-tools\/sorting-algorithms\/#webpage","url":"https:\/\/www.codemonkey.com\/ru\/interactive-cs-tools\/sorting-algorithms\/","name":"Sorting Algorithms - CodeMonkey","description":"Sorting Visualizer Interactive CS Tools Sorting Visualizer Watch five classic algorithms put a list in order, one step at a time. Pause, rewind and follow every move. Algorithm Level Easy Advanced Starting data Random Nearly sorted Reversed Few unique values Bars: 12 New data Play Speed 5 Step 0 How it works What the computer","inLanguage":"ru-RU","isPartOf":{"@id":"https:\/\/www.codemonkey.com\/ru\/#website"},"breadcrumb":{"@id":"https:\/\/www.codemonkey.com\/ru\/interactive-cs-tools\/sorting-algorithms\/#breadcrumblist"},"datePublished":"2026-10-08T11:06:13+00:00","dateModified":"2026-10-29T16:55:21+00:00"},{"@type":"WebSite","@id":"https:\/\/www.codemonkey.com\/ru\/#website","url":"https:\/\/www.codemonkey.com\/ru\/","name":"CodeMonkey","inLanguage":"ru-RU","publisher":{"@id":"https:\/\/www.codemonkey.com\/ru\/#organization"}}]},"og:locale":"ru_RU","og:site_name":"CodeMonkey -","og:type":"article","og:title":"Sorting Algorithms - CodeMonkey","og:description":"Sorting Visualizer Interactive CS Tools Sorting Visualizer Watch five classic algorithms put a list in order, one step at a time. Pause, rewind and follow every move. Algorithm Level Easy Advanced Starting data Random Nearly sorted Reversed Few unique values Bars: 12 New data Play Speed 5 Step 0 How it works What the computer","og:url":"https:\/\/www.codemonkey.com\/ru\/interactive-cs-tools\/sorting-algorithms\/","og:image":"https:\/\/d3sujgifhk94se.cloudfront.net\/wp-content\/uploads\/2020\/06\/21143425\/codemonkey_logo.png","og:image:secure_url":"https:\/\/d3sujgifhk94se.cloudfront.net\/wp-content\/uploads\/2020\/06\/21143425\/codemonkey_logo.png","article:published_time":"2026-10-08T11:06:13+00:00","article:modified_time":"2026-10-29T16:55:21+00:00","twitter:card":"summary_large_image","twitter:title":"Sorting Algorithms - CodeMonkey","twitter:description":"Sorting Visualizer Interactive CS Tools Sorting Visualizer Watch five classic algorithms put a list in order, one step at a time. Pause, rewind and follow every move. Algorithm Level Easy Advanced Starting data Random Nearly sorted Reversed Few unique values Bars: 12 New data Play Speed 5 Step 0 How it works What the computer","twitter:image":"https:\/\/d3sujgifhk94se.cloudfront.net\/wp-content\/uploads\/2020\/06\/21143425\/codemonkey_logo.png"},"aioseo_meta_data":{"post_id":"31056","title":null,"description":null,"keywords":null,"keyphrases":{"focus":{"keyphrase":"","score":0,"analysis":{"keyphraseInTitle":{"score":0,"maxScore":9,"error":1}}},"additional":[]},"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":"","og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"WebPage","isEnabled":true},"graphs":[]},"schema_type":"default","schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":"-1","robots_max_videopreview":"-1","robots_max_imagepreview":"large","priority":null,"frequency":"default","local_seo":null,"limit_modified_date":false,"open_ai":null,"created":"2026-10-08 11:02:52","updated":"2026-10-29 16:55:42","focus_keyword":null,"additional_keywords":null,"truseo_locale":null,"ai":{"faqs":[],"keyPoints":[],"schemas":[],"titles":[],"descriptions":[],"socialPosts":{"email":{"subject":"","preview":"","content":""},"linkedin":[],"twitter":[],"facebook":[],"instagram":[]}},"breadcrumb_settings":null,"seo_analyzer_scan_date":"2026-10-29 16:55:36"},"aioseo_breadcrumb":"<div class=\"aioseo-breadcrumbs\"><span class=\"aioseo-breadcrumb\">\n\t<a href=\"https:\/\/www.codemonkey.com\/ru\/\" title=\"Home\">Home<\/a>\n<\/span><span class=\"aioseo-breadcrumb-separator\">\u00bb<\/span><span class=\"aioseo-breadcrumb\">\n\t<a href=\"https:\/\/www.codemonkey.com\/ru\/interactive-cs-tools\/\" title=\"Free Teacher Tools for Computer Science\">Free Teacher Tools for Computer Science<\/a>\n<\/span><span class=\"aioseo-breadcrumb-separator\">\u00bb<\/span><span class=\"aioseo-breadcrumb\">\n\tSorting Algorithms\n<\/span><\/div>","aioseo_breadcrumb_json":[{"label":"Home","link":"https:\/\/www.codemonkey.com\/ru\/"},{"label":"Free Teacher Tools for Computer Science","link":"https:\/\/www.codemonkey.com\/ru\/interactive-cs-tools\/"},{"label":"Sorting Algorithms","link":"https:\/\/www.codemonkey.com\/ru\/interactive-cs-tools\/sorting-algorithms\/"}],"_links":{"self":[{"href":"https:\/\/www.codemonkey.com\/ru\/wp-json\/wp\/v2\/pages\/31056","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.codemonkey.com\/ru\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.codemonkey.com\/ru\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.codemonkey.com\/ru\/wp-json\/wp\/v2\/users\/55"}],"replies":[{"embeddable":true,"href":"https:\/\/www.codemonkey.com\/ru\/wp-json\/wp\/v2\/comments?post=31056"}],"version-history":[{"count":6,"href":"https:\/\/www.codemonkey.com\/ru\/wp-json\/wp\/v2\/pages\/31056\/revisions"}],"predecessor-version":[{"id":31226,"href":"https:\/\/www.codemonkey.com\/ru\/wp-json\/wp\/v2\/pages\/31056\/revisions\/31226"}],"up":[{"embeddable":true,"href":"https:\/\/www.codemonkey.com\/ru\/wp-json\/wp\/v2\/pages\/31237"}],"wp:attachment":[{"href":"https:\/\/www.codemonkey.com\/ru\/wp-json\/wp\/v2\/media?parent=31056"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}