[{"data":1,"prerenderedAt":1386},["ShallowReactive",2],{"navigation":3,"\u002Fblog\u002Fpython\u002Fst27":386,"\u002Fblog\u002Fpython\u002Fst27-surround":1381},[4],{"title":5,"path":6,"stem":7,"children":8,"page":114},"Blog","\u002Fblog","blog",[9,115,184,329],{"title":10,"path":11,"stem":12,"children":13,"page":114},"Ege","\u002Fblog\u002Fege","blog\u002Fege",[14,18,22,26,30,34,38,42,46,50,54,58,62,66,70,74,78,82,86,90,94,98,102,106,110],{"title":15,"path":16,"stem":17},"ЕГЭ Задание 1","\u002Fblog\u002Fege\u002Ftask1","blog\u002Fege\u002Ftask1",{"title":19,"path":20,"stem":21},"ЕГЭ Задание 10","\u002Fblog\u002Fege\u002Ftask10","blog\u002Fege\u002Ftask10",{"title":23,"path":24,"stem":25},"ЕГЭ Задание 11","\u002Fblog\u002Fege\u002Ftask11","blog\u002Fege\u002Ftask11",{"title":27,"path":28,"stem":29},"ЕГЭ Задание 12","\u002Fblog\u002Fege\u002Ftask12","blog\u002Fege\u002Ftask12",{"title":31,"path":32,"stem":33},"ЕГЭ Задание 13","\u002Fblog\u002Fege\u002Ftask13","blog\u002Fege\u002Ftask13",{"title":35,"path":36,"stem":37},"ЕГЭ Задание 14","\u002Fblog\u002Fege\u002Ftask14","blog\u002Fege\u002Ftask14",{"title":39,"path":40,"stem":41},"ЕГЭ Задание 15","\u002Fblog\u002Fege\u002Ftask15","blog\u002Fege\u002Ftask15",{"title":43,"path":44,"stem":45},"ЕГЭ Задание 16","\u002Fblog\u002Fege\u002Ftask16","blog\u002Fege\u002Ftask16",{"title":47,"path":48,"stem":49},"ЕГЭ Задание 17","\u002Fblog\u002Fege\u002Ftask17","blog\u002Fege\u002Ftask17",{"title":51,"path":52,"stem":53},"ЕГЭ Задание 18","\u002Fblog\u002Fege\u002Ftask18","blog\u002Fege\u002Ftask18",{"title":55,"path":56,"stem":57},"ЕГЭ Задание 19, 20, 21","\u002Fblog\u002Fege\u002Ftask19_20_21","blog\u002Fege\u002Ftask19_20_21",{"title":59,"path":60,"stem":61},"ЕГЭ Задание 2","\u002Fblog\u002Fege\u002Ftask2","blog\u002Fege\u002Ftask2",{"title":63,"path":64,"stem":65},"ЕГЭ Задание 22","\u002Fblog\u002Fege\u002Ftask22","blog\u002Fege\u002Ftask22",{"title":67,"path":68,"stem":69},"ЕГЭ Задание 23","\u002Fblog\u002Fege\u002Ftask23","blog\u002Fege\u002Ftask23",{"title":71,"path":72,"stem":73},"ЕГЭ Задание 24","\u002Fblog\u002Fege\u002Ftask24","blog\u002Fege\u002Ftask24",{"title":75,"path":76,"stem":77},"ЕГЭ Задание 25","\u002Fblog\u002Fege\u002Ftask25","blog\u002Fege\u002Ftask25",{"title":79,"path":80,"stem":81},"ЕГЭ Задание 26","\u002Fblog\u002Fege\u002Ftask26","blog\u002Fege\u002Ftask26",{"title":83,"path":84,"stem":85},"ЕГЭ Задание 27","\u002Fblog\u002Fege\u002Ftask27","blog\u002Fege\u002Ftask27",{"title":87,"path":88,"stem":89},"ЕГЭ Задание 3","\u002Fblog\u002Fege\u002Ftask3","blog\u002Fege\u002Ftask3",{"title":91,"path":92,"stem":93},"ЕГЭ Задание 4","\u002Fblog\u002Fege\u002Ftask4","blog\u002Fege\u002Ftask4",{"title":95,"path":96,"stem":97},"ЕГЭ Задание 5","\u002Fblog\u002Fege\u002Ftask5","blog\u002Fege\u002Ftask5",{"title":99,"path":100,"stem":101},"ЕГЭ Задание 6","\u002Fblog\u002Fege\u002Ftask6","blog\u002Fege\u002Ftask6",{"title":103,"path":104,"stem":105},"ЕГЭ Задание 7","\u002Fblog\u002Fege\u002Ftask7","blog\u002Fege\u002Ftask7",{"title":107,"path":108,"stem":109},"ЕГЭ Задание 8","\u002Fblog\u002Fege\u002Ftask8","blog\u002Fege\u002Ftask8",{"title":111,"path":112,"stem":113},"ЕГЭ Задание 9","\u002Fblog\u002Fege\u002Ftask9","blog\u002Fege\u002Ftask9",false,{"title":116,"path":117,"stem":118,"children":119,"page":114},"Oge","\u002Fblog\u002Foge","blog\u002Foge",[120,124,128,132,136,140,144,148,152,156,160,164,168,172,176,180],{"title":121,"path":122,"stem":123},"ОГЭ Задание 1","\u002Fblog\u002Foge\u002Ftask1","blog\u002Foge\u002Ftask1",{"title":125,"path":126,"stem":127},"ОГЭ Задание 10","\u002Fblog\u002Foge\u002Ftask10","blog\u002Foge\u002Ftask10",{"title":129,"path":130,"stem":131},"ОГЭ Задание 11","\u002Fblog\u002Foge\u002Ftask11","blog\u002Foge\u002Ftask11",{"title":133,"path":134,"stem":135},"ОГЭ Задание 12","\u002Fblog\u002Foge\u002Ftask12","blog\u002Foge\u002Ftask12",{"title":137,"path":138,"stem":139},"ОГЭ Задание 13","\u002Fblog\u002Foge\u002Ftask13","blog\u002Foge\u002Ftask13",{"title":141,"path":142,"stem":143},"ОГЭ Задание 14","\u002Fblog\u002Foge\u002Ftask14","blog\u002Foge\u002Ftask14",{"title":145,"path":146,"stem":147},"ОГЭ Задание 15","\u002Fblog\u002Foge\u002Ftask15","blog\u002Foge\u002Ftask15",{"title":149,"path":150,"stem":151},"ОГЭ Задание 16","\u002Fblog\u002Foge\u002Ftask16","blog\u002Foge\u002Ftask16",{"title":153,"path":154,"stem":155},"ОГЭ Задание 2","\u002Fblog\u002Foge\u002Ftask2","blog\u002Foge\u002Ftask2",{"title":157,"path":158,"stem":159},"ОГЭ Задание 3","\u002Fblog\u002Foge\u002Ftask3","blog\u002Foge\u002Ftask3",{"title":161,"path":162,"stem":163},"ОГЭ Задание 4","\u002Fblog\u002Foge\u002Ftask4","blog\u002Foge\u002Ftask4",{"title":165,"path":166,"stem":167},"ОГЭ Задание 5","\u002Fblog\u002Foge\u002Ftask5","blog\u002Foge\u002Ftask5",{"title":169,"path":170,"stem":171},"ОГЭ Задание 6","\u002Fblog\u002Foge\u002Ftask6","blog\u002Foge\u002Ftask6",{"title":173,"path":174,"stem":175},"ОГЭ Задание 7","\u002Fblog\u002Foge\u002Ftask7","blog\u002Foge\u002Ftask7",{"title":177,"path":178,"stem":179},"ОГЭ Задание 8","\u002Fblog\u002Foge\u002Ftask8","blog\u002Foge\u002Ftask8",{"title":181,"path":182,"stem":183},"ОГЭ Задание 9","\u002Fblog\u002Foge\u002Ftask9","blog\u002Foge\u002Ftask9",{"title":185,"path":186,"stem":187,"children":188,"page":114},"Python","\u002Fblog\u002Fpython","blog\u002Fpython",[189,193,197,201,205,209,213,217,221,225,229,233,237,241,245,249,253,257,261,265,269,273,277,281,285,289,293,297,301,305,309,313,317,321,325],{"title":190,"path":191,"stem":192},"Знакомство с синтаксисом","\u002Fblog\u002Fpython\u002Fst1","blog\u002Fpython\u002Fst1",{"title":194,"path":195,"stem":196},"Отладка","\u002Fblog\u002Fpython\u002Fst10","blog\u002Fpython\u002Fst10",{"title":198,"path":199,"stem":200},"Модули и пакеты","\u002Fblog\u002Fpython\u002Fst11","blog\u002Fpython\u002Fst11",{"title":202,"path":203,"stem":204},"Кортежи","\u002Fblog\u002Fpython\u002Fst12","blog\u002Fpython\u002Fst12",{"title":206,"path":207,"stem":208},"Знакомство со списками","\u002Fblog\u002Fpython\u002Fst13","blog\u002Fpython\u002Fst13",{"title":210,"path":211,"stem":212},"Списки и циклы","\u002Fblog\u002Fpython\u002Fst14","blog\u002Fpython\u002Fst14",{"title":214,"path":215,"stem":216},"Использование списков ч.1","\u002Fblog\u002Fpython\u002Fst15","blog\u002Fpython\u002Fst15",{"title":218,"path":219,"stem":220},"Использование списков ч.2","\u002Fblog\u002Fpython\u002Fst16","blog\u002Fpython\u002Fst16",{"title":222,"path":223,"stem":224},"Использование списков ч.3","\u002Fblog\u002Fpython\u002Fst17","blog\u002Fpython\u002Fst17",{"title":226,"path":227,"stem":228},"Словари","\u002Fblog\u002Fpython\u002Fst18","blog\u002Fpython\u002Fst18",{"title":230,"path":231,"stem":232},"Множества","\u002Fblog\u002Fpython\u002Fst19","blog\u002Fpython\u002Fst19",{"title":234,"path":235,"stem":236},"Переменные","\u002Fblog\u002Fpython\u002Fst2","blog\u002Fpython\u002Fst2",{"title":238,"path":239,"stem":240},"Хеш-таблицы","\u002Fblog\u002Fpython\u002Fst20","blog\u002Fpython\u002Fst20",{"title":242,"path":243,"stem":244},"Решето Эратосфена","\u002Fblog\u002Fpython\u002Fst21","blog\u002Fpython\u002Fst21",{"title":246,"path":247,"stem":248},"Длинная арифметика","\u002Fblog\u002Fpython\u002Fst22","blog\u002Fpython\u002Fst22",{"title":250,"path":251,"stem":252},"Декораторы функций","\u002Fblog\u002Fpython\u002Fst23","blog\u002Fpython\u002Fst23",{"title":254,"path":255,"stem":256},"Знакомство с алгоритмами","\u002Fblog\u002Fpython\u002Fst24","blog\u002Fpython\u002Fst24",{"title":258,"path":259,"stem":260},"Бинарный поиск – примеры задач","\u002Fblog\u002Fpython\u002Fst25","blog\u002Fpython\u002Fst25",{"title":262,"path":263,"stem":264},"Сортировка выбором","\u002Fblog\u002Fpython\u002Fst26","blog\u002Fpython\u002Fst26",{"title":266,"path":267,"stem":268},"Рекурсия и стек","\u002Fblog\u002Fpython\u002Fst27","blog\u002Fpython\u002Fst27",{"title":270,"path":271,"stem":272},"Быстрая сортировка","\u002Fblog\u002Fpython\u002Fst28","blog\u002Fpython\u002Fst28",{"title":274,"path":275,"stem":276},"Поиск в ширину","\u002Fblog\u002Fpython\u002Fst29","blog\u002Fpython\u002Fst29",{"title":278,"path":279,"stem":280},"Работа со строками","\u002Fblog\u002Fpython\u002Fst3","blog\u002Fpython\u002Fst3",{"title":282,"path":283,"stem":284},"Поиск в глубину","\u002Fblog\u002Fpython\u002Fst30","blog\u002Fpython\u002Fst30",{"title":286,"path":287,"stem":288},"Сбалансированные деревья","\u002Fblog\u002Fpython\u002Fst31","blog\u002Fpython\u002Fst31",{"title":290,"path":291,"stem":292},"Алгоритм Дейкстры","\u002Fblog\u002Fpython\u002Fst32","blog\u002Fpython\u002Fst32",{"title":294,"path":295,"stem":296},"Жадные алгоритмы","\u002Fblog\u002Fpython\u002Fst33","blog\u002Fpython\u002Fst33",{"title":298,"path":299,"stem":300},"Динамическое программирование","\u002Fblog\u002Fpython\u002Fst34","blog\u002Fpython\u002Fst34",{"title":302,"path":303,"stem":304},"Алгоритм k ближайших соседей","\u002Fblog\u002Fpython\u002Fst35","blog\u002Fpython\u002Fst35",{"title":306,"path":307,"stem":308},"Типы данных","\u002Fblog\u002Fpython\u002Fst4","blog\u002Fpython\u002Fst4",{"title":310,"path":311,"stem":312},"О функциях","\u002Fblog\u002Fpython\u002Fst5","blog\u002Fpython\u002Fst5",{"title":314,"path":315,"stem":316},"Свойства и методы","\u002Fblog\u002Fpython\u002Fst6","blog\u002Fpython\u002Fst6",{"title":318,"path":319,"stem":320},"Определение функций","\u002Fblog\u002Fpython\u002Fst7","blog\u002Fpython\u002Fst7",{"title":322,"path":323,"stem":324},"Логика","\u002Fblog\u002Fpython\u002Fst8","blog\u002Fpython\u002Fst8",{"title":326,"path":327,"stem":328},"Циклы","\u002Fblog\u002Fpython\u002Fst9","blog\u002Fpython\u002Fst9",{"title":330,"path":331,"stem":332,"children":333,"page":114},"Toi","\u002Fblog\u002Ftoi","blog\u002Ftoi",[334,338,342,346,350,354,358,362,366,370,374,378,382],{"title":335,"path":336,"stem":337},"Информация и информационные процессы","\u002Fblog\u002Ftoi\u002Fst1","blog\u002Ftoi\u002Fst1",{"title":339,"path":340,"stem":341},"Электронные таблицы","\u002Fblog\u002Ftoi\u002Fst10","blog\u002Ftoi\u002Fst10",{"title":343,"path":344,"stem":345},"Система, её свойства и компоненты. Моделирование","\u002Fblog\u002Ftoi\u002Fst11","blog\u002Ftoi\u002Fst11",{"title":347,"path":348,"stem":349},"Представление информации в компьютере","\u002Fblog\u002Ftoi\u002Fst12","blog\u002Ftoi\u002Fst12",{"title":351,"path":352,"stem":353},"Средства информационно-коммуникационных технологий. Файловая система","\u002Fblog\u002Ftoi\u002Fst13","blog\u002Ftoi\u002Fst13",{"title":355,"path":356,"stem":357},"Комбинаторика","\u002Fblog\u002Ftoi\u002Fst2","blog\u002Ftoi\u002Fst2",{"title":359,"path":360,"stem":361},"Адресация в интернете","\u002Fblog\u002Ftoi\u002Fst3","blog\u002Ftoi\u002Fst3",{"title":363,"path":364,"stem":365},"Измерение количества информации","\u002Fblog\u002Ftoi\u002Fst4","blog\u002Ftoi\u002Fst4",{"title":367,"path":368,"stem":369},"Системы счисления","\u002Fblog\u002Ftoi\u002Fst5","blog\u002Ftoi\u002Fst5",{"title":371,"path":372,"stem":373},"Диаграммы Эйлера — Венна","\u002Fblog\u002Ftoi\u002Fst6","blog\u002Ftoi\u002Fst6",{"title":375,"path":376,"stem":377},"Условие Фано","\u002Fblog\u002Ftoi\u002Fst7","blog\u002Ftoi\u002Fst7",{"title":379,"path":380,"stem":381},"Теория графов","\u002Fblog\u002Ftoi\u002Fst8","blog\u002Ftoi\u002Fst8",{"title":383,"path":384,"stem":385},"Алгебра логики","\u002Fblog\u002Ftoi\u002Fst9","blog\u002Ftoi\u002Fst9",{"id":387,"title":266,"author":388,"body":393,"date":1372,"description":1373,"extension":1374,"image":1375,"meta":1376,"minRead":1377,"navigation":692,"num":1378,"path":267,"seo":1379,"stem":268,"__hash__":1380},"python\u002Fblog\u002Fpython\u002Fst27.md",{"name":389,"avatar":390},"Штана Альберт Игоревич",{"src":391,"alt":392},"me.jpg","@ashtana",{"type":394,"value":395,"toc":1356},"minimark",[396,401,406,410,429,432,443,451,574,582,641,644,649,652,704,715,775,778,782,789,800,805,819,878,881,939,973,977,980,1044,1055,1060,1182,1186,1213,1217,1240,1244,1284,1288,1299,1309,1312,1324,1328,1330,1337,1349,1352],[397,398,400],"h2",{"id":399},"рекурсия","Рекурсия",[402,403],"card-collapsible",{":isList":404,"title":405},"[\"Вы узнаете что такое рекурсия – метод программирования, используемый во многих алгоритмах.\",\"Вы научитесь разбивать задачи на базовый и рекурсивный случаи.\"]","Из этой статьи вы узнаете",[407,408,409],"p",{},"Представьте, вы находите запертый загадочный сундук. Ключ от сундука лежит в коробке. В комнате где вы нашли сундук есть также множество всяких коробок.\nВ коробках могут лежать и другие коробки(например, меньшего размера). Ключ находится где в одной из таких коробок.\nКакой алгоритм поиска ключа можно придумать? Одно из решений может быть таким:",[411,412,413,417,420,423,426],"ol",{},[414,415,416],"li",{},"Сложить все коробки в кучу или просто обнаружить их все которые существуют на виду;",[414,418,419],{},"Открыть какую нибудь закрытую коробку;",[414,421,422],{},"Если внутри лежит коробка, добавить её в кучу для последующего вскрытия и иска;",[414,424,425],{},"Если внутри лежит ключ, поиск закончен!",[414,427,428],{},"Повторить пункт 2.",[407,430,431],{},"Есть также альтернативное решение:",[411,433,434,437,440],{},[414,435,436],{},"Просмотреть содержимое коробки;",[414,438,439],{},"Если найдена внутри ещё коробка, выполнить пункт 1;",[414,441,442],{},"Если нашли ключ, то поиск закончен!",[407,444,445,446,450],{},"Какое решение наиболее простое? Первое решение можно построить на цикле ",[447,448,449],"code",{},"while",". Пока куча коробок не пуста, взять очередную коробку и проверить её содержимое.\nНапишем условный или псевдокод на python:",[452,453,458],"pre",{"className":454,"code":455,"language":456,"meta":457,"style":457},"language-python shiki shiki-themes github-light","def look_key(box):\n  pile = box.make_to_look()\n  while pile is not empty:\n    bx = pile.give_box()\n    for item in bx:\n      if item.is_a_box():\n        pile.append(item)\n      elif item.is_a_key():\n        print(\"Найден ключ!\")\n","python","",[447,459,460,477,489,507,518,533,542,548,557],{"__ignoreMap":457},[461,462,465,469,473],"span",{"class":463,"line":464},"line",1,[461,466,468],{"class":467},"sD7c4","def",[461,470,472],{"class":471},"s7eDp"," look_key",[461,474,476],{"class":475},"sgsFI","(box):\n",[461,478,480,483,486],{"class":463,"line":479},2,[461,481,482],{"class":475},"  pile ",[461,484,485],{"class":467},"=",[461,487,488],{"class":475}," box.make_to_look()\n",[461,490,492,495,498,501,504],{"class":463,"line":491},3,[461,493,494],{"class":467},"  while",[461,496,497],{"class":475}," pile ",[461,499,500],{"class":467},"is",[461,502,503],{"class":467}," not",[461,505,506],{"class":475}," empty:\n",[461,508,510,513,515],{"class":463,"line":509},4,[461,511,512],{"class":475},"    bx ",[461,514,485],{"class":467},[461,516,517],{"class":475}," pile.give_box()\n",[461,519,521,524,527,530],{"class":463,"line":520},5,[461,522,523],{"class":467},"    for",[461,525,526],{"class":475}," item ",[461,528,529],{"class":467},"in",[461,531,532],{"class":475}," bx:\n",[461,534,536,539],{"class":463,"line":535},6,[461,537,538],{"class":467},"      if",[461,540,541],{"class":475}," item.is_a_box():\n",[461,543,545],{"class":463,"line":544},7,[461,546,547],{"class":475},"        pile.append(item)\n",[461,549,551,554],{"class":463,"line":550},8,[461,552,553],{"class":467},"      elif",[461,555,556],{"class":475}," item.is_a_key():\n",[461,558,560,564,567,571],{"class":463,"line":559},9,[461,561,563],{"class":562},"sYu0t","        print",[461,565,566],{"class":475},"(",[461,568,570],{"class":569},"sYBdl","\"Найден ключ!\"",[461,572,573],{"class":475},")\n",[407,575,576,577,581],{},"Второй способ основан на таком алгоритме и понятии как рекурсия. ",[578,579,580],"em",{},"Рекурсией"," называется вызов функции самой себя. Второе решение на псевдокоде может выглядеть так:",[452,583,585],{"className":454,"code":584,"language":456,"meta":457,"style":457},"def look_key(box):\n  for item in box:\n    if item.is_a_box():\n      look_key(item)  # Здесь рекурсия!\n    elif item.is_a_key():\n      print(\"Найден ключ!\")\n",[447,586,587,595,607,614,623,630],{"__ignoreMap":457},[461,588,589,591,593],{"class":463,"line":464},[461,590,468],{"class":467},[461,592,472],{"class":471},[461,594,476],{"class":475},[461,596,597,600,602,604],{"class":463,"line":479},[461,598,599],{"class":467},"  for",[461,601,526],{"class":475},[461,603,529],{"class":467},[461,605,606],{"class":475}," box:\n",[461,608,609,612],{"class":463,"line":491},[461,610,611],{"class":467},"    if",[461,613,541],{"class":475},[461,615,616,619],{"class":463,"line":509},[461,617,618],{"class":475},"      look_key(item)  ",[461,620,622],{"class":621},"sAwPA","# Здесь рекурсия!\n",[461,624,625,628],{"class":463,"line":520},[461,626,627],{"class":467},"    elif",[461,629,556],{"class":475},[461,631,632,635,637,639],{"class":463,"line":535},[461,633,634],{"class":562},"      print",[461,636,566],{"class":475},[461,638,570],{"class":569},[461,640,573],{"class":475},[407,642,643],{},"Оба решения делают одно и тоже. При этом второе решение короче и когда вам известен такой способ как рекурсия, решение это становится более понятным.\nПрименение рекурсии не ускоряет работу программы. Более того, решение циклами и с помощью динамического программирование(о нём в другой статье) иногда работает даже быстрее.\nМне нравится одна фраза на эту тему: \"Рекурсия может ускорить работу программиста, циклы могут ускорить работу программы. Выбирайте что вам нужнее в вашей ситуации!\"\nРекурсия используется во многих задачах, поэтому важно понимать её концепцию и применимость.",[645,646,648],"h3",{"id":647},"базовый-и-рекурсивный-случай","Базовый и рекурсивный случай",[407,650,651],{},"Так как рекурсивная функция вызывает сама себя, программисту легко ошибиться и написать функцию так, что возникнет бесконечный вызов такой рекурсивной функции.\nПредположим, вы хотите написать функцию для вывода обратного отсчёта: 3...2...1\nЕё можно записать с помощью рекурсии:",[452,653,655],{"className":454,"code":654,"language":456,"meta":457,"style":457},"def ctdown(i):\n  print(i)\n  ctdown(i-1)\n\nctdown(3)\n",[447,656,657,667,675,688,694],{"__ignoreMap":457},[461,658,659,661,664],{"class":463,"line":464},[461,660,468],{"class":467},[461,662,663],{"class":471}," ctdown",[461,665,666],{"class":475},"(i):\n",[461,668,669,672],{"class":463,"line":479},[461,670,671],{"class":562},"  print",[461,673,674],{"class":475},"(i)\n",[461,676,677,680,683,686],{"class":463,"line":491},[461,678,679],{"class":475},"  ctdown(i",[461,681,682],{"class":467},"-",[461,684,685],{"class":562},"1",[461,687,573],{"class":475},[461,689,690],{"class":463,"line":509},[461,691,693],{"emptyLinePlaceholder":692},true,"\n",[461,695,696,699,702],{"class":463,"line":520},[461,697,698],{"class":475},"ctdown(",[461,700,701],{"class":562},"3",[461,703,573],{"class":475},[407,705,706,707,710,711,714],{},"Запустив такой код возникает проблема: эта функция будет выполнять бесконечно! Чтобы прервать выполнение, нужно закрыть консоль или нажать Ctrl+C.\nКогда вы пишете рекурсивную функцию, в ней необходимо предусмотреть момент прерывания рекурсии.\nПоэтому каждая правильно написанная ",[578,708,709],{},"рекурсивная функция состоит из двух частей: базового и рекурсивного случая.","\nВ рекурсивном случае функция вызывает сама себя. В базовом случае функция себя не вызывает, а наоборот предотвращает вызов и тем самым \"зацикливание\".\nДобавим базовый случай в функцию ",[447,712,713],{},"ctdown",":",[452,716,718],{"className":454,"code":717,"language":456,"meta":457,"style":457},"def ctdown(i):\n  print(i)\n  if i \u003C= i:\n    return\n  ctdown(i-1)\n\nctdown(3)\n",[447,719,720,728,734,748,753,763,767],{"__ignoreMap":457},[461,721,722,724,726],{"class":463,"line":464},[461,723,468],{"class":467},[461,725,663],{"class":471},[461,727,666],{"class":475},[461,729,730,732],{"class":463,"line":479},[461,731,671],{"class":562},[461,733,674],{"class":475},[461,735,736,739,742,745],{"class":463,"line":491},[461,737,738],{"class":467},"  if",[461,740,741],{"class":475}," i ",[461,743,744],{"class":467},"\u003C=",[461,746,747],{"class":475}," i:\n",[461,749,750],{"class":463,"line":509},[461,751,752],{"class":467},"    return\n",[461,754,755,757,759,761],{"class":463,"line":520},[461,756,679],{"class":475},[461,758,682],{"class":467},[461,760,685],{"class":562},[461,762,573],{"class":475},[461,764,765],{"class":463,"line":535},[461,766,693],{"emptyLinePlaceholder":692},[461,768,769,771,773],{"class":463,"line":544},[461,770,698],{"class":475},[461,772,701],{"class":562},[461,774,573],{"class":475},[407,776,777],{},"Теперь функция работает как было задумано.",[645,779,781],{"id":780},"стек","Стек",[407,783,784,785,788],{},"Рассмотрим такое понятие как ",[578,786,787],{},"стек вызовов",". Концепция стека вызовов важно понимать в программировании и особенно при использовании рекурсии.\nПредположим вы устраиваете вечеринку и составляете список задач записывая все дела на листках.\nЗадачи, представим что это элементы некоторого единого списка, но будут вместе выглядеть как стопка листков.\nНовые (вставленные) элементы добавляются всегда в начало списка, то есть наверх стопки с листочками.\nЧитается всегда только верхний элемент, и он же исключается из списка(из стопки). Таким образом, список задач поддерживает всего два действия:\nзанесение(вставка или добавление) и извлечение (чтение и удаление).\nПосмотрим, как работает такой список задач реализованный через стек:",[411,790,791,794,797],{},[414,792,793],{},"Задача извлекается из стека(из стопки);",[414,795,796],{},"Читается и выполняется;",[414,798,799],{},"Либо пункт 1, 2 повторяются снова(только если стек не будет пустым) либо добавляется новая задача или задачи в стек.\nПрограммисты новички с самого начала программирования уже пользуются стеком даже не подозревая об этом!",[801,802,804],"h4",{"id":803},"стек-вызовов","Стек вызовов",[407,806,807,811,812,814,815,818],{},[808,809],"img",{"alt":804,"src":810},"images\u002Fblog\u002Fpython\u002Fst27\u002Fimg1.png","\nВо внутренней работе вашего компьютера используется ",[578,813,780],{},", называемый ",[578,816,817],{},"стеком вызовов",". Разберёмся как он работает.\nПредположим, имеется простая функция:",[452,820,822],{"className":454,"code":821,"language":456,"meta":457,"style":457},"def greetings(name):\n  print(\"Привет, \" + name + \"!\")\n  greet(name)\n  print(\"Дальше будет пока...\")\n  goodbye()\n",[447,823,824,834,857,862,873],{"__ignoreMap":457},[461,825,826,828,831],{"class":463,"line":464},[461,827,468],{"class":467},[461,829,830],{"class":471}," greetings",[461,832,833],{"class":475},"(name):\n",[461,835,836,838,840,843,846,849,852,855],{"class":463,"line":479},[461,837,671],{"class":562},[461,839,566],{"class":475},[461,841,842],{"class":569},"\"Привет, \"",[461,844,845],{"class":467}," +",[461,847,848],{"class":475}," name ",[461,850,851],{"class":467},"+",[461,853,854],{"class":569}," \"!\"",[461,856,573],{"class":475},[461,858,859],{"class":463,"line":491},[461,860,861],{"class":475},"  greet(name)\n",[461,863,864,866,868,871],{"class":463,"line":509},[461,865,671],{"class":562},[461,867,566],{"class":475},[461,869,870],{"class":569},"\"Дальше будет пока...\"",[461,872,573],{"class":475},[461,874,875],{"class":463,"line":520},[461,876,877],{"class":475},"  goodbye()\n",[407,879,880],{},"Эта функция приветствует вас, после чего вызывает две другие функции. Например:",[452,882,884],{"className":454,"code":883,"language":456,"meta":457,"style":457},"def greet(name):\n  print(\"Как твои дела, \" + name + \"?\")\n\ndef goodbye(name):\n  print(\"Хорошо, пока!\")\n",[447,885,886,895,915,919,928],{"__ignoreMap":457},[461,887,888,890,893],{"class":463,"line":464},[461,889,468],{"class":467},[461,891,892],{"class":471}," greet",[461,894,833],{"class":475},[461,896,897,899,901,904,906,908,910,913],{"class":463,"line":479},[461,898,671],{"class":562},[461,900,566],{"class":475},[461,902,903],{"class":569},"\"Как твои дела, \"",[461,905,845],{"class":467},[461,907,848],{"class":475},[461,909,851],{"class":467},[461,911,912],{"class":569}," \"?\"",[461,914,573],{"class":475},[461,916,917],{"class":463,"line":491},[461,918,693],{"emptyLinePlaceholder":692},[461,920,921,923,926],{"class":463,"line":509},[461,922,468],{"class":467},[461,924,925],{"class":471}," goodbye",[461,927,833],{"class":475},[461,929,930,932,934,937],{"class":463,"line":520},[461,931,671],{"class":562},[461,933,566],{"class":475},[461,935,936],{"class":569},"\"Хорошо, пока!\"",[461,938,573],{"class":475},[407,940,941,942,945,946,949,950,953,954,957,958,961,962,965,966,969,970,972],{},"Разберемся, что происходит при вызове функции.\nПредположим, в программе используется вызов ",[447,943,944],{},"greetings(\"Иван\")",". Сначала ваш компьютер выделяет блок памяти вызова функции.\nЗатем эта память используется. Переменной name присваивается значение \"Иван\"(оно также должно быть сохранено в памяти).\nКаждый раз, когда вы вызываете функцию, компьютер сохраняет в памяти значения всех переменных для вызова.\nДалее выводится приветствие: ",[447,947,948],{},"Привет, Иван!",", после чего следует второй вызов ",[447,951,952],{},"greet(\"Иван\")",".\nИ снова компьютер выделяет блок памяти для вызова функции. Далее ваш компьютер объединяет эти блоки в стек.\nВторой блок в стеке с вызовом функции greet создаётся над первым блоком с вызовом функции greetings.\nВы видите сообщение ",[447,955,956],{},"Как твои дела, Иван?",", после чего возвращается управление из вызова функции. Когда это происходит,\nблок на вершине стека извлекается из него(извлекается вызов функции greet).\nТеперь верхний блок в стеке относится к функции greetings; это означает, что вы вернулись к функции greetings.\nПри вызове функции greet функция greetings ещё не была завершена.\nПолучается, ",[578,959,960],{},"когда происходит вызов функции из другой функции, вызывающая функция приостанавливается в частично завершенном состоянии.","\nВсе значения переменных этой функции остаются в памяти.\nА когда выполнение функции greet будет завершено, происходит возврат к функции greetings в то же место, где выполнение её прервалось.\nИ наконец, далее сначала выводится сообщение ",[447,963,964],{},"Дальше будет пока...",", после чего вызывается функция goodbye.\nБлок для функции goodbye добавляется на вершину стека. И напоследок выводится сообщение ",[447,967,968],{},"Хорошо, пока!"," с выходом из вызова функции.\nУправление снова возвращается функции greet. Делать в программе больше нечего, так что управление возвращается и из функции greetings.\nТакой стек в котором сохранялись вызовы разных функций называется ",[578,971,817],{},".\nПосмотрим, как работает стек вызовов с рекурсивными функциями.",[801,974,976],{"id":975},"стек-вызовов-с-рекурсией","Стек вызовов с рекурсией",[407,978,979],{},"В рекурсивной функции тоже используются стек вызовов!\nСамое просто это посмотреть на примере рекурсивной функции вычисления факториала. На Python запишем её так:",[452,981,983],{"className":454,"code":982,"language":456,"meta":457,"style":457},"def factorial(n):\n  if n == 1:\n    return 1\n  else:\n    return n * factorial(n-1)\n",[447,984,985,995,1011,1019,1026],{"__ignoreMap":457},[461,986,987,989,992],{"class":463,"line":464},[461,988,468],{"class":467},[461,990,991],{"class":471}," factorial",[461,993,994],{"class":475},"(n):\n",[461,996,997,999,1002,1005,1008],{"class":463,"line":479},[461,998,738],{"class":467},[461,1000,1001],{"class":475}," n ",[461,1003,1004],{"class":467},"==",[461,1006,1007],{"class":562}," 1",[461,1009,1010],{"class":475},":\n",[461,1012,1013,1016],{"class":463,"line":491},[461,1014,1015],{"class":467},"    return",[461,1017,1018],{"class":562}," 1\n",[461,1020,1021,1024],{"class":463,"line":509},[461,1022,1023],{"class":467},"  else",[461,1025,1010],{"class":475},[461,1027,1028,1030,1032,1035,1038,1040,1042],{"class":463,"line":520},[461,1029,1015],{"class":467},[461,1031,1001],{"class":475},[461,1033,1034],{"class":467},"*",[461,1036,1037],{"class":475}," factorial(n",[461,1039,682],{"class":467},[461,1041,685],{"class":562},[461,1043,573],{"class":475},[407,1045,1046,1047,1050,1051,1054],{},"Вызов функции ",[447,1048,1049],{},"factorial(5)"," вычисляет факториал 5! и определяется следующим образом: 5! = 5 * 4 * 3 * 2 * 1.\nТо же самое соответствует вызов функции ",[447,1052,1053],{},"factorial(4)"," 4! = 4 * 3 * 2 * 1. Проанализируем этот вызов:",[1056,1057,1059],"h5",{"id":1058},"пошаговое-формирование-стека","Пошаговое формирование стека",[411,1061,1062,1085,1104,1121,1139],{},[414,1063,1064,1065,1067],{},"Вызов ",[447,1066,1053],{},[1068,1069,1070,1075],"ul",{},[414,1071,1072,1073],{},"Создаётся фрейм в стеке: ",[447,1074,1053],{},[414,1076,1077,1078,1081,1082],{},"Условие ",[447,1079,1080],{},"n == 1"," не выполнено → вызов ",[447,1083,1084],{},"factorial(3)",[414,1086,1064,1087,1089],{},[447,1088,1084],{},[1068,1090,1091,1097],{},[414,1092,1093,1094,1096],{},"Новый фрейм: ",[447,1095,1084],{}," (стек: factorial(4) → factorial(3))",[414,1098,1077,1099,1081,1101],{},[447,1100,1080],{},[447,1102,1103],{},"factorial(2)",[414,1105,1106,1107],{},"Вызов factorial(2)\n",[1068,1108,1109,1114],{},[414,1110,1093,1111,1113],{},[447,1112,1103],{}," (стек: factorial(4) → factorial(3) → factorial(2))",[414,1115,1077,1116,1081,1118],{},[447,1117,1080],{},[447,1119,1120],{},"factorial(1)",[414,1122,1064,1123,1125],{},[447,1124,1120],{},[1068,1126,1127,1132],{},[414,1128,1093,1129,1131],{},[447,1130,1120],{}," (стек: factorial(4) → factorial(3) → factorial(2) → factorial(1))",[414,1133,1077,1134,1136,1137],{},[447,1135,1080],{}," выполнено → возврат ",[447,1138,685],{},[414,1140,1141,1142],{},"Разворачивание стека (возвраты)\n",[1068,1143,1144,1162,1172],{},[414,1145,1146,1148,1149,1151,1152,1154,1155,1158,1159],{},[447,1147,1120],{}," возвращает ",[447,1150,685],{}," → ",[447,1153,1103],{}," вычисляет ",[447,1156,1157],{},"2 * 1 = 2"," → возвращает ",[447,1160,1161],{},"2",[414,1163,1164,1154,1166,1158,1169],{},[447,1165,1084],{},[447,1167,1168],{},"3 * 2 = 6",[447,1170,1171],{},"6",[414,1173,1174,1154,1176,1158,1179],{},[447,1175,1053],{},[447,1177,1178],{},"4 * 6 = 24",[447,1180,1181],{},"24",[1056,1183,1185],{"id":1184},"графическая-визуализация-стека-вертикально-сверху-последний-вызов","Графическая визуализация стека (вертикально, сверху — последний вызов)",[452,1187,1191],{"className":1188,"code":1189,"language":1190,"meta":457,"style":457},"language-markdown shiki shiki-themes github-light","[ factorial(1) ]  ← Базовый случай (возврат 1)\n[ factorial(2) ]  ← Вычисляет 2 * 1 = 2\n[ factorial(3) ]  ← Вычисляет 3 * 2 = 6\n[ factorial(4) ]  ← Вычисляет 4 * 6 = 24\n","markdown",[447,1192,1193,1198,1203,1208],{"__ignoreMap":457},[461,1194,1195],{"class":463,"line":464},[461,1196,1197],{},"[ factorial(1) ]  ← Базовый случай (возврат 1)\n",[461,1199,1200],{"class":463,"line":479},[461,1201,1202],{},"[ factorial(2) ]  ← Вычисляет 2 * 1 = 2\n",[461,1204,1205],{"class":463,"line":491},[461,1206,1207],{},"[ factorial(3) ]  ← Вычисляет 3 * 2 = 6\n",[461,1209,1210],{"class":463,"line":509},[461,1211,1212],{},"[ factorial(4) ]  ← Вычисляет 4 * 6 = 24\n",[1056,1214,1216],{"id":1215},"текстовая-трассировка-по-шагам","Текстовая трассировка (по шагам)",[411,1218,1219,1222,1225,1228,1231,1234,1237],{},[414,1220,1221],{},"factorial(4) → вызывает factorial(3)",[414,1223,1224],{},"factorial(3) → вызывает factorial(2)",[414,1226,1227],{},"factorial(2) → вызывает factorial(1)",[414,1229,1230],{},"factorial(1) → возвращает 1",[414,1232,1233],{},"factorial(2) → возвращает 2 * 1 = 2",[414,1235,1236],{},"factorial(3) → возвращает 3 * 2 = 6",[414,1238,1239],{},"factorial(4) → возвращает 4 * 6 = 24",[1056,1241,1243],{"id":1242},"схема-в-виде-дерева-вызовов","Схема в виде дерева вызовов",[452,1245,1247],{"className":1188,"code":1246,"language":1190,"meta":457,"style":457},"factorial(4)\n├── factorial(3)\n│   ├── factorial(2)\n│   │   └── factorial(1) → 1\n│   └── 2 * 1 = 2\n└── 3 * 2 = 6\n└── 4 * 6 = 24\n",[447,1248,1249,1254,1259,1264,1269,1274,1279],{"__ignoreMap":457},[461,1250,1251],{"class":463,"line":464},[461,1252,1253],{},"factorial(4)\n",[461,1255,1256],{"class":463,"line":479},[461,1257,1258],{},"├── factorial(3)\n",[461,1260,1261],{"class":463,"line":491},[461,1262,1263],{},"│   ├── factorial(2)\n",[461,1265,1266],{"class":463,"line":509},[461,1267,1268],{},"│   │   └── factorial(1) → 1\n",[461,1270,1271],{"class":463,"line":520},[461,1272,1273],{},"│   └── 2 * 1 = 2\n",[461,1275,1276],{"class":463,"line":535},[461,1277,1278],{},"└── 3 * 2 = 6\n",[461,1280,1281],{"class":463,"line":544},[461,1282,1283],{},"└── 4 * 6 = 24\n",[1056,1285,1287],{"id":1286},"ключевые-моменты","Ключевые моменты",[1068,1289,1290,1293,1296],{},[414,1291,1292],{},"Стек растёт при рекурсивных вызовах (каждый новый фрейм добавляется сверху).",[414,1294,1295],{},"Стек сокращается при возвратах (фреймы удаляются по порядку LIFO — «последний вошёл, первый вышел»).",[414,1297,1298],{},"Базовый случай (n == 1) останавливает рекурсию и запускает разворачивание стека.",[407,1300,1301,1302,1305,1306,1308],{},"Стек вызовов наглядно показывает, как рекурсия «погружается» в вызовы, а затем «поднимается» с результатами.\nСтек играет важнейшую роль в рекурсии. Здесь важно, что каждый вызов функции создаёт собственную копию переменной ",[447,1303,1304],{},"n",".\nОбратиться к переменной ",[447,1307,1304],{},", принадлежащей другой функции(или её вызову) – невозможно!\nСтек в данном случае особенно удобен, потому что вам не нужно отслеживать значения переменной каждый раз самостоятельно – стек делает это за вас!",[407,1310,1311],{},"Стек удобен, но при его использовании есть своя цена: сохранение всей промежуточной информации может привести к значительным затратам памяти.\nКаждый вызов функции занимает немного памяти, но если стек станет слишком \"высоким\", это будет означать, что ваш компьютер сохраняет информацию по очень многим вызовам!\nНа такой стадии есть два варианта:",[411,1313,1314,1317],{},[414,1315,1316],{},"Переписать код с использованием цикла;",[414,1318,1319,1320,1323],{},"Иногда можно воспользоваться так называемой ",[578,1321,1322],{},"\"хвостовой рекурсией\"",". Это непростая тема, которая вдобавок поддерживается далеко не во всех языках программирования.",[402,1325],{":isList":1326,"title":1327},"[\"Когда функция вызывает саму себя – это рекурсия;\",\"В каждой рекурсивной функции должно быть два случая: базовый и рекурсивный;\",\"Стек поддерживает две операции: занесение и извлечение элементов;\",\"Все вызовы функций сохраняются в стеке вызовов;\",\"Если стек вызовов станет очень большим, он займет слишком много памяти.\"]","ШПАРГАЛКА",[801,1329],{"id":457},[1331,1332],"card-collapsible-num-answers",{":isAnswers":1333,":isList":1334,":startOl":685,"isText":1335,"title":1336},"[\"Сначала вызывается функция greetings для переменной name = \\\"Иван\\\"; Затем функция greetings вызывает функцию greet для переменной name = \\\"Иван\\\"; На этой стадии функция greetings находится в незавершённом, приостановленном состоянии; Текущим вызовом является вызов функции greet; После завершения функции greet, функция greetings продолжит свою работу.\",\"Стек будет расти бесконечно, но каждой программе выделяется ограниченный объём памяти в стеке. Когда всё пространство памяти будет исчерпано, программа завершиться с ошибкой переполнения стека.\"]","[\"Предположим есть стек вызовов следующего вида: greet(name: \\\"Иван\\\") -> greetings(name: \\\"Иван\\\"). Что можно сказать о текущем состоянии программы на основании этого стека вызовов?\",\"Предположим, вы случайно написали рекурсивную функцию, которая бесконечно вызывает саму себя. Как вы уже видели, компьютер выделяет память в стеке при каждом вызове функции. А что произойдёт со стеком при бесконечном выполнении рекурсии?\"]","Попробуйте ответить на следующие вопросы","УПРАЖНЕНИЯ",[407,1338,1339,1340,1344,1345,1348],{},"Попробуйте сами скопировать и запустить код в окне ниже с интерпретатором Python и повторите примеры из статьи чтобы самим увидеть и понять как всё это работает.\nДля этого в ячейке с кодом нажмите клавиши на клавиатуре ",[1341,1342,1343],"strong",{},"Shift+Enter"," или запустите код через ",[1341,1346,1347],{},"кнопку Run"," по значку ▶.",[1350,1351],"jypiter",{},[1353,1354,1355],"style",{},"html pre.shiki code .sD7c4, html code.shiki .sD7c4{--shiki-default:#D73A49}html pre.shiki code .s7eDp, html code.shiki .s7eDp{--shiki-default:#6F42C1}html pre.shiki code .sgsFI, html code.shiki .sgsFI{--shiki-default:#24292E}html pre.shiki code .sYu0t, html code.shiki .sYu0t{--shiki-default:#005CC5}html pre.shiki code .sYBdl, html code.shiki .sYBdl{--shiki-default:#032F62}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}",{"title":457,"searchDepth":479,"depth":520,"links":1357},[1358],{"id":399,"depth":479,"text":400,"children":1359},[1360,1361],{"id":647,"depth":491,"text":648},{"id":780,"depth":491,"text":781,"children":1362},[1363,1364,1371],{"id":803,"depth":509,"text":804},{"id":975,"depth":509,"text":976,"children":1365},[1366,1367,1368,1369,1370],{"id":1058,"depth":520,"text":1059},{"id":1184,"depth":520,"text":1185},{"id":1215,"depth":520,"text":1216},{"id":1242,"depth":520,"text":1243},{"id":1286,"depth":520,"text":1287},{"id":457,"depth":509,"text":457},"2025-11-20","Алгоритм рекурсии и понятие стек вызовов функции","md","images\u002Fblog\u002Fpython\u002Fst27\u002Fimg.png",{},17,27,{"title":266,"description":1373},"8pzYCqUt-KaqUCrOEbKlMUq0q3elyp2Do2Z_aOthAvU",[1382,1384],{"title":262,"path":263,"stem":264,"description":1383,"children":-1},"Алгоритм сортировки выбором массива или списка",{"title":270,"path":271,"stem":272,"description":1385,"children":-1},"Алгоритм быстрой сортировки массива. Стратегия \"Разделяй и властвуй\"",1780737510349]