Перейти к содержимому

Как поменять местами узлы в односвязном списке

  • автор:

Поменять местами ноды в односвязном списке

Я застрял на применении односвязного списка. Проблема в том, что я не могу понять почему не меняются местами последний и предпоследние элементы списка.

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

  1. меньше двух узлов: вернуть список как есть
  2. ровно два узла: поменять узлы местами
  3. больше двух: сделать, чтобы последний узел указывал бы на второй узел, а предпоследний — на первый.

где next_to_last() ищет предпоследний узел:

Это достаточно прямолинейное решение в лоб, возможно есть более элегантный подход.

Поменять местами два элемента односвязного списка

Поменять два элемента односвязного списка
Я где-то ошибся, и функция swap(smen2 -> pNext, smen1 -> pNext); в строке 123 ничего не меняет.

Поменять местами два элемента двусвязного списка
Доброго времени суток. Помогите пожалуйста с задачей. Необходимо реализовать функцию, которая.

Поменять местами два элемента двусвязного списка и удалить из него указанный элемент
Дан двусвязный список. Требуется напечатать исходный список. Поменять местами два элемента списка.

Поменять местами последний и предпоследний элементы односвязного списка
Ребят, помогите, пожалуйста, реализовать ф-ию замены последнего и предпоследнего элементов местами.

Лучший ответСообщение было отмечено Dennis Ritchie как решение

Решение

Сообщение от Nosey

Сообщение от Dennis Ritchie

Когда речь идет о списках, хранящих какие-то "полезные данные", задание "поменять местами два элемента" — неоднозначно.

* Во-первых, в списке "поменять местами два элемента" можно путем перецепления ссылок на узлы списка. "Полезные данные" останутся на прежних местах в памяти, но порядок физических узлов в списке изменится.

* Во-вторых, в списке "поменять местами два элемента" можно просто путем обмена "полезных данных", хранящихся в узлах, оставив ссылки нетронутыми. В таком случае наоборот, "полезные данные" обменяются в памяти, но порядок физических узлов в списке останется прежним.

С точки зрения распечатки содержимого списка, результат будет одним и тем же в обоих случаях. Однако побочные эффекты этих вариантов различаются. Например, если у меня есть два посторонних внешних указателя на обмениваемые узлы списка, то в первом способе "полезные данные", видимые через эти указатели, останутся прежними. А во втором способе они тоже обменяются.

О каком именно обмене идет речь?

Второй способ, понятное дело, применим к любому контейнеру. Поэтому когда в задаче явно говорят о списке, то это зачастую является "намеком" именно на первый способ.

Как поменять местами позиции двух узлов в односвязном списке, изменяя только указатели?

Я пытаюсь поменять местами два узла односвязного списка с заданными нулями индексами. В моем коде я обрабатываю много случаев, но этот подход действителен только когда j-i<=2 . Если между i и j есть разница в 3 или более, я не смогу ее обработать.
Пожалуйста, помогите мне исправить мой подход.

3 ответа

Основы указателя-жокея для замены узлов в связанном списке просты:

  • Найдите в списке указатели, которые указывают на узлы, которые вы хотите поменять местами. Одним из этих указателей может быть указатель head , но по крайней мере один из них будет указателем next в списке. Помните, что это указатели, которые указывают на узлы, которые вы меняете.
  • Поменяйте местами эти указатели
  • Поменяйте местами указатели next этих узлов, чтобы восстановить оставшийся порядок в списке.
  • Вот и все.

Для этого проще всего использовать указатели на указатели . Это позволяет избежать необходимости полностью обходить указатели prev , что делает алгоритм ужасно более сложным, чем он должен быть.

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

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

Это не сделало бы справедливости без действующего примера. Далее будет построен упорядоченный список из десяти элементов, пронумерованных 1..10. Затем он использует описанную выше процедуру подстановки с нулевым индексом, чтобы поменять местами различные элементы, в частности, что-то, что меняет головной узел, хвостовой узел и некоторые внутренние узлы, а затем отменяет все это, изменяя свопы, чтобы прийти к списку, который мы начали с.

