Связный список

Материал из Неолурк, народный Lurkmore
Перейти к навигации Перейти к поиску

Связный список (англ. linked list) — структура данных, используемая для хранения данных. В обывательском смысле это как массив, только нефиксированного размера, чудеса.

Как устроен, есть ли побочные эффекты?[править]

Связный список является очень простой вещью, по-сути это набор ячеек (если говорить абстрактно), где каждая ячейка имеет ссылку на следующую.

Хороший пример IRL — очереди за колбасой и на почту.

Последняя же ячейка, имеет вместо адреса следующей ячейки значение NULL, что при переборе должно означать, что дальше Бога нет это последний элемент в списке.

Главное отличие списка от массива состоит в том, что он не хранится на стеке, а в куче[1], что даёт меньшую скорость доступа. А также для нового элемента списка может просто банально не найтись свободного места в ОЗУ, что приведёт к аварийной ошибке, если не уследить за этим моментом.

Двусвязный список[править]

Тот же связный список, но кроме ссылки на следующий элемент, хранит ссылку и на предыдущий. Обеспечивает возможность движения по списку в обе стороны, в ущерб размера элементов, так как в 64-битной архитектуре каждый указатель занимает 8 байт, а если принять во внимание, то что элементов в списке могут быть тысячи, а запущенных процессов может быть десятки, то уже может появиться заметное использование оперативной памяти.

Интрузивный связанный список[править]

Это когда ссылки на следующий (предыдущий, или обе) элемент хранятся внутри самих элементов списка, а не хранящих эти элементы узлов. Более низкоуровневый способ организации данных позволяет связывать элементы, созданные кем-то еще и хранимые где угодно.

Список без слова «связный»[править]

Не следует путать связный список и просто список. В некоторых языках List — интерфейс последовательного контейнера, обеспечивающего эффективный доступ по индексам и быструю вставку в конец, таким требованиям удовлетворяет обычный динамический массив.

Операции и взаимодействие[править]

Допустим, у нас есть односвязный список, то какие базовые операции мы может делать:

Вставить в начало[править]

  • Создаем новый элемент и записываем ему .next на адрес текущей головы списка (в случае изначально пустого списка это NULL, все ок)
  • Обновляем ссылку на начало ссылкой на новый элемент

Добавить в конец (add)[править]

  • Берем связный список.
  • Проходим по списку до самого конца (пока ссылка на след. элемент не станет равна NULL).
  • Создаем новый элемент.
  • Меняем ссылку последнего элемента, присваивая ей адрес созданного элемента.

Вставить (insert)[править]

  • Берем связный список и индекс элемента, после которого надо создать новый.
  • Проходим по списку до нужного элемента (пока кол-во пройденных элементов не станет равно указанному индексу).
  • Создаем новый элемент.
  • Запоминаем адрес элемента следующего после того, на который указывает индекс.
  • Меняем ссылку элемента с указанным индексом, присваивая ей адрес созданного элемента.
  • Меняем ссылку нового элемента на адрес, который мы запомнили выше.

Удалить по индексу (pop)[править]

  • Берем связный список и индекс элемента, который нам надо стереть с лица земли.
  • Проходим по списку до нужного элемента (пока кол-во пройденных элементов не станет равно указанному индексу).
  • Когда кол-во пройденных элементов станет равно [индекс-1], то запоминаем адрес элемента, чтобы в дальнейшем его изменить.
  • Получаем адрес элемента идущего после того, что нам нужно уничтожить.
  • Уничтожаем элемент (высвобождаем занятую им память).
  • Меняем ссылку элемента который мы до этого запомнили на адрес следующего элемента.

Удалить элемент из произвольного места (remove)[править]

  • Берем непустой связный список и элемент, предшествующий тому, который хотим стереть с лица земли
  • Заменяем у предшествующего элемента ссылку на .next на .next стираемого элемента
  • Удаляем осиротевший элемент, на которого теперь никто не ссылается

Обход контейнера[править]

  • Берем связный список
  • Заводим переменную — указатель на текущий узел, изначально указывающий на начало
  • Пока текущий указатель не NULL, делаем что-то с содержимым узла, а потом обновляем указатель на .next
  • Из-за особенностей работы процессора с памятью[2], последовательный доступ к элементам не так эффективен, как для массивов, что несколько ограничивает применение.

Доступ по индексу[править]

  • Берем связный список
  • Как и в случае с обходом, переходим к следующему элементу N раз, пока не насчитаем нужный
  • Операция имеет линейную сложность O(N), поэтому так лучше не делать, это НЕ то, для чего нужен этот контейнер.

