Помощь - Поиск - Пользователи - Календарь
Полная версия: Динамические структуры, удаление текущего элемента x линейного списка.
Форум «Всё о Паскале» > Pascal, Object Pascal > Задачи
Catherinektz
Здравствуйте, мне нужна помощь, я сделала все процедуры (ниже в программе), а процедуру Remove(var x:PNode) не знаю как сделать! Помогите, пожалуйста. В ней нужно удалить текущий элемент x линейного списка.

Program Labal1_2;
Uses crt;

Type PNode=^Node;
Node=Record
data:Integer;
next:PNode;
End;

Var u,y:PNode;
n,k:Integer;

Procedure AddFirst(k:Integer; var p:PNode);
var t:PNode;
Begin
New(t);
t^.data:=k;
t^.next:=p;
p:=t;
End;

Procedure InputList(var p:PNode; n:Integer);
Var i,k:Integer;
Begin
For i:=1 To n Do Begin
                 Write('Введите k:');
                 ReadLn(k);
                 AddFirst(k,p)
                 End;
End;

Procedure PrintList(p:PNode);
Begin while p<>nil Do Begin
                      Write(p^.data, ' ');
                      p:=p^.next;
                      End;
WriteLn;
End;

Procedure DelFirst(var p:PNode);
Var t:PNode;
Begin
t:=p;
p:=p^.next;
dispose(t);
End;

Procedure DelNext(x:PNode);
Var t:PNode;
Begin
t:=x^.next;
x^.next:=t^.next;
dispose(t);
End;

Procedure DelLast(var x:PNode);
Var q:PNode;
Begin
If x^.next=nil Then DelFirst(x) Else Begin
                                     q:=x;
                                     While q^.next^.next<>nil Do q:=q^.next;
                                     DelNext(q);
                                     End;
End;

Procedure Delete(n:Integer; var p:PNode);
Var i,k:Integer;
Var q:PNode;
Begin
If n=1 Then DelFirst(p) Else Begin
                             q:=p;
                             For i:=1 To n-2 Do Begin
                                                If q^.next=nil Then Break Else q:=q^.next;
                                                End;

                             If q^.next<>nil Then DelNext(q) Else WriteLn('Нет столько элеметов в списке');

                             End;
End;

Procedure Clear(var p:PNode);
Begin
While p<>nil Do DelFirst(p);
End;



Begin
Clrscr;
WriteLn('Тестирование');

Writeln('Введите количество элементов в списке:');
Read(k);
InputList(u,k);
PrintList(u);

WriteLn('Удаление первого элемента:');
DelFirst(u);
PrintList(u);

WriteLn('Удаление элемента следующего за:');
DelNext(u);
PrintList(u);

WriteLn('Удаление последнего элемента:');
DelLast(u);
PrintList(u);

WriteLn('Удаление заданного элемента:');
WriteLn('Введите номер элемента');
ReadLn(n);
Delete(n,u);
PrintList(u);

WriteLn('Удаление всего списка:');
Clear(u);
PrintList(u);

ReadLn;
End.
Федосеев Павел
Здесь в FAQ есть ответ:
Цитата
Если следует удалить элемент на который указывается ссылка q, то следует в начале присвоить элементу q^ значение следующего за ним элемента, а затем этот элемент удалить.

{удаление элемента q^}
Procedure Delete(Var q: point);
Var r: point;
Begin
  r:=q^.next;
  q^:=r^;
  r^.Next:=nil; 
End;

Цитата
Обратите внимание на то, что удаляемый из списка элемент остается в памяти и к нему имеется доступ к указателю r, так что в дальнейшем этот элемент можно вставить, например, в другой список. Если требуется освободить занимаемую этим элементом память, то следует выполнить:
{ ... }
Dispose( r );
r:=nil;
{ ... }
Catherinektz
Цитата(Федосеев Павел @ 15.03.2012 20:12) *

Здесь в FAQ есть ответ:

{удаление элемента q^}
Procedure Delete(Var q: point);
Var r: point;
Begin
  r:=q^.next;
  q^:=r^;
  r^.Next:=nil; 
End;




К сожалению не работает, выдает ошибку разыменования нулевого указателя. Я записала так:
Procedure Remove(Var x:PNode);
Var r:PNode;
Begin
r:=x^.next;
x^:=r^;
r^.Next:=nil;
{Dispose®;
r:=nil; }
End;

в основной программе:
WriteLn('Удаление:');
Remove(u);
PrintList(u);
End.
Федосеев Павел
FAQ не идеал, а образец для подражания (почти как "пиратский кодекс")

Procedure Remove(Var x:PNode);
Var r:PNode;
Begin
 r:=x^.next;
 if Assigned( r) then
 begin
   x^:=r^;
  Dispose( r);
 end
 else
   DelLast(x);
End;
Catherinektz
Цитата(Федосеев Павел @ 15.03.2012 23:01) *

FAQ не идеал, а образец для подражания (почти как "пиратский кодекс")

Procedure Remove(Var x:PNode);
Var r:PNode;
Begin
 r:=x^.next;
 if Assigned( r) then
 begin
   x^:=r^;
  Dispose( r);
 end
 else
   DelLast(x);
End;




А что такое Assigned (перевод понимаю и знаю), а вот как и для чего нет! В Pascal ABC выдает ошибку
Федосеев Павел
Sorry, за выпендрёж.

