Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Информатика_и_Пр_Бизнес_лекции.doc
Скачиваний:
84
Добавлен:
10.05.2015
Размер:
1.21 Mб
Скачать

10.1.3. Реализация линейного списка с помощью связанного однонаправленного списка

Связанный однонаправленный список – это список элементов, в котором последовательные элементы связанны указателями. Каждый элемент такой структуры содержит значение элемента списка (например, целое число или строку) и указатель на следующий элемент. Последний элемент содержит указатель со значением 0.

В языке С++ элемент списка – это структура из двух полей: информационного, содержащего значение элемента, и служебного, содержащего указатель на следующий элемент. Пример объявления типа элемента однонаправленного связанного списка:

struct element{

int info ; //значение элемента списка –целое число

element *next;//адрес следующего элемента

};

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

Создание и поддержка связанного списка требуют использования динамического распределения памяти: увеличения памяти при добавлении элементов и освобождения памяти, когда она не нужна списку, то есть использования операций new и delete.

Список, основанный на связанных указателями элементах, является более гибкой структурой, чем список, реализованный с помощью массива. Связанный однонаправленый список не требует выделения памяти под весь список заранее, как при использовании массивов: память выделяется под элемент списка в момент выполнения операции добавлении элемента и освобождается, когда потребность в элементе исчезает. Таким образом, при использовании связанных указателями списков происходит рациональное использование памяти, что особенно важно для программ, работающих с несколькими линейными списками. Кроме того, реализация списка в виде связанных указателями элементов позволяет эффективно выполнять операции вставки и удаления элементов, сцепления и разбиения списков, так как для выполнения этих операций не требуется перемещать элементы.

Пример программы, выполняющей операции над линейным списком целых чисел, реализованном с помощью связанного однонапрвленного списка:

#include <iostream.h>

#include <conio.h>

//Добавление элемента x в начало списка

void insertbegin (element* & list, int x);

//Добавление элемента x в конец списка

void insertend (element* & list, int x);

//Вывод списка

void print(element* list);

//Удаление первого элемента списка

void del (element* & list, bool &ok);

//Очистка списка

void clear(element* & list );

void main()

{

element * list1; //адрес начала списка

int x; //значение элемента списка

bool ok;

list1=0; //создание пустого списка

cout<<"x ? ";

cin>>x; //10

insertbegin(list1, x);

print( list1); //10

cout<<"x? ";

cin>>x; //20

insertend(list1, x);

print( list1); //10 20

del(list1,ok);

print( list1); //20

clear(list1);

del(list1,ok);

if (!ok)

cout<<”list1 is empty”<<endl;

print (list1);

getch();

}

void print(element* list)

{

element* node; //указатель на текущий элемент списка

if (list==0)

cout<<”list is empty”<<endl;

else

{

node=list;

while (node!=0) //цикл перемещения node по списку

{

cout<<node->info<<' ';

node=node->next; //перемещение к следующему элементу

}

cout<<endl;

}

}

void insertbegin(element* & list, int x)

{

element* node; //указатель на новый элемент

node=new element; //выделение памяти под новый элемент

//Заполнение элемента

node->info=x;

node->next=list;

list=node; //включение элемента в список

}

void insertend(element * & list, int x)

{

element * node, p; //указатели на новый и текущий элементы

node=new element; //создание элемента

//Заполнение элемента

node->info=x;

node->next= 0;

//Включение элемента в конец списка

if (node==0) //список пуст

list = node;

else

{//Поиск адреса последнего элемента

p=list;

while (p->next!=0)

p=node->next;

p->next=node;

}

}

void del (element* &list)

{

element* node; //адрес удаляемого элемента

if (list==0) //список пуст

ok=false;

else

{

node=list; //сохранение адреса удаляемого элемента списка

list=list->next; //исключение элемента из списка

delete node; //освобождение памяти

ok=true;

}

}

void clear(element* & list)

{

while(list!=0 )

del(list);

}

Недостатки связанных списков:

  • размер элементов связанных списков больше, чем размер элементов массивов, так как в них хранятся служебные данные – указатели;

  • связанные списки не допускают прямого обращения к элементу по его номеру;

  • поиск элементов в упорядоченном по значению элементов массиве выполняется бытрее, чем в упорядоченном связанном списке.