Справочник от Автор24
Поделись лекцией за скидку на Автор24
Забирай в ТГ промокод на 1000 рублей
А еще там много крутого контента!
Подписаться

Алгоритмы на Python 3; массивы (тип list)

  • 👀 433 просмотра
  • 📌 374 загрузки
Выбери формат для чтения
Загружаем конспект в формате doc
Это займет всего пару минут! А пока ты можешь прочитать работу в формате Word 👇
Конспект лекции по дисциплине «Алгоритмы на Python 3; массивы (тип list)» doc
Алгоритмы на Python 3. Лекция №5 Массивы (тип list) Массив - это такой способ доступа к данным, когда у вас есть одно имя и сразу много данных, то есть у вас есть какое-то имя А  1/ 2/ 3/ 4/ 5 -объекты данные обыкновенно хранящиеся в массиве имеют одинаковый тип. То есть, у вас есть объекты, заключенные в массив, вот эти объекты каждый из них является индивидуальным объектом. Это конкретные объекты, хранящиеся в массиве, как в некотором контейнере в которой как элементы хранятся целые числа. Весь этот массив имеет тип list, а вот хранящиеся в нем элементы не имеют собственных имен, но доступиться к ним можно. Каждый из них имеет тип int. Как создать конкретно такой вот массив: А = [1,2,3,4,5] Что можно делать с массивом? Поскольку он является вполне таким «контейнером» первое и самое интересное что можно с ним сделать: это перебрать контейнер по порядку для этого не надо практически ничего, из-за того что в Python очень удобны для этого цикл (for) for x in A: print (x) Можно распечатать и весь контейнер целиком print А, он так и распечатает в квадратных скобках через запятую все элементы. Если же хочется последовательно доступаться по элементно, то надо понимать следующее: что в этом случае возникает на каждой операции альтернативное имя Х, которое ссылается на те же самые элементы. То есть, альтернативное имя Х добавочное, но это уже имя конкретного объекта. Если вместо Х или вдобавок к нему напечатать еще и type x, то увидим что там класс int.(Каждое из них целое число) В то же время, если спросить какой type А, то он вернет List- это список. Поговорим о модели данных в языке python Как хранятся собственно данные? Оказывается, в python есть изменяемые типы и неизменяемые. Вот есть такой объект как единичка типа int, а теперь представьте себе что я говорю: «единичка измени свое значение на двойку»,но всё же не могу так сказать т.к она константа. Так вот для целых,дробных чисел и вообще для других чисел принято следующее правило: они являются константами, то есть константный тип неизменяемый. Инструкция х+=1 расшифровывается следующим образом, она расшифровывается, то есть эквивалентно следующий х=х+1 Как вычисляется это? Это вычисляется так,в начале посчитать результат: А  1/ 2/ 3/ 4/ 5 Х «+» 2 1 У меня есть объект единичка, есть еще один объект единичка временный, который сожрет сборщик мусора, как только вы числится вот это выражение. У меня эти два объекта порождают целое число, они порождают при помощи операции «+» объект 2 и после этого происходит x равно, то есть присваивания в python- это связывание имени и объекта и у меня имя x отвязываетcя от старого объекта и связывается с новым объектом. После чего, временный объект необходимый для вычисления удаляется и остается что x ссылается на объект 2 после этого благополучно происходит print x распечатывается (x) и что (x) на следующей итерации имя (х) не исчезает, но начинает ссылаться на другой объект временный. На него ссылок больше нет, приходит так называемый сборщик мусора и съедает этот временный объект. Идея в том, что есть имена, а есть объекты А как же нам изменить сам массив, вот сами элементы, хранящиеся в нем? хотелось бы их как-то поменять ну Давайте, например, поставим задачу: возвести каждый элемент в квадрат. Так чтобы к самой ссылке, вот оказывается очень просто. Для этого мне требуется доступаться к элементу по индексу. У массива у каждого элемента предусмотрен индекс, причем эти индексы идут от нуля. То есть у первого элемента индекс 1. Вот у массива нулевой элемент- это первый. Так вот я сейчас при помощи k пробегусь по диапазону от нуля до четырех. for k in range (5) range функция мне сгенерирует арифметическую прогрессию старт-стоп степ. Когда пишу range 5 это то же самое как,если написать range (0,5,1) :начать с нуля, стоп 5 не достигаемый и шаг единичка. Но можно просто написать range 5 и понятно, что это значит от 0 до 4. Итак, перебираю индексы по порядку от нуля до четырех. Вот теперь у меня нет никакого дополнительного имени x которая является, на самом деле есть у меня этот k, но это всего лишь у меня номерок, то есть это индексная переменная, и она постепенно там тикает 0,1,2 И я этой индексной переменной пользуюсь для того, чтобы сам список менять. Возникает вопрос: «А как бы мне создать массив по длиннее?» Если я хочу создать массив размером 100,1 000,1 000 000 целых чисел. Как его создать? Как мне его заполнить? Для этого можно воспользоваться следующим синт. Я могу взять и сказать: «нулевое значение хочу размножить там в столько раз в сколько мне надо.» Дальше возникает следующий вопрос: создал массив размером 1000, потому что мне поставили задачу. Сейчас я хочу ввести переменную, которая будет хранить уровень реальной заполненности в этом массиве. То есть сейчас там хранится 0 элементов. Я введу это словом top верхушечку. Вот верхушка сейчас на нуле Top указывает на индекс 0. она говорит там 0 элементов. Заодно top указывает, что фактически первый элемент куда нужно копировать. Что делаю я: считываю число x Дальше пока у меня этот x не равен нулю. Что я буду делать? То есть я получил х значит, мне впихнуть его нужно в массив куда? Естественно по указателю топ, то есть я ровненько в топовое место кладу то число, которое мне пришло. Я говорю А от top, где топ это уровень заполненности, равно x Но я же туда положил реальное число, допустим там 1,2,3,4,5 вводятся, а потом 0 1 2 3 4 5 0 на входе Каждая в отдельной строке. Но top должен сказать, теперь там один элемент хранится, то есть топ я должен увеличить. top+=1 Ну и считываю следующий х туда Х=int (input (1) Таким образом, я организовал считывание и теперь у меня два эффекта: У меня в самом массиве разложены все числа последовательно, а заодно top = 5, то есть количеству реально хранимых чисел. И я могу дальше теперь уже не циклом while, который имеет непредсказуемое количество операций, а теперь вывести числа задом наперёд. Я могу как for обычным. Я запускаю цикл for k который пробегает индексы в диапазоне for k in rang начиная с top – 1, потому что у меня если там пять элементов, то максимальный заполненный индекс – 4. Я ж с 0 начал, с 0 по 4 у меня они хранятся. Поэтому for k in rang (4;-1;-1) начиная от 4- это старт, 0 должен быть достигнут поэтому 0 стопом быть не может -1-стоп, и шаг -1. Теперь я распечатываю: print ( A[k] ) То есть, при помощи дополнительной переменной я могу контролировать реальный уровень заполненности в массиве. Простые алгоритмы 1. Копирование массива Допустим в моей задачке будет заранее известен размер массива. В первой строке вводится размер массива то, сколько элементов будет введено, а потом уже их надо запоминать и так далее. Итак, вот мне уже известен размер массива, я создаю два массива: Допустим А мне ввели из клавиатуры, ну каким образом мне считать массив А? Итак, что я сейчас делаю?- я создал два, я заполню А разумными числами. Как мне скопировать из А в В? я Давайте сейчас напишу здесь С=А Имена в питоне создаются методом присваивания в них. Что у меня сейчас происходит: у меня (А) создался, как контейнер, содержащий нули в объеме 1000 штук (В) создался как контейнер, содержащий нули в объеме 1000 штук. А как создался (С)? Никакой операции создания нового объекта не происходит. Это значит, что (С) всего лишь является ссылкой на тот же самый (А) А если я хочу создать новый список, и запустить этот процесс автоматический, т.е. создать копию? (С) в данном случае это второе имя того же самого объекта, а учитывая что списки являются изменяемыми, то если я изменю теперь А нулевому положу какое-нибудь значение 777, то я легко обнаружу, что С нулевой у меня кто?- 777 Не единичка, которая туда вначале была с клавиатуры, а вот то есть имя у меня может существовать сколько угодно имен, одного и того же объекта. Если объект является изменяемым, то у меня могут происходить внезапное изменение самого объекта. А как же мне все-таки вернуться к тому, чтобы сделать полный дубликат того списка, который есть и покороче. Чтоб не писать, тоже самое что для (В) сделано. Есть такая возможность: сотвори ко мне список на основе списка (А) С = list (А) Я вызываю явным образом конструктор списка, и он создаст новый список (копию списка) Значит у нас с вами линейный поиск массива. Я создам функцию, которая будет называться array_search Я ей буду передавать массив, я буду передавать размер массива, и я буду передавать то есть размер, в котором я буду собственно искать диапазон поиска, и я буду передавать собственно Х-искомое число. Надо сказать, что в питоне, начиная с некоторой версии я могу упоминать типы, то есть я могу тут писать, какой тип там ожидается. Могу писать,чтобы подразумевалось, что там у меня будет: А-list N-int (это целое число) Х- int (это целое число Это заголовок моей функции. Документ строка, что делает эта функция?- ```Осуществляет поиск числа Х в массиве А в диапазоне от 0 до N-1 индекса включительно, то есть по N не включительно. Дальше возникает вопрос о том, что она возвращает, если она нашла элемент, что она по-хорошему должна вернуть его местоположение(этаж, индекс) И так, возвращает индекс элемента Х в массиве А. А если там нет такого элемента, что ей возвращать? Ноль- это законный этаж, он первым элементом там находится. -1 вот хорошая мысль возвращать -1. Или -1, если такого нет. Вот я сейчас сформулировал некий договор и пока что оставлю pass Это функция пустышка, это махинатор, который как раз ничего не делает пока что. Я начну им пользоваться в начале, то есть я сейчас напишу маленький тест, который будет эту функцию тестировать, я увижу сразу что тест мой заваливается (не то что я ожидаю на самом деле), но потом я уже реализую, и когда реализую правильно, то мои тесты начнут проходить. Напишу результаты тестирования, но каким же образом? Оформим это: Она ничего не возвращает, она просто напечатает результат. Вот что она будет делать: она создает список(я прям сразу создам список 1 2 3 4 5) Я получаю значение, которое вернет array research Давайте назовем его М. Что я буду искать?-я буду искать в списке Что делаю сейчас: Array research A1 я говорю что там пять элементов, и я буду искать число 8. Давайте вначале проверим действительно негативный случай. Что я теперь говорю: если у меня m равно минус 1, то в этом случае я скажу, что у меня тест один –ok А иначе что я скажу: тест 1 фэйл. Вот я и написал метро тестирование Теперь дальше я второй тест сделаю с А2, поскольку оно будет очень похоже я сделаю copy & paste. Значит второй тест я сделаю массив -1 -2 -3 -4 -5, 5 элементов по-прежнему я буду искать -3. Соответственно у -3 какой должен быть, что был ok?- индекс должен быть 2. Давайте допишем документ строку хотя бы. Что мы напишем: Вот три теста у меня будет ну и соответственно я среди пяти элементов, еще элемент 10 и индекс это 0. Ниже по тексту напишу, что тест aray_search. Запускаем и обнаруживаем, что у нас программа заваливается с ошибкой выполнения. Дело в том, что функция возвращает мне в этом случае специфическую переменную нан нан type, a это специфическое ничего. Значит я сейчас все-таки напишу заместо pass - return-1. Пусть она всегда возвращает и окажется что, возможно некоторые тесты случайно прошли. Но реально функция будет работать, когда пройдут все. Я сделаю следующим образом: я буду перебирать индексы в диапазоне от 0 до N не включительно, если у меня А[k] окажется равным Х, в этом случае я сразу могу выходить, возвращая индекс k. Алгоритм обращения массива Я сейчас напишу примерно также, только быстренько с меньшим количеством комментариев. У нас будет функция, которая будет инвертировать сам массив Обратите внимание, что эта функция должна будет менять массив в самом себе. Значит у меня А предполагает список, N предполагает целое число, значит обращение массива то есть у меня задом наперед. Значит его поворот в рамках индексов от 0 до N-1 Сейчас я буду еще проще чем в прошлый раз тестировать, я не буду создавать отдельный список, я его буду совать ей прям вот в аргумент функции. В общем я туда скопирую несколько этих и дальше я сейчас буду запускать этот тест файл сюда. Значит что у меня получается, если у меня А1 равен 5 4 3 2 1, то ok. Итак, я предполагаю, что после вызова функции invert_array(А, 5) указываю 5 как количество элементов в нем хранящихся. Второй пример: заполню его нулями и сделаю четное количество элементов 10. Мы написали тестирование, запускаем, смотрим результат Собственно, тест 1, тест 2 ничего не разворачивает. Так, а теперь давайте с вами напишем обращение массива. Очевидно, если у меня было два массива, то я могу вместо копирования из A[K] в B[K], я могу копировать в B[K] из А[N-K-1] ,откуда возникает N1,то есть я буду копировать элементы как бы накрест. вот так произойдет зеркальное копирование. Вот таким вот образом: А теперь я пишу туда то, что у меня заготовлено для копирования массива, только в обратном порядке Запускаем: Произошло, что у меня элементы А перетирают элементы А Мне надо менять элементы местами. Для этого я воспользуюсь алгоритмом обмена двух переменных значениями. У нас вот эти 2 элемента надо поменять местами. Как я это сделаю, я говорю Запускаем тест файл в чем проблема ?- в том, что мы в начале меняем 0 с четвертым потом первый. Мне нужно было на серединке остановиться. Для этого мне нужно что N пополам на цело с отбрасыванием остатка чтобы даже двойку с двойкой не менять местами поэтому N пополам с отбрасыванием остатка и не включать в диапазон, но это будет выглядеть очень просто. Но надо сказать, что обмен двух переменных местами в таком виде когда это x y он выглядит нормально. Так, добавление элемента в конец и начало массива мы в принципе сделали. Теперь таких алгоритмов не совсем учебных циклический сдвиг. Решето Эратосфена Циклический сдвиг- эта операция преобразования элементов массива, причем она бывает разной. Циклический сдвиг бывает влево, а бывает вправо. Что делает сдвиг влево: элементы я сейчас их совпадающими собственными индексами заложу 0 1 2 3 4 я беру и сдвигаю их, а нулевой элемент я отправляю к 4 Вот этот ноль мне нужно вначале куда-нибудь выложить во временную переменную, которую я назову tmp, затем поверх него скопирую, а затем я осуществляю следующую операцию. Эти ящики как бы, подтягивая на себя, и шагаю индексом. Копирование происходит из следующего элемента в предыдущий, но само движение грузчика происходит слева направо. Циклический сдвиг вправо должен логично действовать ровно наоборот. копирование будет из предыдущего в следующий, а грузчик двигается справа-налево. То есть циклический сдвиг влево осуществляется при пробегании индексов в прямом порядке, а циклический сдвиг вправо в обратном порядке. Циклический сдвиг влево Массив А уже есть в нем N элементов я перебираю k в диапазоне N минус 1, то есть у меня N минус 1 не достигается, у меня N минус 2 достигается то есть k переберет 0 1 2 3 индексы для данного массива. 4 он не будет, потому что я буду одновременно работать здесь сразу с двумя, а именно ему говорить что A[k] присваиваю значения k + 1 В конце что я делаю в самый последний элемент с индексом N минус 1 я кладу tmp. A[N-1] = tmp Циклический сдвиг вправо В этом случае я выкладываю в переменную tmp последний элемент, затем я пробегаю индексами в диапазоне от N минус 2 до 0 включительно. Значит -1 является с топом и минус один шаг. Я делаю A[k+1 кладу значения A[k] ровно наоборот. Потом положить в А нулевой старое значение n минус 1 которое сохранено во временной переменной. В решете эратосфена не требуется использовать операцию умножения. я возможно успею на В решете эратосфена мы будем хранить по сути ложь и истину. Дальше что я делаю: обратите внимание что в этом случае я присваиваю в элементы, и поэтому я каскадным равенством туда имею полное право запихать 0 falls. Теперь я беру и для каждого значения Значит,если у меня A[k] является правдой,то значит это число простое. Я буду все кратные ему, соответственно пробегу вперед с шагом равным собственно его индексу, и отмечаю у них у всех что они уже не являются простыми. If A[k]: Итак, если он простое число, то я запускаю цикл,в котором я теперь уже вторым индексом М начну бежать в диапазоне, начиная от 2*k А(м)-у нас число составное К вот этому моменту print а будет представлять из себя массив, логических значений где индексом будут соответствовать правда или ложь. Условия и правый операнд значения выражения будет равна либо тому что слева, либо тому что справа в зависимости от того истинно вот это или ложь.
«Алгоритмы на Python 3; массивы (тип list)» 👇
Готовые курсовые работы и рефераты
Купить от 250 ₽
Не знаешь, как приступить к заданию?
За 5 минут найдем эксперта и проконсультируем по заданию.

Тебе могут подойти лекции

Смотреть все 588 лекций
Нужна помощь
с заданием?

Поможем справиться с любыми заданиями. Квалифицированные и проверенные эксперты

Получить помощь
Забирай в ТГ промокод
на 1000 ₽

А еще в нашем канале много крутого контента

Перейти в Telegram bot