Большинство крайних случаев, которые вы пытаетесь избежать, просто исчезают, если вы помните, что пытаетесь сделать: меняйте указатели, а не узлы. Хитрость заключается в том, чтобы найти указатели (не их значения; фактические указатели), которые указывают на узлы, которые вы хотите поменять, и поменять значения этих указателей.

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

Давай я тебе помогу : —

  • Задача 1 — Нахождение i-го индексного узла и j-го индексного узла путем обхода связанного списка (нет необходимости находить расстояние между ними)
  • Задача 2 — Замена обоих узлов

Требования — Чтобы поменять узел, получить доступ к его предыдущему узлу (что кажется вам известным, так как вы пробовали это в своем коде)

Некоторые угловые случаи —

  • Если я == j или i> j (управляется вашим кодом)
  • Если у i-го узла нет предыдущего узла (т. Е. Он возглавляет связанный список)

Теперь попробуйте проанализировать ваш код.

Для справки смотрите код ниже

Надеюсь, это поможет.

Продолжайте спрашивать, продолжайте расти 🙂

Вы делаете свою логику свопинга более сложной, чем она должна быть. Попробуйте что-то вроде этого:

Поменять местами два узла в односвязном списке

Как переключить два узла в односвязном списке на паскале?

(Здесь pNode — указатель на узел в списке.)

Узлы определяются следующим образом:

Этот код не работает. Он либо не компилируется, говоря «Невозможно взять адрес константных выражений», либо просто ничего не делает. Я думаю, это связано с тем, как работают указатели.

Я нашел актуальную информацию здесь, но я не читаю C.

Спасибо за любой совет!

задан 13 июн ’14, 22:06

Можете ли вы показать, как определены ваши узлы — Ken White

Спасибо. Я не хотел просто предположить, что ваше определение узла было таким же, как код C, который вы связали. 🙂 — Ken White

Код, который не компилируется, не отображается? Или где ошибка? — Marco van de Voort

2 ответы

Думаю, что-то вроде этого сработает:

Я не был уверен, что это сработает в классическом Паскале. Я не очень хорошо помню, что было раньше — Delphi меня избаловал. 🙂 — Кен Уайт

Что-то вроде этого должно сработать для вас. Он использует локальную переменную типа Node (которая, предположительно, является указателем на PNode) в качестве заполнителя.

Вот его версия, которая не является методом объекта, с консольным приложением, которое его тестирует:

Спасибо за хороший ответ, но он не работает для меня. Странно, один из узлов вычеркнут из списка напрочь! — миги

Он отлично работает в тестовом приложении, которое я предоставил. Я не могу объяснить, почему это не работает, когда вы реализуете это в своем коде, потому что я не вижу вашего кода. — Кен Уайт

Я просто перебираю узлы списка, чтобы записать их. После подкачки один из замененных элементов просто опускается. Хм. — миги

Я не вижу вашей реализации списка, как вы добавляете элементы или выделяете память или какую-либо другую информацию. Я добавил пару строк кода в тестовое приложение выше, чтобы продемонстрировать, что оба узла не повреждены (но поменялись местами) после замены. Просто чтобы уточнить: вы используете только функцию List.switch в своем коде, а не код тестового приложения, который использует New и Dispose? — Кен Уайт

Я понимаю. Да, я тестирую его на своем коде и получаю здесь какое-то странное поведение. Список обрезается перед первым замененным узлом, а узел перед первым замененным узлом указывает на второй замененный узел. Может проблема в моей реализации, но я трижды проверил и так не думаю. — миги

Не тот ответ, который вы ищете? Просмотрите другие вопросы с метками linked-list pascal or задайте свой вопрос.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Школа онлайн с государственным аттестатом