Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
печатай!!11!1.doc
Скачиваний:
5
Добавлен:
23.11.2019
Размер:
97.79 Кб
Скачать

Int main()

{List <int> l;

int value,curIndex,x,y,i;

Ifstream in("input.Txt");

ofstream out("output.txt");

in>>x;in>>y;

//пока не дошли до конца файла, считываем элементы,

while (in>>value)

{

curIndex=l.getLength()+1; //позиция, в которую вставляем узел будет на 1

//больше, чем количество узлов списка

l.insert(curIndex,value);//вставляем узел со значением valueв конец списка

}

In.Close();

for (int i=1;i<=l.getLength();i++)

//счетчик пробегает все позиции в списке

if (l.get(i)==x) //если значение элемента в текущей позиции равно x

{l.insert(i,y); //вставляем новый элемент у в текущую позицию

//при этом элемент со значением х сдвинется на следующую

l.remove(i+1); //удаляем его из списка

}

for (int i=1;i<=l.getLength();i++)

out<<l.get(i)<<" ";

l.~List();

out.close();

return 0;

}

_________________________________input.txt_____________________________

7 0

7 7 1 3 7 5 2 5 7 2 7 9 3 7 7

_____________________________output.txt________________________________

0 0 1 3 0 5 2 5 0 2 0 9 3 0 0

Рассмотрим подробнее, как выполняется данная задача. В цикле сначала вызывается метод get, который по номеру позиции возвращает значение элемента, стоящего на данной позиции в списке. Как выполняется это действие? Внутри метода get вызывается метод find, внутри которого вспомогательный указатель устанавливается на голову списка и начинает двигаться по списку, «отсчитывая» элементы, пока не доберется до нужного. Далее, если найден элемент x, то вызываются по очереди методы insertи remove. Метод insertвставляет данный элемент в данную позицию, для чего опять вызывается метод find, который снова устанавливает указатель на первый элемент и начинает двигаться по списку, пока не дойдет до данного. То же самое, происходит при выполнении метода remove. Конечно, проще один раз найти указатель на данный элемент и работать с ним, но нельзя, чтобы указатель на элемент списка был доступен «извне», это может привести к порче данных (по неосторожности или по безграмотности). Т.о. за удобство и безопасность приходится платить потерей эффективности. Если такую задачу приходится выполнять неоднократно, то в реализацию класса, можно добавить соответствующий метод, который будет иметь доступ к указателям и поэтому не будет выполнять «лишних» действий:

void change(Item x, Item y)

{ elem *cur=head; //устанавливаем вспомогательный указатель curна

//голову списка

while (cur!=NULL) //пока список не пройден

{

if (cur->inf==x) cur->inf=y; //если информационная часть очередного

//элемента равна x, заменяем ее на y

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

}

}

Реализация двухсвязного списка

Мы рассмотрели операции вставки и удаления, которые для двусвязного списка имеют свою специфику. Остальные операции выполняются почти так же, как и в случае односвязного списка, надо только помнить о том, что в каждом узле теперь два указателя.

class listException: public exception

{

public:

listException(const string & message="")

: exception(message.c_str())

{}

};

template <class Item>

class List

{

struct elem

{Item inf;

elem *next;

elem *prev;

elem (Item x):inf(x),next(0),prev(0)

{}

};

elem *head;

elem *tail;

int size;

elem *find(int index)

{

if ((index<1)||(index>size))

return NULL;

else

{

elem *cur=head;

for (int i=1;i<index;i++)

cur=cur->next;

return cur;

}

}

public:

List():head(0),tail(0),size(0){}

~List()

{while (!empty())

remove(1);

}

bool empty()

{return head==0;}

int getLength()

{return size;}

Item get(int index)

{

if ((index<1)||(index>size))

throw listException("StackException: get — list error");

else

{

elem *r=find(index);

Item i=r->inf;

return i;

}

}

void insertLeft(int index, Item data)

//слева от элемента в позиции indexвставляется элемент data

{

int newLength=getLength()+1;

if ((index<1)||(index>size+1))

throw listException("StackException: insert — list error");

else

{

elem *newPtr=new elem(data);

size=newLength;

//ищем указатель на узел в позиции index

elem *cur=find(index);

//если этот указатель пустой, то список был пуст, поэтому новый

//элемент будет и первым и последним

if (cur==NULL)

{

head=newPtr;

tail=newPtr;

}

else

//производим вставку в непустой список, выделяя отдельно случай

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

{

newPtr->next=cur;

newPtr->prev=cur->prev;

cur->prev=newPtr;

if (cur==head) head=newPtr;

else

newPtr->prev->next=newPtr;

}

}

}

void insertRight(int index, Item data)

//справа от элемента в позиции indexвставляется элемент data

{

int newLength=getLength()+1;

if ((index<1&&head!=NULL)||(index>size+1))

throw listException("StackException: insert — list error");

else

{

elem *newPtr=new elem(data);

size=newLength;

//ищем указатель на узел в позиции index

elem *cur=find(index);

//если этот указатель пустой, то список был пуст, поэтому новый

//элемент будет и первым и последним

if (cur==NULL)

{

head=newPtr;

tail=newPtr;

}

else

//производим вставку в непустой список, выделяя отдельно случай

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

{

newPtr->next=cur->next;

newPtr->prev=cur;

cur->next=newPtr;

if (cur==tail)

tail=newPtr;

else

newPtr->next->prev=newPtr;

}

}

}

void remove(int index)

//удалениеэлементавпозиции index

//выделяются частные случаи:

//когда список после удаления пуст (тогда нужно присвоить head=NULL;tail=NULL;)

//когда удаляемый элемент первый

//когда удаляемый элемент последний

//общийслучай

{

if ((index<1)||(index>size))

throw listException("StackException: remove — list error");

else

{elem *cur=find(index);

--size;

if (size==0)

{head=NULL;tail=NULL;}

else

if (cur==head)

{ head=head->next;

head->prev=NULL;

}

else

if (cur==tail)

{

tail=tail->prev;

tail->next=NULL;

}

else

{cur->prev->next=cur->next;

cur->next->prev=cur->prev;

}

cur->next=NULL;

cur->prev=NULL;

delete cur;

}

}

};

2.6. Решение практических задач с использованием

двунаправленного списка

1. В файле input.txtзаписана последовательность целых чисел. Создать на основе нее список, заменить в нем каждый элемент xна у. Полученный список переписать в файл output.txt

#include "exception"

#include "iostream"

#include "fstream"

#include "string"

using namespace std;

//описывается соответствующий класс

intmain()

{List <int> l;

int value,curIndex,x,y,i;