Assign(p) эквивалент p<>nil
Catherinektz
Цитата(Федосеев Павел @ 16.03.2012 12:14) *

Sorry, за выпендрёж.

Assign(p) эквивалент p<>nil


Спасибо, буду пробовать!
Catherinektz
А что обозначает эта строчка: x^:=r^;
У меня почему -то удаляет только первый элемент списка.
IUnknown
Можно посмотреть на окончательный вариант программы? Конкретно - уточни, что именно по-твоему должна делать процедура Remove? И как находится тот элемент, который в Remove передается? И как, наконец, вызывается эта самая Remove...
Catherinektz
Цитата(IUnknown @ 20.03.2012 12:36) *

Можно посмотреть на окончательный вариант программы? Конкретно - уточни, что именно по-твоему должна делать процедура Remove? И как находится тот элемент, который в Remove передается? И как, наконец, вызывается эта самая Remove...

Procedure Remove(Var x:PNode);
Var r:PNode;
Begin
r:=x^.next;
If r<>nil Then Begin
x^:=r^;
Dispose®;
End
Else
DelLast(x);
End;

В программе:
WriteLn('Удаление текущего элемента x линейного списка:');
Remove(u);
PrintList(u);

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

Добавлено через 6 мин.
Вот вся моя программа:
Program Labal1_2;
Uses crt;

Type PNode=^Node;
Node=Record
data:Integer;
next:PNode;
End;

Var u,y:PNode;
n,k:Integer;

Procedure AddFirst(k:Integer; var p:PNode);
var t:PNode;
Begin
New(t);
t^.data:=k;
t^.next:=p;
p:=t;
End;

Procedure InputList(var p:PNode; n:Integer);
Var i,k:Integer;
Begin
For i:=1 To n Do Begin
Write('Введите k:');
ReadLn(k);
AddFirst(k,p)
End;
End;

Procedure PrintList(p:PNode);
Begin while p<>nil Do Begin
Write(p^.data, ' ');
p:=p^.next;
End;
WriteLn;
End;

Procedure DelFirst(var p:PNode);
Var t:PNode;
Begin
t:=p;
p:=p^.next;
dispose(t);
End;

Procedure DelNext(x:PNode);
Var t:PNode;
Begin
t:=x^.next;
x^.next:=t^.next;
dispose(t);
End;

Procedure DelLast(var x:PNode);
Var q:PNode;
Begin
If x^.next=nil Then DelFirst(x) Else Begin
q:=x;
While q^.next^.next<>nil Do q:=q^.next;
DelNext(q);
End;
End;

Procedure Delete(n:Integer; var p:PNode);
Var i,k:Integer;
Var q:PNode;
Begin
If n=1 Then DelFirst(p) Else Begin
q:=p;
For i:=1 To n-2 Do Begin
If q^.next=nil Then Break Else q:=q^.next;
End;

If q^.next<>nil Then DelNext(q) Else WriteLn('Нет столько элеметов в списке');

End;
End;

Procedure Clear(var p:PNode);
Begin
While p<>nil Do DelFirst(p);
End;


Procedure Remove(Var x:PNode);
Var r:PNode;
Begin
r:=x^.next;
If r<>nil Then Begin
x^:=r^;
Dispose®;
End
Else
DelLast(x);
End;


Begin
Clrscr;
WriteLn('Тестирование');

Writeln('Введите количество элементов в списке:');
Read(k);
InputList(u,k);
PrintList(u);

WriteLn('Удаление первого элемента:');
DelFirst(u);
PrintList(u);

WriteLn('Удаление элемента следующего за:');
DelNext(u);
PrintList(u);

WriteLn('Удаление последнего элемента:');
DelLast(u);
PrintList(u);

WriteLn('Удаление текущего элемента x линейного списка:');
Remove(u);
PrintList(u);

WriteLn('Удаление заданного элемента:');
WriteLn('Введите номер элемента');
ReadLn(n);
Delete(n,u);
PrintList(u);

WriteLn('Удаление всего списка:');
Clear(u);
PrintList(u);

ReadLn;
End.
IUnknown
Цитата
WriteLn('Удаление текущего элемента x линейного списка:');
Remove(u);
То есть, в Remove передается начало списка? Тогда почему тебя это удивляет:
Цитата
У меня почему -то удаляет только первый элемент списка.
? Какой же элемент должен удалиться, если процедура получила адрес первого?

Цитата
Я думаю, что нужно ввести еще переменную, где будем указывать какой именно элемент в списке, и затем он его будет удалять.
Почему переменную, а не функцию? Скажем, реализовать функцию Search (которая в списке будет искать первый элемент с заданным значением и возвращать ссылку на него), и вызывать Remove вот так:

Remove( Search(u, 6) );
Catherinektz
Цитата(IUnknown @ 20.03.2012 21:11) *

То есть, в Remove передается начало списка? Тогда почему тебя это удивляет:
? Какой же элемент должен удалиться, если процедура получила адрес первого?

Почему переменную, а не функцию? Скажем, реализовать функцию Search (которая в списке будет искать первый элемент с заданным значением и возвращать ссылку на него), и вызывать Remove вот так:

Remove( Search(u, 6) );


А можно мне еще эту функцию написать, а то я только с работы пришла, вообще голова не варит!
-Федосеев Павел-
Глянь ещё раз в FAQ. Там есть одноимённая процедура (Search). Переделай её в функцию.
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.