Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ЛЕКЦИИ Программирование и основы алгоритмизации...doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
1.5 Mб
Скачать

Функции для работы с двунаправленным линейным списком

Для формирования списка и работы с ним требуется иметь по крайней мере один указатель – на начало списка (pbeg). Удобно иметь ещё один указатель – на конец списка (pend). Для простоты допустим, что список состоит из целых чисел.

//----------------------------------------------------------------------------------------------

#include <iostream.h>

struct Node

{ int d;

Node* next;

Node* prev;

};

//--------------------------------------------------------------------------------------------

Node* first(int d); //формирование первого элемента

void add(Node** pd, int d); //добавление элемента в конец списка

Node* find(Node* const pg, int key); //поиск элемента по ключу

int remove(Node** pg, Node** pd, int key); //удаление элемента по ключу

Node* insert(Node* const pg, Node** pd, int key, int d); //вставка после key

//----------------------------------------------------------------------------------------------

void main()

{ Node* pbeg=first(1); //формирование 1-го элемента списка

Node* pend=pbeg; //список состоит из одного элемента

//добавление в конец списка 4-х элементов 2, 3, 4, 5:

for(int i=2; i<6; i++) add(&pend, i);

//вставка элемента 10 после элемента 2:

insert(pbeg, &pend, 2, 10);

//удаление элемента 5:

if(!remove(&pbeg, &pend, 5)) cout<<”не найден”;

//вывод списка на экран:

Node* pv=pbeg; //pv – вспомогательный указатель

while(pv){ cout<<pv->d<<’ ‘;

pv=pv->next; }

}

//----------------------------------------------------------------------------------------------

На экране: 1 2 10 3 4

//---------------------------------------------------------------------------------------------

//Формирование 1-го элемента списка

Node* first(int d)

{ Node* pv=new Node;

pv->d=d; pv->next=0; pv->prev=0;

return pv;

}

//----------------------------------------------------------------------------------------------

//Добавление в конец списка

void add(Node** pd, int d)

{ Node* pv=new Node;

pv->d=d; pv->next=0; pv->prev=*pd;

(*pd)->next=pv; *pd=pv;

}

//----------------------------------------------------------------------------------------------

//Поиск элемента по ключу

Node* find(Node* const pg, int key)

{ Node* pv=pg;

while(pv{

if(pv->d==key) break;

pv=pv->next;

}

return pv;

}

//----------------------------------------------------------------------------------------

//Удаление элемента по ключу

int remove(Node** pg, Node** pd, int key)

{ if(Node* pkey=find(*pg, key))

if(pkey==*pg) //удаляется 1-й элемент

{ *pg=(*pg)->next;

(*pg)->prev=0; }

else if(pkey==*pd) //удаляется последний элемент

{ *pd=(*pd)->prev;

(*pd)->next=0; }

else{ //удаляется элемент внутри списка

(pkey->prev)->next=pkey->next;

(pkey->next)->prev=pkey->prev;

}

delete pkey; //освобождается память под элементом списка

return 1;

}

return 0;

}

//----------------------------------------------------------

//Вставка элемента после элемента с key

Node* insert(Node* const pg, Node** pd, int key, int d)

{ if(Node* pkey=find(pg, key))

{ Node* pv=new Node;

pv->d =d;

//установление связи вставляемого элемента с последующим (1)

pv->next=pkey->next;

//установление связи вставляемого элемента с предыдущим (2)

pv->prev=pkey;

//установление связи предыдущего элемента с вставляемым (3)

pkey->next=pv;

//установление связи последующего элемента с вставляемым (4)

if(pkey!=*pd) (pv->next)->prev=pv;

//обновление указателя на конец списка, если элемент

//вставляется в конец списка

else *pd=pv;

return pv;

}

return 0;

}

Примечание. Все параметры, не изменяемые внутри функций, должны передаваться с const. Указатели, которые могут изменяться (например, при удалении из списка последнего элемента указатель на конец списка требуется переназначить на предпоследний элемент), передаются по адресу.

Сортировка связанного списка заключается в изменении связей между элементами. Исходный список просматривается, и каждый элемент вставляется в новый список на место, определяемое значением его ключа.

//----------------------------------------------------------------------------------------------

//Функция формирования упорядоченного (по возрастанию d) списка

// (предполагается, что первый элемент уже существует).

void add_sort(Node** pg, Node** pd, int d)

{ Node* pv=new Node;

pv->d=d;

Node* pt=*pg; // pt – указатель на текущий элемент списка

while(pt) { // просмотр списка

if(d<pt->d) // занести перед текущим элементом

{ pv->next=pt;

if(pt==*pg) // в начало списка

{ pv->prev=0;

*pg=pv; }

else // в середину списка

{ (pt->prev)->next=pv;

pv->prev=pt->prev; }

pt->prev=pv;

return;

}

pt=pt->next;

}

pv->next=0; // в конец списка

pv->prev=*pd;

(*pd)->next=pv;

*pd=pv;

}

//----------------------------------------------------------------------------------------------

//Функция уничтожения списка

void clear(Node** pg)

{ Node* pv=*pg,*pr=0; // pv и pr – указатели на текущий и предыдущий

// элементы списка

cout<<”Список уничтожается! \n”;

while(pv)

{ pr=pv; pv=pv->next;

delete pr; }

*pg-0;

}

//-----------------------------------------------------------------------------------------