Удаление отрицательных элементов из списка - C (СИ)
Формулировка задачи:
Решение задачи: «Удаление отрицательных элементов из списка»
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
typedef struct node {
struct node* next;
int val;
} snode;
typedef struct {
snode* head;
snode* tail;
} slist;
void slist_init(slist* lst);
int slist_add(slist* lst, int val);
void slist_clear(slist* lst);
void slist_print(FILE* _out, const slist* lst);
void slist_remove(slist* lst, int (*pfcmp)(int));
static int fcmp(int val) { return (val < 0); }
int main(void){
int i;
slist lst;
slist_init(&lst);
for(i = 0; i < 20; ++i)
slist_add(&lst, -9 + rand() % 19);
slist_print(stdout, &lst);
slist_remove(&lst, &fcmp);
slist_print(stdout, &lst);
slist_clear(&lst);
return 0;
}
//удаление
void slist_remove(slist* lst, int (*pfcmp)(int)){
snode* t, *i, *p = lst->head;
for(i = lst->head; i != NULL; ){
if((*pfcmp)(i->val)){
t = i;
if(i == lst->head)
p = i = lst->head = lst->head->next;
else {
if(i == lst->tail)
lst->tail = p;
i = p->next = i->next;
}
free(t);
continue;
}
p = i;
i = i->next;
}
if(lst->head == NULL)
lst->tail = NULL;
}
//инициализация
void slist_init(slist* lst){
lst->head = lst->tail = NULL;
}
//вставка
int slist_add(slist* lst, int val){
snode* p = (snode*)malloc(sizeof(snode));
if(p != NULL){
p->val = val;
p->next = NULL;
if(lst->head == NULL)
lst->head = lst->tail = p;
else {
lst->tail->next = p;
lst->tail = p;
}
}
return (p != NULL);
}
//удаление всех
void slist_clear(slist* lst){
snode* t;
while(lst->head != NULL){
t = lst->head;
lst->head = lst->head->next;
free(t);
}
lst->tail = NULL;
}
//печать списка
void slist_print(FILE* _out, const slist* lst){
const snode* p;
for(p = lst->head; p != NULL; p = p->next)
fprintf(_out, "%d ", p->val);
fputc('\n', _out);
}
Объяснение кода листинга программы
Код представляет собой реализацию односвязного списка в языке C. Структура данных состоит из двух указателей: head и tail, которые указывают на начало и конец списка соответственно. Каждый элемент списка представлен структурой snode, которая содержит указатель на следующий элемент (next) и значение (val). Функция slist_init инициализирует список, устанавливая head и tail в NULL. Функция slist_add добавляет новый элемент в список. Если выделенный массив не равен NULL, то в нем устанавливается значение элемента, а затем он добавляется в список, становясь последним элементом. Если список пуст, то новый элемент становится и первым, и последним. Функция slist_clear удаляет все элементы из списка, начиная с первого, и освобождает память, выделенную под каждый элемент. Функция slist_print выводит все элементы списка на экран, разделяя их пробелами. Функция slist_remove удаляет из списка все элементы, значение которых меньше нуля. Для этого используется функция сравнения fcmp, которая возвращает ненулевой результат, если значение меньше нуля. В цикле проходят по всем элементам списка. Если значение текущего элемента меньше нуля, то его удаляют из списка, освобождают память и продолжают проход по списку с нового места. Если после удаления всех элементов список оказывается пустым, то head и tail устанавливаются в NULL.