IPB
ЛогинПароль:

> Прочтите прежде чем задавать вопрос!

1. Заголовок темы должен быть информативным. В противном случае тема удаляется ...
2. Все тексты программ должны помещаться в теги [code=pas] ... [/code].
3. Прежде чем задавать вопрос, см. "FAQ", если там не нашли ответа, воспользуйтесь ПОИСКОМ, возможно такую задачу уже решали!
4. Не предлагайте свои решения на других языках, кроме Паскаля (исключение - только с согласия модератора).
5. НЕ используйте форум для личного общения, все что не относится к обсуждению темы - на PM!
6. Одна тема - один вопрос (задача)
7. Проверяйте программы перед тем, как разместить их на форуме!!!
8. Спрашивайте и отвечайте четко и по существу!!!

> Циклический односвязный список с зацикливанием через указатель (голову), Задача
zabludshiy
сообщение 8.11.2011 9:51
Сообщение #1





Группа: Пользователи
Сообщений: 6
Пол: Мужской
Реальное имя: MAX

Репутация: -  0  +


Помогите добрые люди разобраться в следующей задаче: заполнить циклический односвязный список с зацикливанием «через голову». Дополнительные операции: a) добавить новый узел в хвост; б) вывести текущий список на экран ... примечание к задаче "Некоторые сложности представляет согласование типов указателей. Например, для инициализации пустого списка не всегда удается просто написать «Head := @Head», это может быть синтаксической ошибкой (в зависимости от настроек компилятора). Более корректно использовать явное преобразование типов: «Head := Link(@Head)». При этом важно, чтобы поле Next было обязательно описано как первое поле записи Node."

Прога получилась следующая:

 
program Lr_1;
{Вариант задания: циклический односвязный список с зацикливанием
"через голову".}
Type
Link = ^Node;
Node = record
Next: Link;
Data: Integer;
end;
List = Link;

Var
choice: Integer;
item: Integer;
list1: List;

procedure menu;
{Приглашение к вводу команды}
begin
Writeln('*************************************************************');
Writeln('* Действие со списком: *');
Writeln('* 2 - Добавить узел в хвост *');
Writeln('* 5 - выдача текущего списка на экран *');
Writeln('* 0 - Завершить работу (+освобождение памяти) *');
Writeln('*************************************************************');
Write('> ');
end; {menu}

procedure InitList(var L: List);
{Инициализация списка}
begin
l:=nil;
end; {InitList}

procedure FreeList(var L: List);
{Освобождение памяти списка}
var
p: list;
begin
while L^.next <> link(@L) do
begin
p := L;
L := L^.Next;
Dispose(p);
end;
end; {FreeList}

procedure ShowList(L: List);
var p:list;
begin
write('Текущий список ');
p:=l;
if p = nil then {Пустой список}
Write(' ->')
else
repeat
Write(' -> ', p^.Data);
p := p^.Next;
until p = link(@l);
Writeln;
end; {ShowList}

procedure InTail(var L: List; item: Integer);
{Вставка узла с данными item в хвост списка L}
var
p, q: Link;
begin
p := New(Link);
p^.Next := nil;
p^.Data := item;
if L = nil then
begin
L := p;
p^.next:=link(@l);
end
else begin
q := L;
while q^.Next <> link(@l) do
q := q^.Next;
{Теперь q указывает на последний узел}
p^.Next := q^.next;
q^.Next := p;
end;
end; {InTail}

begin
{Основная программа}
InitList(list1);
repeat
menu;
readln(choice);
case choice of
0: begin
FreeList(list1);
break;
end;
2: begin
Write('Введите добавляемое значение: ');
Readln(item);
InTail(list1, item);
end;
5: begin
showlist(list1);
end;
else
end;
until choice = 0;
end.



Заполняется без зависаний и выпадающих ошибок, но когда список выводится происходит зацикливание. Не могу понять почему, нигде не могу найти ни ответа ни подобного примера. Помогите кто чем может!!! wacko.gif
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
 
 Ответить  Открыть новую тему 
Ответов
IUnknown
сообщение 8.11.2011 17:37
Сообщение #2


a.k.a. volvo877
*****