Объединение двух связанных списков[править]

  • Берем два связанных списка
  • Записываем .next последнего элемента в head второго списка
  • Помечаем второй список как пустой (head = NULL)

Примечания[править]

  1. важно ответить, что массив тоже может хранится в куче, если его выделить динамически
  2. чтение памяти по произвольному адресу — операция довольно медленная, а пользовательские данные обычно упакованы плотно, поэтому при запросе в RAM по заданному адресу процессор читает не только запрошенные данные, а целый блок с запасом («кеш-линия»), и записывает в собственную быстродействующую память. Если следующий запрос будет по близкому адресу — данные возьмутся прямо из кеша. В противном случае процессору придется заново читать память, такая ситуация называется «cache miss»
Movax1010h.png Глубокий смысл скрыт в этих неестественных языках
Языки программированияПромышленные: BATC#CC++JavaJavaScript (AJAX) • PascalPerlPHPPythonRubyABAPАссемблерВасикFortran (Профессор)
Эзотерические: BrainFuckHQ9++ErlangForthHaskellLISP (My other car) • PrologTclΤΕΧOracleMySQLGolangВ++Scala
ПрофессииБыдлокодерПрограммистТестировщикХакерХеллоуворлдщикIT-звёздыПрограммист (существо)Тернарный операторUnreal MCPИсходный код
Методы и стилиReverse EngineeringАнти-паттернВыстрелить себе в ногуГрязный хакКод (индусский) • КостыльМетод научного тыкаПомолясьСвистелки и перделкиОчередьСпортивное программированиеОбфускацияБета-тестАльфа-тестШаблоныRegReplaceФреймворкБыдлокодIndex.phpОхота за жукамиКуМирКлеточный автоматПроцедурное программированиеПоиск файлов в Unix по содержимомуPetoohФункция активации нейронаПерегрузка операторов в PythonЗерокодинг
Средства разработкиSublime TextПодсветка синтаксиса кодаUnstable DiffusionAPIPythonTutorCodeWarsDataCampUnity3DКнижный PythonMallocСвязный списокSOLIDООПУказательNULLWeLang++XenonRecompFuse.jsОптимизацияТестирование
ЛюдиИлья КанторЮрий КлючевскийЭдуард ЛаасЭдвард СноуденСеймур Пейперт
Прочее++i + ++iДедлайн%s640 килобайтCMSDummy modeЕГГОГFoobarGod is real, unless explicitly declared as integerGOTOIfconfigKISSRegExpSICPsql.ruXyzzyДискетаИнжалид дежицеКОИ-8ЛогМанРекурсияСУБДТест ТьюрингаУмение разбираться в чужом кодеФаза ЛуныФатальный недостатокПроблема 2000ТаймстампКэшЗапись в файл без кэша (Perl)Танцы с бубномКодачХукCurl cffi
App.png Весьма полезная вещь, позволяет машинам работать с помощью коммандычей
МетаПрограммаDRM (SecuROMStarForceАналоговая дыра) • БагБот (Автоответчик) • Варез (Repack) • ГлюкГуйДонатКопирайт (By design) • ЛогНюкРут (Не работай под рутом) • Спортивное программированиеМегапиксельКомпьютерВерсия 2.0КодОбфускацияСкриншотДатамайнПлагинТекстовый файлБольшие данныеАльфа и бета-тестыТаймстампКэшШаблоныHello WorldНейросетиФайлИнсталляцияВидеоМощный сбой Microsoft 19 июля 2024 годаCrowdStrikeПроект GNUUserscriptDxvkVkd3dБратан хорош давай давай впередКонечный автоматLumenЗаступник (приложение)NeeUnreal MCPОптимизацияДрайверТестированиеТройная буферизацияQBitTorrentСинтезаторОбрыв загрузки файла на 99%Polycount.comГрок написал программу о себе
ФичиБагрепорт12309BSODCookiesEmbrace, extend and extinguishFL StudioSheep.exeWinlogon.exeБубенЗащита от дуракаКостыльМашинный переводПасхальные яйцаСвистелки и перделкиСм. рис. 1Съешь ещё этих мягких французских булокTermuxGNU MetroИндусский кодНескучные обои • Сжатие (За сжатие ДжипегаШакалШкала) • Работает — не трогайРандомайзерPDF (Распознавание PDF) • Дело Google в ФАСЧат-ботXMLМакросКритическая ошибкаФреймворкСинонимайзерSourceТрёхмерное отслеживаниеТрассировка фотоновHZB OcclusionДаунгрейд RTX 4070TressFXАвтопереводчикVSCodiumThorium BrowserShovelwareФайл подкачки
ВредоносноеБотнетБрутфорсВинлокЗвонилкаКитайские пингвиныПиксель смертиТроянЧервь МоррисаBonziBuddyMediaGetBrowser hijackingTinderМиссис МажорУтечка буфера обменаWin 10 TweakerОпараш Mozilla FirefoxЯндекс.МузыкаКрэкерБезопасность через умолчаниеGrifter.aviTrojan.Winlock.DeathМиссис МажорСредаDirectStorageDriverpackГенератор случайных чиселDisable Core 0РомхакингDDrawCompatWingetCreateWinGetCoowonЯндекс МессенджерVCPkgSELinuxXfireYouTube Auto-ResumeTape OperatorBotFatherMTProtoSignalDoubleClickFixGiteeБотофермаMalwareCeno Browser
КомпанииApple / Apple (AppleScript) • GoogleMicrosoftSAPЯндексExiled Exchange 2BraveAdNauseamСкурвление FirefoxCafe BazaarAMD FEMFXPPSSPPАвтохукQuick machine recoveryMAXBypassNROWizTreeJTubeGallium NineFalconRu-WireGuardМобильное приложениеWebRenderСмс-бомберInstaller-SHProton GEProcess LassoParkControlDolby AccessDevToolsDxWrapperБойкот мессенджера MaxFirejail
Движения8-bitOpen source (КрасноглазикиЛинуксоиды) • Вирусная сценаДаунгрейдДемосценаМоддингMMDDirectDrawЛагиБлокировка Дискорда в РоссииOpera GXНесоответствие MIME-типаRenoisePygameLs (UNIX)МетаданныеПатчNginxПиксельЭмуляторSearxТамТамMallocСвязный списокSOLIDGreasemonkeyПлатные сообщенияFlatpakNouveauFuse.jsFellouИстория браузера
Офис3DS MAXGIMPGNU EmacsMovie MakerMS Paint • OpenOffice • PowerPointviMicrosoft WordExcelБлокнотФотошопАнтивирус КасперскогоAvast!TikZShareXAlternativeToСкрепышMicrosoft OfficeТекстовый редакторWeChatZoomДиспетчер задачMicrosoft CortanaWinampBallonTranslatorKerish DoctorОбщая ошибкаFirefox: Как один баг сломал весь YouTubeМеждулициеMeld StudioLadybirdCheat EngineTotal Commander
ОСAndroidBSDDOSMenuetOSReactOSWindows (Phone 7Phone 878Vista) / МаздайЛинуксРусская ОСФантом ОСIndex.phpCompassУход мэйнтейнера NouveauБойкот лаунчеровAria2cNoiceMinecraft-Installer.exeDirectX
БраузерыInternet ExplorerОпера / Opera • Тормозилла (ОгнелисLolifoxMozilla FirefoxFirefoxFirefox Klar) • Хром (шпионаж) • SafariЯндекс.БраузерУведомления в браузереVivaldiTor-браузерЗосимаФронтенд
ИнтернетAdobe Systems (Flash) • I2PLow Orbit Ion CannonTorTunatic • Чат−клиенты (MirandaQIPSkypeЖабберDiscordVIPole) • HTTPSПрокси-сервер (Proxifier) • Торрент (Magnet-ссылкаΜTorrent) • JavaScriptCSSHTMLБаннермейкерИзменение TTL сетевых пакетовКапчаICQFiddlerViberZonaSteamSillyTavernWickr Me
РазработкаBrainFuckCC++C#JavaHaskellАссемблерChaos ConstructionsBATMySQLGitHubAutoHotKey (AutoHotInterception) • Sublime TextAPK (APKPureзапрет) • BASICPerlPythonPHPФоркUnity3DSAISIPСАПРФлагUTAUФласк макросАуработRaidCallAdobe MingОфициальный™ список кошерных программDevOpsНиколай ДуровЗаброшенное ПО
ЛюдиВеб-мастерLovinGODБалмерГейтсГенерал ФейлорДжобсМитникПоттерингде РаадтСпольскиСтоллманТорвальдсШахиджанянAche666Марк ЦукербергЕвгений ПоповДенис КумпонМассовая компьютерная безграмотность
КостылиCygwin • PunkBusterT9WineWishmasterАнтивирусыХакинтошСборки WindowsDenuvoЧистая установкаКалькулятор Consul WarMicrosoft StoreUBlock OriginLightshotAdBlockSearchApp.exeCPU-ZГуглPhotoshopКаптча с пчёламиВзлом Windows через MetasploitЩЩ Мессенджер
Команды^H^WAlt+F4Ctrl+Alt+Delman/me/quitrm -rf