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

> Внимание!

1. Пользуйтесь тегами кода. - [code] ... [/code]
2. Точно указывайте язык, название и версию компилятора (интерпретатора).
3. Название темы должно быть информативным.
В описании темы указываем язык!!!

Наладить общение поможет, если вы подпишитесь по почте на новые темы в этом форуме.

 
 Ответить  Открыть новую тему 
> Удаление элементов из конца списка, Си
сообщение
Сообщение #1


Профи
****

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

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


Как можно удалить определённое число элементов из конца односвязного линейного списка?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #2


Гость






Я тебе уже говорил: пробегать по ВСЕМУ списку, считать число элементов в нем, потом сначала отсчитывать столько, сколько должно остаться, а остальные - удалять...
 К началу страницы 
+ Ответить 
сообщение
Сообщение #3


Профи
****

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

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


Цитата(volvo @ 16.05.2007 18:13) *

Я тебе уже говорил: пробегать по ВСЕМУ списку, считать число элементов в нем, потом сначала отсчитывать столько, сколько должно остаться, а остальные - удалять...

Я не пойму, как это сделать...
попробывала иначе (берём 2 подряд элемента, пусть p1 и p2. продвигаем их по списку
пока p2 не станет нулём. значит,p1 - указатель на последний, этот
элемент можно удалять. и так 5 раз) - не получилось....ничего не выводится в файл ( а должны быть оставшиеся элементы)


for (i=1; i==3; i++) // удалим 3 последних элементов
{
p1=lst;
p2=p1->next;

while (p2)
{p1=p1->next;
p2=p2->next;}
free(p1);
p1 = NULL;
}

for (p1=lst;p1;) //вывод оставшихся элементов
{ fprintf(f,"%s\n",p1->number);
p1=(T=p1)->next;
free(T);

} lst=NULL;


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


Гость






Цитата
Я не пойму, как это сделать...
Как-то вот так:
for(n = 0, p = lst; p; p = p -> next, n += 1);
for(p = lst; n > 5; p = p -> next);

// теперь p содержит адрес последнего элемента, который
// должен остаться в списке, это нужно, чтобы его next сбросить в NULL
// (предварительно запомнив где-то в доп. переменной), а потом просто
// проходить по отсеченному "хвосту" и удалять по одному элементу ...
 К началу страницы 
+ Ответить 
сообщение
Сообщение #5


Профи
****

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

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


Цитата(volvo @ 16.05.2007 19:50) *



// теперь p содержит адрес последнего элемента, который
// должен остаться в списке, это нужно, чтобы его next сбросить в NULL
// (предварительно запомнив где-то в доп. переменной), а потом просто
// проходить по отсеченному "хвосту" и удалять по одному элементу ...




for (n=0,p=lst;p;p=p->next,n+=1);
for(p=lst;n>5;p=p->next);
(T=p)->next=NULL;
for (T; T; T=T->next)
free(T);



Так? (по-моему у меня сново что-то не то...)

А вывод оставшегося в списке с последующим освобождение динамической памяти правильный:

for (p1=lst;p1;) // lst - голова списка
{ fprintf(f,"%s\n",p1->number);
p1=(T=p1)->next;
free(T);

} lst=NULL;



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


Гость






Цитата
по-моему у меня сново что-то не то
Естественно... Ты же удаляешь элемент T, а потом у уже удаленного переходишь по указателю next? Так нельзя... Надо так, например:

(T=p) -> next = NULL;
for(;T;) {
to_delete = T;
T = T -> next;
free(to_delete);
}
 К началу страницы 
+ Ответить 
сообщение
Сообщение #7


Профи
****

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

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


Цитата(volvo @ 16.05.2007 22:09) *

Естественно... Ты же удаляешь элемент T, а потом у уже удаленного переходишь по указателю next? Так нельзя... Надо так, например:

(T=p) -> next = NULL;
for(;T;) {
to_delete = T;
T = T -> next;
free(to_delete);
}


Ага..теперь поняла
А теперь, чтобы вывести оставшиеся элементы, я должна в цикле идти от головы списка до последнего оставшегося элемента (а что у нас после удаления выступает в качестве него?)
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #8


Гость






Зачем? Ты должна идти пока указатель ненулевой, не зря же я тебе отдельно сказал, что его обязательно надо обнулить...

Добавлено через 3 мин.
Стой, стой... Не так:
Цитата
(T=p) -> next = NULL;
, а вот так надо:

T = p -> next; // запоминаешь куда указывал предыдущий элемент
p -> next = NULL; // и потом уже указатель обнуляешь



Не злоупотребляй сдвоенными операциями - это очень легко приводит к ошибкам...

Сообщение отредактировано: volvo -
 К началу страницы 
+ Ответить 
сообщение
Сообщение #9


Профи
****

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

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


Цитата(volvo @ 16.05.2007 23:00) *

Зачем? Ты должна идти пока указатель ненулевой, не зря же я тебе отдельно сказал, что его обязательно надо обнулить...


т.е.

lst=p;
while (p)
{
fprintf(f, "%s",p->number);
p=p->next;
free(p);
}
lst=NULL;


???
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #10


Гость






Ты постоянно наступаешь на те же грабли...

lst=p;
while (p)
{
fprintf(f, "%s",p->number);
T = p; // !!! ты должна СОХРАНЯТЬ значение...
p = p->next; // потом продвигать указатель...
free(T); // и только потом удалять сохраненное значение
}
lst=NULL;



Я больше не буду повторять эти прописные истины... Только в этом треде я написал правильный код минимум 4 раза, ты опять все переворачиваешь по-своему...
 К началу страницы 
+ Ответить 
сообщение
Сообщение #11


Профи
****

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

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


Цитата(volvo @ 16.05.2007 19:50) *

for(n = 0, p = lst; p; p = p -> next, n += 1);
for(p = lst; n > 5; p = p -> next);




объясни пожалуйста, как из этих циклов получилось, что после них р - поледний элемент, стоящий перед 5-ю элементами, которые нужно удалить из конца списка?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #12


Профи
****

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

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


сделала всё, как было объяснено, но оставшиеся элементы не выводятся (а должны).
В чём же может быть причина?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #13


Гость






Вот этот вариант только что у меня прекрасно отработал:

...
printf("!!! starting !!!\n");
root = read_list();
for(p = root; p; p = p -> next)
printf("%s\n", p -> number);

for(n = 0, p = root; p; p = p -> next, n += 1);
for(p = root; n > 6; p = p -> next) n -= 1;
T = p -> next;
p -> next = NULL;
for(;T;) {
T = (p = T) -> next;
free(p);
}


printf("!!!after deleting!!!\n");
for(p = root; p; p = p -> next)
printf("%s\n", p -> number);
...

 К началу страницы 
+ Ответить 

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

 





- Текстовая версия 21.09.2020 20:52
500Gb HDD, 6Gb RAM, 2 Cores, 7 EUR в месяц — такие хостинги правда бывают
Связь с администрацией: bu_gen в домене octagram.name