Список – это последовательность структур, каждая из которых содержит ссылку, связывающую её с другой структурой. Для организации списков используются структуры, состоящие из двух смысловых частей – информационной и дополнительной. Информационная часть содержит подлежащую обработке информацию, в дополнительной находятся указатели на последующую или предыдущую структуру списка:
Struct spis { char data[20];
struct spis *next; }; // Указатель на структуру
Здесь при описании указателя используем ещё не описанный объект struct spis *next , который будет служить ссылкой на последующий элемент списка. Самая последняя структура в списке никуда не указывает, т.е. поле next должно иметь значение NULL. Адрес начала (головы) списка хранится в переменной типа указатель *head. На текущую структуру будет указывать *p.
Пример создания и просмотра односвязного списка.
#include <stdio.h> #include <conio.h> #include <alloc.h> struct spis {char data[20]; struct spis *next;}; struct spis * create(void); //прототип функции создания списка (возвращает адрес его головы) void list(spis *head); // прототип функции просмотра списка struct spis *head; // глобальная переменная, адрес головы списка main() {clrscr(); head= create(); list(head); free(head); } struct spis * create(void) {spis *p, *pred; char c; // pred – указатель на предыдущую структуру head=pred=p=(spis *)malloc(sizeof(spis)); //выделяем память для первой записи printf(" фамилия: "); scanf("%s", p->data); do { p=(spis *)malloc(sizeof(spis)); printf("\n фамилия: "); scanf("%s", p->data); pred->next=p; //ссылка из предыдущей записи на текущую pred=p; // сохранение адреса текущей записи printf(" Закончить? y/n "); c=getch(); } while (c!='y'); p->next=NULL; return head; } void list(spis *head) {spis *p; p=head; while (p!=NULL) // пока не конец списка {printf("\n фамилия: %s",p->data); p=p->next; // продвижение по списку } getch(); }
В двусвязном списке каждая структура содержит две ссылки: на предыдущую и последующую структуры. Таким образом, по списку можно перемещаться от начала к концу и от конца к началу. Для доступа к началу и концу списка должны быть известны их адреса, которые могут сохраняться в глобальных переменных типа указатель.
Пример создания и работы с двусвязным списком.
#include <stdio.h> #include <conio.h> #include <alloc.h> #include <string.h> struct spis {char data[20]; struct spis *v1; // v1 – указатель на предыдущую структуру struct spis *v2; // v2 – указатель на последующую структуру }; void create(void); // создание void list(spis *); // просмотр void del(void); // удаление struct spis *head,*tail; // указатели на начало и конец списка main() { clrscr(); create(); list(head); // просмотр с начала списка list(tail); // просмотр с конца списка del(); list(head); free(head); } void create(void) {spis *p,*pred; pred=NULL; do { p=(spis *)malloc(sizeof(spis)); printf("Фамилия: "); gets(p->data); p->v1=pred; if (pred != NULL) pred->v2=p; else head=p; pred=p; puts(" Закончить -"); } while (getch()!=27); tail=p; tail->v2=NULL; } void list(spis *p) {if (p==head) while (p != NULL) {puts(p->data); p=p->v2; } else if (p==tail) while ( p!= NULL) {puts(p->data); p=p->v1; } else puts("Неверный адрес "); getch(); } void del(void) {spis *p,*temp;char f[20]; // f[20] – Строка для удаляемой фамилии clrscr(); printf("Фамилия: ");gets(f); p=head; while (p!=NULL) {if (strcmp((p->data),f)==0) // если найдена заданная фамилия {if (p==head) // если найденная запись - первая {head=p->v2; head->v1=NULL; free(p); p=head; } else if (p==tail) // если найденная запись - последняя {tail=p->v1; tail->v2=NULL; free(p); p=tail; } else // удаление из средины списка {p->v2->v1=p->v1; p->v1->v2=p->v2; temp=p; p=p->v2; free(temp); } } else // если заданная фамилия не найдена – продвигаемся по списку p=p->v2; } }
1. Понятие статической и динамической памяти.
2. Как создаётся и просматривается односвязный список?
3. Как создаётся и просматривается двусвязный список?
4. Как удалить структуру из списка?
5. Как добавить структуру в список?