Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции по прогр.ч.2.doc
Скачиваний:
3
Добавлен:
01.05.2025
Размер:
293.89 Кб
Скачать

Лекция 10

Обработка однонаправленных списков на языке С++

Рассмотрим принципы обработки списков на примере ЛОС.

Постановка задачи. Определить класс, включающий следующие поля:

целое число;

строку;

адрес первого элемента ЛОС;

указатель на следующий элемент ЛОС;

и следующие методы:

создание ЛОС;

вывод на экран элементов ЛОС;

сохранение в файле ЛОС;

считывание элементов файла в ЛОС;

поиск заданного элемента в ЛОС.

#include<iostream.h>

#include<conio.h>

#include<fstream.h>

#include<stdio.h>

#define n 3

class los

{int b;

char str[20];

los *next;

public:

static los*p;//адрес начала ЛОС

void create();

void output();

int savef();

int loadf();

};

los*los::p;

void los::create()

{los *q;//текущий указатель

clrscr();

p=new los;

cin>>p->b;

gets(p->str);

q=p;

for(int i=0;i<n-1;i++)

{q->next=new los;

q=q->next;

cin>>q->b;

gets(q->str);

}

q->next=NULL;

getch();

}

void los::output()

{clrscr();

los *q;

q=p;

while(q!=NULL)

{cout<<q->b<<"\n";

cout<<q->str<<”\n”;

q=q->next;

}

getch();

}

int los::savef()

{clrscr();

ofstream out("test");

if(!out)

{

cout<<"The file can’n be created\n";

return 1;}

los *q;

q=p;

while(q!=NULL)

{out<<q->b<<’ ‘;

out<<q->str<<’ ‘;

q=q->next;

}

out.close();

cout<<”The file is created\n”;

getch();

return 0;

}

int los::loadf()

{clrscr();

ifstream in("test");

if(!in)

{

cout<<"The file does not exist\n";

return 1;

}

los*q;

p=new los;

in>>p->b;

in>>p=>str;

q=p;

for(int i=0;i<n-1;i++)

{

q->next=new los;

q=q->next;

in>>q->b;

in>>q->str;

}

q->next=NULL;

in.close();

cout<<”The file is readed\n”;

getch();

return 0;

}

void los::search()

{clrscr();

los *q;

int key;

cout<<”Enter key\n”;

cin>>key;

q=p;

while(q!=NULL &&q->b!=key)

q=q->next;

if(q!=NULL &&q->b==key)

{cout<<q->b;

cout<<”\n”;

cout<<q->str<<”\n”;

}

else

cout<<”The element is not found\n”;

getch();

}

void main()

{los ob;

clrscr();

ob.create();

ob.output();

ob.savef();

ob.loadf();

ob.output();

ob.search();

getch();

}

Циклический однонаправленный список

Циклический однонаправленный список(ЦОС) – это ДСД, каждый элемент которой включает информационное поле и ссылку на следующий элемент. В отличие от ЛОС последний элемент ЦОС в качестве указателя на следующий элемент использует адрес начала списка.

На языке С++ элемент ЦОС описывается так же, как элемент ЛОС.

Например, опишем класс, характеризующий ЦОС, и включим в него функцию создания ЦОС.

#include<iostream.h>

#include<conio.h>

#define n 3

class cos

{

int b;

cos *next;

public:

static cos *p;

void create();//создание ЦОС

};

cos *cos::p;

void cos::create()

{cos *q, *r;

clrscr();

p=new cos;

cin>>p->b;

p->next=p;

q=p;

for(int i=0;i<n-1;i++)

{r=new cos;

cin>>r->b;

r->next=p;

q->next=r;

q=r;

}

getch();

}

Лекция 11

Обработка двунаправленных списков

Рассмотрим линейный двунаправленный список (ЛДС). ЛДС – это ДСД, каждый элемент которой содержит информационное поле и два указателя на следующий и предыдущий элементы. У последнего элемента ссылка на следующий элемент равна NULL, а у первого элемента ссылка на предыдущий равна NULL.

Опишем класс, определяющий элемент ЛДС, и включим в него метод вставки заданного элемента в конец списка.

class lds

{int b;

lds *next;

lds *prev;

public:

static lds *p;

void insert();//вставка элемента в конец списка

};

lds *lds::p;

void lds::insert()

{lds *q, *r;

int key;

clrscr();

cin>>key;

if(p==NULL)

{p=new lds;

p->b=key;

p->next=NULL;

p->prev=NULL;

}

else

{q=p;

while(q->next!=NULL)

q=q->next;

r=new lds;

r->b=key;

r->next=NULL;

r->prev=q;

q->next=r;

}

getch();

}

Циклический двунаправленный список

Циклический двунаправленный список (ЦДС) – это ДСД , каждый элемент которой содержит информационное поле и два указателя на следующий и предыдущий элементы. В отличие от ЛДС в качестве указателя на следующий элемент у последнего элемента ЦДС используется адрес первого элемента, а в качестве указателя на предыдущий элемент у первого элемента ЦДС – указатель на последний элемент.

Например, создадим класс, характеризующий ЦДС, и включим в него метод удаления заданного элемента из списка.

class cds

{int b;

cds *next;

cds *prev;

public:

static cds *p;

void delete_element();//удаление элемента

};

cds *cds::p;

void cds::delete_element()

{cds *q;

int key;

clrscr();

cin>>key;

q=p;

if(p!=NULL)

if(p->next==p)//один элемент в списке

if(p->b==key)

{delete p;

p=NULL;

}

else

cout<<”Элемента нет.\n”;

else

{q=p;

do

{if(q->b==key)

{ q->next->prev=q->prev;

q->prev->next=q->next;

if(q==p)

p=q->next;

delete q;

q=p;

}

else

q=q->next;

}

while(q!=p);

}

getch();

}

Бинарные деревья поиска

На практике при программировании наряду со списками широко используются бинарные деревья.

Бинарное дерево – это конечное множество вершин, которое либо пусто, либо состоит из корня с двумя отдельными бинарными деревьями, которые называются левым и правым поддеревом этого корня.

Вершина y, находящаяся непосредственно ниже вершины x, называется непосредственным потомком х.

Вершину х называют непосредственным предком вершины у.

Если вершина дерева не имеет потомков, то ее называют листом.

Вершина, имеющая хотя бы одного потомка, называется внутренней.

Представление деревьев в памяти компьютера

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

  1. Каждая вершина должна содержать как минимум ключ и два указателя на левое и правое поддеревья.

  2. Для того, чтобы показать, что вершина не имеет левого или правого поддерева, необходимо соответствующему указателю присвоить значение NULL.

  3. Чтобы сделать дерево доступным для обработки, необходимо задать указатель на корень дерева.

На языке С++ элемент дерева можно описать в виде следующего класса:

class tree

{int key;//ключ

tree *left;//указатель на левое поддерево

tree *right;//указатель на правое поддерево

//методы класса

};

Способы обхода бинарных деревьев

Существуют три способа обхода бинарных деревьев: сверху – вниз, слева – направо, снизу – вверх.

Предположим, что t – указатель на корень дерева, f(t) – функция, выполняемая над каждой вершиной.

Сверху – вниз

void Pref(tree *t)

{if(t!=NULL)

{f(t);

Pref(t->left);

Pref(t->right);

}

}

Слева – направо

void Inf(tree *t)

{if(t!=NULL)

{ Inf(t->left);

f(t);

Inf(t->right);

}

}

Снизу – вверх

void Post(tree *t)

{if(t!=NULL)

{f(t);

Post(t->left);

Post(t->right);

}

}