Академический Документы
Профессиональный Документы
Культура Документы
Chişinău
2015
0
ТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ МОЛДОВЫ
Chişinău
Editura „Tehnica-UTM”
2015
1
Данные методические указания и задания к лабораторным
работам, которые предназначены для изучения использования
структур данных, таких как двумерная матрица, одномерный
массив указателей, связный список, очередь, стек и дерево для
задания графов и деревьев и для реализации алгоритмов поиска
в глубину и в ширину на графах и деревьях на языке С/С++.
Для каждой лабораторной работы указаны: тема, цель работы,
теоретические сведения, контрольные вопросы, условие
задачи, приведены 15 вариантов заданий и примеры базовых
программ на языке С/С++.
Работа предназначена для студентов всех специальностей
факультета информатики, вычислительной техники и
микроэлектроники дневной и заочной форм обучения,
изучающих дисциплины «Программирование на языке С/С++»,
«Структуры данных и алгоритмы» и «Дискретная математика».
Редактор Т. Олиниченко
UTM, 2015
2
Лабораторная работа № 1
3
Например, для неориентированного графа на рис.1
e1
v1
v2
e4
e3 e2
v4 e5
v3
v1 v2 v3 v4
е1 1 1 0 0
е2 0 1 1 0
е3 0 1 0 1
е4 1 0 0 1
e5 0 0 1 1
4
000
Например, для ориентированного графа на рис. 3
e1 v2
v1
е4 е3 е2
v4
е5
v3
Рис 3. Ориентированный граф
v1 v2 v3 v4
e1 -1 1 0 0
e2 0 -1 1 0
e3 -1 0 1 0
e4 -1 0 0 1
e5 0 0 1 -1
5
Матрица смежности графа [2, 3]
Матрицей смежности неориентированного графа с n
вершинами называется квадратная матрица
A aij , i, j 1,2,...,n , в которой
v1 v2 v3 v4
v1 0 1 1 1
v2 0 0 1 0
v3 0 0 0 0
v4 0 0 1 0
Списки смежности
Представление графа с помощью матрицы смежности
зачастую неудобно, поскольку заранее необходимо знать
количество вершин. Если граф должен создаваться или
изменяться во время исполнения программы, то для каждого
добавления или удаления вершины надо строить новую
матрицу. Кроме того, даже если граф содержит малое число
ребер (дуг) и матрица смежности состоит в основном из нулей,
память должна быть отведена для всех возможных дуг вне
зависимости от того, существуют ли они. Если граф содержит
7
n вершин, то должна быть отведена память для n2 элементов.
Поэтому лучшим решением для представления графа является
использование динамических (связанных) структур данных -
списков смежности.
Списки смежности содержат для каждой вершины v,
принадлежащей множеству вершин V, список смежных ей
вершин [1, 3]. Используя терминологию языка С/С++, можно
утверждать, что каждый элемент такого списка является
структурой с адресом R в памяти, содержащей в поле (*R).Key
вершину графа, а в поле (*R).Sled - указатель на следующую
структуру в списке. Ясно, что для последней структуры в
списке (*R).Sled содержит NULL. Обозначим beg[v] -
указатель на начало списка, содержащего вершины, смежные с
вершиной v, где beg является массивом указателей на входы в
цепочки. Признаком конца цепочки является указатель на
ноль - NULL в языке С/С++. Например, для ориентированного
графа на рис. 3 списки смежности имеют следующий вид :
1 - 2,3,4,0
2 - 3,0
3-0
4 - 3,0
Такой список будет представляться в памяти ЭВМ
следующим образом (рис. 7):
2 3 4 0
Массив 1 * * * *
указателей 3 0 Динамические
на входы в
2 * * переменные,
цепочки 3 * 0 состоящие из
целого числа и
4 * 3 0 указателя
*
9
Варианты заданий для лабораторной работы № 1
Вариант 1
0 1 0 0 0 1 0 0 0 1
0 0 0 1 0 0 0 0 1 0
0 0 1 0 1 0 0 0 0 1
0 0 0 0 0 0 0 1 0 0
0 0 0 1 0 0 0 0 0 1
1 1 0 0 0 0 0 0 0 0
0 0 1 0 1 0 0 0 0 0
0 1 0 0 0 0 1 0 0 0
1 0 0 0 0 1 0 1 0 0
0 0 0 0 0 0 1 0 1 0
Вариант 2
0 -1 0 0 0 0 0 1 0 0
0 0 0 2 0 0 0 0 0 0
0 0 0 0 1 0 0 0 -1 0
0 0 1 0 0 -1 0 0 0 0
1 -1 0 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0 -1 0
0 0 0 1 0 0 0 0 0 -1
0 0 -1 0 0 0 0 0 1 0
0 0 0 0 1 0 -1 0 0 0
0 0 0 -1 0 1 0 0 0 0
0 0 0 0 0 -1 1 0 0 0
0 -1 1 0 0 0 0 0 0 0
0 0 0 1 0 0 0 -1 0 0
0 -1 0 0 1 0 0 0 0 0
0 0 -1 1 0 0 0 0 0 0
1 0 0 -1 0 0 0 0 0 0
10
Вариант 3
1 – 2,3,4,7,9,0
2 – 5,6,7,0
3 – 9,10,0
4 – 1,2,0
5 – 1,4,5,0
6–0
7 – 10,7,0
8 – 4,0
9 – 10,0
10 – 4,8,0
Вариант 4
0 1 0 0 0 1 0 0 0 1
0 0 0 1 0 0 0 0 1 0
0 0 0 0 0 0 0 1 0 1
0 0 0 0 0 0 0 1 0 0
0 0 0 1 0 0 0 0 0 1
1 1 0 0 0 1 0 0 0 0
0 0 1 0 0 0 0 0 0 0
0 1 0 0 0 0 1 0 0 0
1 0 0 0 1 1 0 1 0 0
0 0 0 0 0 0 1 0 1 0
Вариант 5
0 -1 0 1 0 0 0 0 0 0
0 0 0 1 0 0 -1 0 0 0
0 0 0 0 1 0 0 0 -1 0
0 0 1 0 0 -1 0 0 0 0
1 -1 0 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0 -1 0
0 0 0 1 0 0 0 0 0 -1
0 0 -1 0 0 0 0 0 1 0
0 0 0 0 1 0 -1 0 0 0
0 0 0 0 0 1 -1 0 0 0
0 0 0 0 0 0 2 0 0 0
0 -1 1 0 0 0 0 0 0 0
0 0 0 1 0 0 0 -1 0 0
0 -1 0 0 1 0 0 0 0 0
0 0 -1 1 0 0 0 0 0 0
1 0 0 -1 0 0 0 0 0 0
11
Вариант 6
1 – 2,3,4,5,9,0
2 – 5,6,7,9,0
3 – 9,2 ,0
4 – 1,2,3,0
5 – 1,4,5,0
6 – 1,0
7 – 10,0
8 – 4,0
9 – 10,3,0
10 – 4,0
Вариант 7
1 1 1 0 0 1 0 0 0 1
0 0 0 0 0 0 0 0 1 0
0 0 0 0 1 0 0 0 0 1
0 0 0 0 0 0 0 1 0 0
0 0 1 1 0 0 0 0 0 0
1 1 0 0 0 0 0 0 0 0
0 0 1 0 1 0 0 0 0 0
0 1 0 0 0 0 1 0 0 0
1 0 0 0 1 1 0 1 0 0
0 0 0 0 0 0 0 0 1 0
Вариант 8
0 0 -1 0 0 0 0 1 0 0
0 -1 0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 -2 0
0 0 1 0 0 -1 0 0 0 0
1 -1 0 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0 -1 0
0 0 0 1 0 0 0 0 0 -1
0 0 -1 0 0 0 0 0 1 0
0 0 0 0 1 0 -1 0 0 0
0 0 0 -1 0 1 0 0 0 0
0 0 0 0 0 -1 1 0 0 0
0 -1 1 0 0 0 0 0 0 0
-1 0 0 1 0 0 0 0 0 0
0 -1 0 0 1 0 0 0 0 0
0 0 -1 1 0 0 0 0 0 0
1 0 0 -1 0 0 0 0 0 0
12
Вариант 9
1 – 3,4,7,9,0
2 – 1,5,6,7,0
3 – 2,,10,0
4 – 1,2,0
5 – 1,4,5,0
6 – 5,0
7 – 10,7,0
8 – 4,0
9 – 10,0
10 – 4,8,0
Вариант 10
0 0 0 0 0 1 1 0 0 1
0 1 0 1 0 0 0 0 1 0
0 0 0 0 1 0 0 0 0 1
0 0 0 0 0 0 0 1 0 0
0 0 0 1 0 0 0 0 0 1
1 1 0 0 0 0 0 0 0 0
0 0 1 0 1 0 0 0 0 0
0 1 0 0 1 0 1 0 0 0
1 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 1 0 1 0
Вариант 11
0 -1 0 0 0 0 0 1 0 0
1 0 0 -1 0 0 0 0 0 0
0 0 0 0 1 0 0 0 -1 0
0 0 1 0 0 -1 0 0 0 0
1 0 0 0 0 -1 0 0 0 0
0 0 0 0 0 1 0 0 -1 0
0 1 0 0 0 0 0 0 0 -1
0 0 -1 0 0 0 0 0 1 0
0 0 0 0 1 0 -1 0 0 0
0 0 0 0 0 2 0 0 0 0
0 0 0 0 0 -1 1 0 0 0
0 -1 1 0 0 0 0 0 0 0
0 0 0 1 0 0 0 -1 0 0
0 -1 0 0 1 0 0 0 0 0
0 0 -1 1 0 0 0 0 0 0
1 0 0 -1 0 0 0 0 0 0
13
Вариант 12
1 – 4,7,9,0
2 – 1,4,5,6,7,0
3–0
4 – 1,2,5,6,0
5 – 1,4,5,0
6–0
7 – 10,7,0
8 – 4,0
9 – 10,1,2,0
10 – 4,8,0
Вариант 13
0 1 0 1 0 1 0 0 0 1
0 0 0 1 0 0 0 0 1 0
0 0 1 0 1 0 0 0 0 1
0 0 0 0 0 0 0 1 0 0
0 0 0 1 0 0 0 0 0 1
1 1 0 1 0 0 0 0 0 0
0 0 1 0 1 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0
1 0 0 0 0 1 0 1 0 0
0 0 0 0 0 0 0 1 1 1
Вариант 14
0 0 0 0 0 0 0 2 0 0
0 0 0 1 0 0 -1 0 0 0
0 0 0 0 1 0 0 0 -1 0
0 0 1 0 0 0 0 -1 0 0
1 -1 0 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0 -1 0
0 0 0 1 0 0 0 0 0 -1
0 0 -1 0 0 0 0 0 0 1
0 0 0 0 1 0 -1 0 0 0
0 1 0 -1 0 0 0 0 0 0
0 0 0 0 0 -1 1 0 0 0
0 -1 1 0 0 0 0 0 0 0
0 0 0 1 0 0 0 -1 0 0
0 -1 0 0 1 0 0 0 0 0
0 0 -1 1 0 0 0 0 0 0
1 0 0 -1 0 0 0 0 0 0
14
Вариант 15
1 – 2,3,4,7,0
2 – 5,6,7,0
3 – 9,10,0
4 – 1,2,0
5 – 1,4,5,0
6 – 2,5,0
7 – 10,7,0
8 – 4,0
9 – 10,0
10 – 4,0
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <locale.h>
//процедуры ввода
void readArray(int *, int, int); //матрицы
node *readList(); //списка смежности
//процедуры вывода
void printArray(int *, int, int); //матрицы
void printList(node *); //списка смежности
15
//процедуры преобразования
//м. инцидентности -> м. смежности
void MI_MS(int *, int *, int, int);
//м. смежности -> список смежности
void MS_SS(int *, int, node **);
//список смежности -> м. инцидентности
void SS_MI(int *, int , node **);
//дополнительные
//подсчёт элементов списка смежности
int countInList(node **, int);
//освобождение памяти для строки из списка
void destroy(node *);
int main()
{
setlocale(0,"Rus");
int choice;
printf("Выберите подходящий вариант:\n");
printf("1 - Перевести из матрицы
инцидентности\n");
printf("2 - Перевести из матрицы смежности\n");
printf("3 - Перевести из списка смежности\n");
printf("0 - Закрыть программу\n");
printf("Ваш выбор: "); scanf("%d", &choice);
switch(choice)
{
case 1: MIin(); break;
case 2: MSin(); break;
case 3: SSin(); break;
default: printf("\t Программа
закрывается...\n"); break;
}
getch();
return 0;
}
//определение функций...
void MIin()
{
int M, N, i, choice;
int *A, *B;
node **arrayOfList;
16
printf("Укажите размеры массива:\n");
printf("M="); scanf("%d", &M);
printf("N="); scanf("%d", &N);
A=(int *)malloc(M*N*sizeof(int));
readArray(A, M, N);
printf("-----------------------------------n");
printf("Ваша матрица инцидентности:\n");
printArray(A, M, N);
printf("----------------------------------\n");
printf("Выберите, в какой форме отобразить:\n");
printf("1 - Перевести в матрицу смежности\n");
printf("2 - Перевести в список смежности\n");
scanf("%d", &choice);
switch(choice)
{
case 1: printf("Перевод в матрицу смежности\n");
B=(int *)calloc(N*N, sizeof(int));
//выделение памяти для МС
MI_MS(A, B, M, N);
//преобразование
printf("\nПолученная матрица смежности:\n");
printf("----------------------------------\n");
printArray(B, N, N);
//вывод полученной матрицы
printf("----------------------------------\n");
free(A);
free(B);
break;
case 2: B=(int *)calloc(N*N, sizeof(int));
//выделение памяти для промежуточной МС
MI_MS(A, B, M, N);
//преобразование
free(A);
printf("Перевод в список смежности\n");
arrayOfList=(node **)malloc(N*sizeof(node *));
//выделение памяти для СС
MS_SS(B, N, arrayOfList);
printf("\nПолученный список смежности:\n");
printf("----------------------------------\n");
for(i=0; i<N; i++)
{
printf("%d:", i+1);
17
printList(*(arrayOfList+i));
}
printf("----------------------------------\n");
free(B);
for(i=0; i<N; i++)
destroy(*(arrayOfList+i));
free(arrayOfList);
break;
default:printf("\nНеверный выбор...\n");
free(A);
}
}
void MSin()
{
int M, N, i, choice;
int *A;
node **arrayOfList;
18
printList(*(arrayOfList+i));
}
free(A);
for(i=0; i<N; i++)
destroy(*(arrayOfList+i));
free(arrayOfList);
break;
сase 2:arrayOfList=(node **)malloc(N*sizeof(node *));
MS_SS(A, N, arrayOfList);
M=countInList(arrayOfList, N);
free(A);
printf("Перевод в матрицу инцидентности\n");
A=(int *)calloc(M*N, sizeof(int));
SS_MI(A, N, arrayOfList);
printf("\nПолученная матрица инцидентности:\n");
printf("----------------------------------------\n");
printArray(A, M, N);
printf("----------------------------------------\n");
free(A);
for(i=0; i<N; i++)
destroy(*(arrayOfList+i));
free(arrayOfList);
break;
default:printf("\nНеверный выбор...\n");
free(A);
}
}
void SSin()
{
int M, N, i, choice;
int *A, *B;
node **arrayOfList;
19
printf("----------------------------------\n");
printf("Список смежности:\n");
for(i=0; i<N; i++)
{
printf("%d:", i+1);
printList(*(arrayOfList+i));
}
printf("----------------------------------\n");
M=countInList(arrayOfList, N);
printf("Выберите, в какой форме отобразить:\n");
printf("1 - Перевод в матрицу инцидентности\n");
printf("2 - Перевод в матрицу смежности\n");
scanf("%d", &choice);
switch(choice)
{
case 1:printf("Перевод в матрицу инцидентности\n");
A=(int *)calloc(M*N, sizeof(int));
SS_MI(A, N, arrayOfList);
printf("\nПолученная матрица инцидентности:");
printf("\n--------------------------------------\n");
printArray(A, M, N);
printf("----------------------------------------\n");
free(A);
for(i=0; i<N; i++)
destroy(*(arrayOfList+i));
free(arrayOfList);
break;
case 2: A=(int *)calloc(M*N, sizeof(int));
SS_MI(A, N, arrayOfList);
for(i=0; i<N; i++)
destroy(*(arrayOfList+i));
free(arrayOfList);
B=(int *)calloc(N*N, sizeof(int));
printf("Перевод в матрицу смежности\n");
MI_MS(A, B, M, N);
printf("\nПолученная матрица смежности:");
printf("\n--------------------------------------\n");
printArray(B, N, N);
printf("----------------------------------------\n");
free(A);
free(B);
break;
20
default:printf("\nНеверный выбор\n");
for(i=0; i<N; i++)
destroy(*(arrayOfList+i));
free(arrayOfList);
}
}
node *readList()
{
int i=0, semn;
int sizeOfNode=sizeof(node);
node *A=NULL, *R1, *R2;
printf("%d : ", ++i); scanf("%d",&semn);
if(semn)
{
R1=(node *)malloc(sizeOfNode);
R1->value=semn; R1->next=NULL;
A=R1;
printf("%d : ", ++i); scanf("%d",&semn);
}
while(semn)
{
R2=(node *)malloc(sizeOfNode);
R2->value=semn; R2->next=NULL;
R1->next=R2; R1=R2;
printf("%d : ", ++i); scanf("%d",&semn);
}
printf("\n");
return A;
}
21
void printArray(int *A, int M, int N)
{
int i, j;
for(i=0; i<M; i++)
{
for(j=0; j<N; j++) printf("%3d", *(A+i*N+j));
printf("\n");
}
}
void printList(node *R)
{
int i=0, semn;
int sizeOfNode=sizeof(node);
while(R)
{
printf("%2d", R->value);
R=R->next;
}
printf("%2d\n", 0);
}
void MI_MS(int *A, int *B, int M, int N)
{
int i, j, a, b;
for(i=0; i<M; i++)
{
for(j=0; j<N; j++)
if(*(A+i*N+j)==2) a=b=j;
else
{
if(*(A+i*N+j)==-1) a=j;
if(*(A+i*N+j)==1) b=j;
}
*(B+a*N+b)=1;
}
}
22
for(i=0; i<N; i++) //найти первую 1 в строке
{
j=0; k=0;
while(!k&&(j<N))
{
if(*(A+i*N+j)) k=j+1;
j++;
}
//k=0 - нет в строке 1, иначе k - номер
//первой 1 в строке (отсчёт с 1)
if(k)
{
R1=(node *)malloc(sizeOfNode);
R1->value=k; R1->next=NULL;
*(arrayOfList+i)=R1;
//продолжаем исследовать строку
while(j<N)
{
if(*(A+i*N+j))
{
R2=(node *)malloc(sizeOfNode);
R2->value=j+1; R2->next=NULL;
R1->next=R2; R1=R2;
}
j++;
}
}
else *(arrayOfList+i)=NULL;
}
}
void SS_MI(int *A, int N, node **arrayOfList)
{
int i, j, k=0;
node *R;
for(i=0; i<N; i++)
{
R=*(arrayOfList+i);
while(R)
{
if((R->value)-1 == i) *(A+k*N+i)=2;
else
{
23
*(A+k*N+i)=-1;
*(A+k*N+(R->value)-1)=1;
}
R=R->next;
k++;
}
}
}
24
Лабораторная работа № 2
Структуры данных:
Списки
Каждый тип списков определяет множество конечных
последовательностей элементов, имеющих заданный базисный
тип. Число элементов списка, называемое его длиной, в разных
списках одного типа может быть различным [1]. Список без
элементов называется пустым списком. Для списка
определены понятия начального, конечного и текущего
элементов, а также следующего и предыдущего элементов по
отношению к текущему. Текущий элемент - это тот
единственный элемент списка, который в данный момент
доступен для обработки.
Очередь
Очередь используется для реализации такой дисциплины
обработки элементов списка, при которой элементы списка
удаляются из него в порядке их включения в список (т.е. по
принципу "Первым пришел - первым ушел") [1].
Набор базисных операций над списками, являющимися
очередями, состоит из четырех операций:
1) создание пустой очереди;
2) проверка очереди на пустоту;
3) выборка первого элемента из очереди с одновременным
его удалением;
4) занесение некоторого значения базисного типа в
качестве нового последнего элемента очереди.
25
Стек
Стек используется для реализации такой дисциплины
обработки элементов списка, при которой элементы списка
удаляются из него в порядке, обратном порядку их занесения
в стек (т.е. по принципу "Последним пришел - первым ушел")
[1].
Набор базисных операций над списками, являющимися
стеками, состоит из пяти операций:
1) создание пустого стека;
2) проверка стека на пустоту;
3) выборка последнего элемента из стека без удаления его
из стека или с его удалением;
5) занесение некоторого значения базисного типа в
качестве нового последнего элемента стека.
Деревья
Над некоторым базисным типом определяют множество
структур, каждая из которых состоит из объекта базисного
типа, называемого вершиной или корнем данного дерева, и
некоторого списка элементов из определяемого множества,
называемых поддеревьями данного дерева. Дерево, в котором
список поддеревьев пуст, называется тривиальным, а корень
тривиального дерева - листом дерева. Корень дерева
называется отцом вершин, являющихся корнями
поддеревьев; а эти вершины называются сыновьями корня
дерева, причем корень первого поддерева является старшим
сыном, а корень каждого следующего поддерева в списке
называется братом корня предыдущего поддерева [1,2].
Набор базисных операций для деревьев состоит из
следующих операций: создание тривиального дерева по
элементу базисного типа и выборки или замены корня дерева
или списка его поддеревьев, а также всех операций (для
списка поддеревьев), которые являются базисными для списка.
26
Обход дерева и графа в глубину
При обходе дерева в глубину (известном также как
прохождение в прямом порядке) вершины дерева
посещаются в соответствии со следующей рекурсивной
процедурой: сначала посетить корень дерева q, затем если
корень рассматриваемого дерева не является листом, то для
каждого сына p корня q рекурсивно обратиться к процедуре
обхода в глубину, для того чтобы обойти все поддеревья с
корнями p в порядке упорядоченности вершин p как сыновей
корня q. Если использовать стек S для хранения текущего
пути по дереву, т.е. пути, который начинается в корне дерева
и заканчивается в вершине, посещаемой в данный момент,
то можно построить нерекурсивный алгоритм для обхода
дерева в глубину [3, 4]:
Посетить корень дерева и поместить его в пустой стек S;
WHILE стек S не является пустым DO
BEGIN
пусть p - вершина, находящаяся на верху стека S;
IF сыновья вершины p еще не посещались
THEN посетить старшего сына вершины p и поместить
его в
стек S
ELSE BEGIN
удалить вершину p из стека S
IF p имеет братьев THEN посетить брата вершины
pи
поместить его в стек S
END
END.
28
В том случае, когда мы имеем дело с произвольным
связанным графом, вершины которого не имеют линейной
упорядоченности, порядок прохода вершин не имеет
значения. Поэтому предлагается другой алгоритм, не
обеспечивающий строгого порядка прохода вершин и более
широко использующий возможности стека, что приводит к
увеличению быстродействия программ, построенных на его
основе. В частности, этот алгоритм в рекурсивном
исполнении широко используется в программах,
выполняющих глобальный поиск по подкаталогам на дисках
(например, в антивирусах).
Поместить в стек исходную вершину графа и пометить ее;
WHILE стек не пуст DO
BEGIN
извлечь вершину из стека;
IF есть непомеченные вершины и смежные с данной
THEN пометить их и загрузить в стек;
END.
Контрольные вопросы
29
Условие задачи для лабораторной работы № 2
30
Лабораторная работа № 3
31
Контрольные вопросы
32
Варианты заданий для лабораторных работ № 2 и №3
Варианты графов
Вариант 1
1 2 3 4 5
6 7 8 9 10
Вариант 2
1 2 3 4 5
6 7 8 9 10
Вариант 3
1 2 3 4 5
6 7 8 9 10
Вариант 4
1 2 3 4 5
6 7 8 9 10
Вариант 5
1 2 3 4 5
6 7 8 9 10
33
Вариант 6
1 2 3 4 5
6 7 8 9 10
Вариант 7
1 2 3 4 5
6 7 8 9 10
Вариант 8
1 2 3 4 5
6 7 8 9 10
Вариант 9
1 2 3 4 5
6 7 8 9 10
Вариант 10
1 2 3 4 5
6 7 8 9 10
Вариант 11
1 2 3 4 5
6 7 8 9 10
Вариант 12
1 2 3 4 5
6 7 8 9 10
34
Вариант 13
1 2 3 4 5
6 7 8 9 10
Вариант 14
1 2 3 4 5
6 7 8 9 10
Вариант 15
1 2 3 4 5
6 7 8 9 10
Варианты деревьев
Вариант 1 1
2 3 4
5 6 7 8 9
10 11 12 13 14 15 16 17
18 19 20 21
35
Вариант 2 1
2 3 4
5 6 7 8 9
10 11 12 13 14 15 16 17
Вариант 3 1 18
2 3 4 19
5 6 7 8 9
10 11 12 13 14 15 16 17
Вариант 4 18 19 1
2 3 4
5 6 7 8 9
10 11 12 13 14 15 16 17
18 19 20 21
36
Вариант 5 1
2 3 4
5 6 7 8 9
10 11 12 13 14 15 16 17
Вариант 6 18 19 1
2 3 4
5 6 7 8 9
10 11 12 13 14 15 16 17
Вариант 7 18 1 19
2 3 4
5 6 7 8 9
10 11 12 13 14 15 16 17
18 19 20 21
37
Вариант 8 1
2 3 4
5 6 7 8 9
10 11 12 13 14 15 16 17
Вариант 9 18 19 1
2 3 4
5 6 7 8 9
10 11 12 13 14 15 16 17
Вариант 10 1 18 19
2 3 4
5 6 7 8 9
10 11 12 13 14 15 16 17
18 19 20 21
38
Вариант 11 1
2 3 4
5 6 7 8 9
10 11 12 13 14 15 16 17
Вариант 12 1 18 19
2 3 4
5 6 7 8 9
10 11 12 13 14 15 16 17
Вариант 13 18 19 1
2 3 4
5 6 7 8 9
10 11 12 13 14 15 16 17
18 19 20 21
39
Вариант 14 1
2 3 4
5 6 7 8 9
10 11 12 13 14 15 16 17
Вариант 15 1 18 19
2 3 4
5 6 7 8 9
10 11 12 13 14 15 16 17
18 19
40
Пример программы для выполнения лабораторных работ
№2 и №3
41
Выбор происходит следующим образом:
Data* toProceadj;
if (k) toProceadj = new Stack;
else toProceadj = new Query;
Дело в том, что в языке С/С++ возможно выделение
памяти под указатель
Data* toProceadj;
Листинг программы
# include <iostream.h>
# include <conio.h>
# include <math.h>
# include <stdio.h>
#include<alloc.h>
struct Data
{ int data[1000];
virtual void Push(int x) {}
virtual int Pop() {}
virtual int isEmpty() {}
};
struct Queue: Data
{ unsigned char q1, q2;
Queue() {q1=q2=0;}
virtual void Push(int x){data[q2++]=x;}
virtual int Pop() {return data[q1++];}
virtual int isEmpty() {return q1==q2;}
};
42
struct Stack: Data
{ unsigned char t;
Stack() {t=0;}
virtual void Push(int x){data[t++]=x;}
virtual int Pop() {return data[--t];}
virtual int isEmpty() {return !t;}
};
struct node{ int v;
node *next;
node(int x, node * t){v=x;next=t; }
};
typedef node *lnk;
lnk adj[100];
void DFS_adj_IVsit(int u){
Data* toProceadj;
if (k) toProceadj = new Stack;
else toProceadj = new Queue;
toProceadj->Push(u);
color[u]=2;
do
{
u = toProceadj->Pop();
printf("%d ",u+1);
lnk tmp = adj[u];
while(tmp){
int v =tmp->v;
if(color[v]==0){
color[v]=2;
toProceadj->Push(v);
}
tmp=tmp->next;
}
} while (!toProceadj->isEmpty());
delete toProceadj;
}
void DFS_adj_Iterative()
{ printf("\nOtvet ");
for(int u=0; u<n; u++)
if(color[u]==0)
DFS_adj_IVsit(u);
printf("\n");
}
43
void FMI()
{
printf("Matritsa Intidentnosti\n ");
for(int i=0;i<m;i++) {
printf("vvedite %d stroku\n", i+1);
for(int j=0;j<n;j++)
scanf("%d",&MI[i][j]);
}
}
void FMS()
{
printf("Matrita Smejnosti\n ");
for(int i=0;i<n;i++){
printf("vvedite %d stroku\n",i+1);
for(int j=0;j<n;j++)
scanf("%d",&MS[i][j]);
}
}
void FSS()
{
int tmp;
printf("Spisok Smejnosti\n ");
for(int i=0;i<n;i++){
printf("vvedit vershinu sviazanui s
%d\n",i+1);
printf( "%d: ",i+1);
scanf("%d",&tmp);
while(tmp){
adj[i]=new node(tmp-
1,adj[i]);
scanf("%d",&tmp);
}
}
}
void FMSvSS()
{
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
if(MS[i][j])
adj[i]=new node(j,adj[i]);
}
44
void FSSvMI()
{ int m=0;
for(int i=0;i<n;i++){
lnk tmp=adj[i];
while(tmp){ MI[m][i]=-1;
MI[m++][tmp->v]=1;
tmp=tmp->next;
}
}
}
void FMIvMS()
{ int i,j,k,l;
for (i=0;i<m;i++){
for (j=0;j<n;j++){
if(MI[i][j]==-1) k=j;
if(MI[i][j]==1) l=j;
}
MS[k][l]=1;
}
}
void printm()
{ printf("Matritsa Intidentnosti\n");
for(int i=0;i<m;i++){
for(int j=0;j<n;j++)
printf("%2d ",MI[i][j]);
printf("\n");
}
printf("Matritsa Smejnosti\n");
for(i=0;i<n;i++){ for(int j=0;j<n;j++)
printf("%2d ",MS[i][j]);
printf("\n");
}
printf("\n\tspisok smeznosti\n");
for(i=1;i<=n;i++){
printf("%d : ",i);
lnk tmp=adj[i-1];
while(tmp){printf("%d ",tmp->v+1);
tmp=tmp->next;
}
printf("0\n");
}
}
45
int main()
{
clrscr();
printf("Vvedi kol-vo ver6in i Dug\n");
scanf("%d%d",&n,&m);
printf("Sposob vvoda\n1.Matritsa
Intidentnosti\n2.Matritsa Smejnosti\n3.Spisok
Smejnosti\n");
scanf("%d",&k);
switch(k){
case 1: FMI() ; FMIvMS(); FMSvSS();
break;
case 2: FMS(); FMSvSS(); FSSvMI();
break;
case 3: FSS(); FSSvMI(); FMIvMS();
break;
}
printm();
printf("vvedite DFS - 1 BFS - 0\n");
scanf("%d",&k);
DFS_adj_Iterative();
return 0;
}
46
ЛИТЕРАТУРА
47
СОДЕРЖАНИЕ
Лабораторная работа № 1
Использование структур данных - двумерных
матриц и связных списков - для различных
способов задания графов............................................................. 3
Лабораторная работа № 2
Использование структур данных для поиска на
деревьях и графах. Алгоритм поиска в глубину....................... 25
Лабораторная работа № 3
Использование структуры данных “очередь” на
примере поиска в ширину для ориентированного
графа.............................................................................................. 31
48