Группа: Пользователи
Сообщений: 1 013
Пол: Мужской

Репутация: -  627  +


Цитата
Если я правильно понимаю задачу, надо добиться использования link(@L) вместо link(L)
Нет. Использовать Link(@L) нельзя. Точка. Забудь об этом. Нельзя заткнуть рот компилятору насильным преобразованием какого-то постороннего значения к нужному тебе типу, и потом надеяться, что программа будет работать корректно.

Цитата
2 схема - структура списка, которую надо сделать
А какой смысл в этом? Сделать какой-то левый указатель, который бы указывал на весь список, но не имел бы ни поля Data, ни поля Next? Зачем он нужен тогда? Чтоб память позанимать лишнюю? Реализация будет вот такая (решай сам, надо оно тебе или нет) :

program Lr_1;
uses crt;
type
{
Link будет указателем на элемент списка, имеющий поля
next и Data. Из подобных элементов и будет строиться "кольцо"

ListPtr же будет указателем на САМ СПИСОК (у тебя на схеме
он выглядит именно так: нечто, что указывает на начало кольцевого
списка)
}
Link = ^Node;
Node =
record
Next : Link;
Data : Integer;
end;
ListPtr = ^Link;

procedure menu;
begin
Writeln('*************************************************************');
Writeln('* Действие со списком: *');
Writeln('* 2 - Добавить узел в хвост *');
Writeln('* 5 - выдача текущего списка на экран *');
Writeln('* 0 - Завершить работу (+освобождение памяти) *');
Writeln('*************************************************************');
Write('> ');
end; {menu}

{ Инициализация списка: выделим память под этот "аппендикс", но указывать
он пока ни на что не будет }
procedure InitList(var L: ListPtr);
begin
new(L);
L^ := nil;
end; {InitList}

{ Освобождаем список: Все, как и раньше, но чтобы получить первый полезный
элемент - обращаемся по адресу, который хранится в "аппендиксе" }
procedure FreeList(var L: ListPtr);
var
p, q : Link;
begin
if L^ <> nil then { "аппендикс" на что-то указывает? Тогда удаляем }
begin
q := L^; { "Первый" элемент списка }
repeat
p := q^.next;
dispose(q);
q := p;
until q = L^; { До тех пор, пока не доберемся до того места, куда указывает L }

dispose(L); { удаляем сам "аппендикс". Это можно делать и в другом месте }
L := nil;
end;
end; {FreeList}

{ Показываем список }
procedure ShowList(L: ListPtr);
var p : Link;
begin
write('Текущий список ');
P := L^; { Опять же, начинаем оттуда, куда указывает L }
if p = nil then Write(' ->')
else
repeat
Write(' -> ', p^.Data);
p := p^.Next;
until P = L^;
Writeln;
end; {ShowList}

{ Добавляем элемент }
procedure InTail(var L: ListPtr; item : Integer);
var
p, q : Link;
begin
p := New(Link); { Память выделяем в любом случае }
p^.Next := nil;
p^.Data := item; { Сохраняем данные }

if L^ = nil then { Список был пуст? }
begin
L^ := p; { "Аппендикс" теперь указывает на добавленный элемент }
p^.next := p; { , а элемент указывает сам на себя }
end
else
begin { Нет, уже что-то добавлялось }
q := L^;
{ Ищем жлемент, указывающий на "начало" }
while q^.Next <> L^ do q := q^.Next;
{ И добавляем после него (между ним и "началом") новый элемент }
p^.Next := q^.next;
q^.Next := p;
end;
end; {InTail}

var
choice: Integer;
item: Integer;
list1: ListPtr;

begin
{ Основная программа }
InitList(list1);
repeat
Menu;
readln(choice);
case Choice of
0 : FreeList(list1);
2 :
begin
Write('Введите добавляемое значение: ');
Readln(item);
InTail(list1, item);
end;
5:
begin
showlist(list1);
end;

else {}
end { case };
until choice = 0;
end.


 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 

Сообщений в этой теме


 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 



- Текстовая версия 31.07.2025 18:03
Хостинг предоставлен компанией "Веб Сервис Центр" при поддержке компании "ДокЛаб"