ВВЕДЕНИЕ
На сегодняшний день всё большее количество людей сталкивается с компьютером, прогресс неумолимо движет нас вперёд. В данное время это обусловлено большими информационными потоками, и необходимо обеспечивать эту отрасль специалистами информационных технологий.
Одно из наиболее мощных свойств языка программирования – указатели. Указатели – одна из наиболее трудных для освоения возможностей С. Указатели предоставляют программам возможность моделировать передачу по ссылке и создавать и манипулировать динамическими структурами данных, т.е. структурами данных, которые могут нарастать и сокращаться, например, такими как связные списки, очереди, стеки и деревья.
Переменные-указатели содержат в качестве своих значений адреса памяти. Обычно переменная содержит определенное значение. С другой стороны, указатель содержит адрес переменной, которая содержит определенное значение. В этом смысле имя переменной отсылает к значению прямо, а указатель – косвенно. Ссылка на значение посредством указателя называется косвенной адресацией.
Указатель – это переменная, содержащая адрес в памяти компьютера. Если удастся осознать смысл этого простого предложения, то это и все, что необходимо знать об указателях. Указатель – это переменная, которая содержит адрес оперативной памяти.
Чтобы лучше понять указатели, рассмотрим устройство оперативной памяти компьютера. Оперативная память разделена на последовательно пронумерованные ячейки. Каждая переменная размещается в одной или нескольких последовательно расположенных отдельных ячейках памяти, адрес первой из них называется адресом переменной. Каждая ячейка в оперативной памяти занимает 1 байт или 8 бит.
ПОСТАНОВКА ЗАДАЧИ
Задание №1:
Описать функцию, которая меняет местами первый и предпоследний элемент непустой очереди.
Входные данные:
Запись{inf}: цел – элементы очереди;
Промежуточные данные:
kol: цел – счетчик(номера элементов очереди);
key: сим – клавиша события;
tmp: сим – временный массив символов;
Ограничения:
нет
Задание №2:
Определить количество изолированных вершин неориентированного графа, вывести их список. Сделать выбранную вершину неизолированной.
Входные данные:
Запись {v1, v2}: цел – 1-я и 2-я вершины одного ребра;
n: цел – общее количество вершин в графе.
Промежуточные данные:
i: цел – счетчик(номера элементов 1-ой очереди);
f: цел – счетчик(проверка на существование висячих вершин);
ch: сим – клавиша события;
s,s1: сим – строки, которые нужны для проверки введенных результатов;
v [10]: сим – показатель степени данной вершины.
Ограничения:
2<=n<=5;
1<=v1<=n;
1<=v2<=n;
v1<>v2.
Выходные данные:
Запись {v1, v2}: цел – граф после удаления одной из висячих вершин.
ОБРАБОТКА СПИСКОВ
Описание структуры списка
Линейный список - это конечная последовательность однотипных элементов (узлов), возможно, с повторениями. Количество элементов в последовательности называется длиной списка, причем длина в процессе работы программы может изменяться. Линейный список F, состоящий из элементов D1,D2,...,Dn, записывают в виде последовательности значений заключенной в угловые скобки F=, или представляют графически (рисунок 2.1).
D1 | | D2 | | D3 | | ... | | Dn |
Рисунок 2.1. - Изображение линейного списка
Например, F1=< 2,3,1>,F2=< 7,7,7,2,1,12 >, F3=< >. Длина списков F1, F2, F3 равна соответственно 3,6,0. В реальных языках программирования нет какой-либо структуры данных для представления линейного списка. Поэтому при работе с линейными списками важным является представление используемых в программе линейных списков таким образом, чтобы была обеспечена максимальная эффективность и по времени выполнения программы, и по объему требуемой памяти. Методы хранения линейных списков разделяются на методы последовательного и связанного хранения. При последовательном хранении элементы линейного списка размещаются в массиве d фиксированных размеров, например, 100, и длина списка указывается в переменной l, т.е. в программе необходимо иметь объявления вида
float d [100] ; int l;
Размер массива 100 ограничивает максимальные размеры линейного списка. Список F в массиве d формируется так:
d [0] =7; d [1] =10; l=2;
Полученный список хранится в памяти согласно схеме на рисунке 2.2.
l: | 2 | ||||||
d: | 7 | 10 | ... | ||||
[0] | [1] | [2] | [3] | [98] | [99] | ||
Рисунок 2.2. – Последовательное хранение линейного списка |
При связанном хранении в качестве элементов хранения используются структуры, связанные по одной из компонент в цепочку, на начало которой (первую структуру) указывает указатель dl. Структура образующая элемент хранения, должна кроме соответствующего элемента списка содержать и указатель на соседний элемент хранения.
Описание структуры и указателя в этом случае может имееть вид:
typedef struct snd /* структура элемента хранения */
{ float val; /* элемент списка */
struct snd *n; /* указатель на элемент хранения */
} DL;
DL *p; /* указатель текущего элемента */
DL *dl; /* указатель на начало списка */
Для выделения памяти под элементы хранения необходимо пользоваться функцией malloc(sizeof(DL)) или calloc(l,sizeof(DL)). Формирование списка в связанном хранении может осуществляется операторами:
p=malloc(sizeof(DL));
p->val=10; p->n=NULL;
dl=malloc(sizeof(DL));
dl->val=7; dl->n=p;
В последнем элементе хранения (конец списка) указатель на соседний элемент имеет значение NULL. Получаемый список изображен на рисунке 2.3.
Рисунок 2.3. – Связное хранение линейного списка
Операции над графами
При связанном хранении каждая вершина графа представляет собой структуру graf, состоящую из двух элементов: v1,v2 - предназначены для хранения вершин графа, next - для указателя на структуру, содержащую следующую вершину графа. На первые элементы графа указывает указатель head. Для всех операций над графом используется описание:
typedef struct graf
{ int v1,v2;
struct graf* next;
} Graf;
Graf *g, *head, *temp;
Для реализации операций могут использоваться следующие фрагменты программ:
1) определить первый элемент в линейном списке (рисунок 3.1):
printf("v1=");
scanf("%d",&head->v1);
head->next=0;
NULL
head NULL
Рисунок 3.3– Создание первого элемента в графе
2) вставить дополнительный элемент после указанного узла (рисунок 3.2):
printf("v=");
scanf("%d",&g->v1);
g->next=head;
head=g;
…. .
head NULL
Рисунок 3.4– Вставка дополнительного элемента
3) печать всех элементов списка:
printf("Ребра графа: \n");
g=head;
i=0;
while(g! =NULL) {
i++;
printf("РЕБРО%d: v1=%d v2=%d\n", i,g->v1,g->v2);
g=g->next; }
4) удаление ребра:
Удалить ребро означает разрушить связь между вершинами, которые являются для данного графа концевыми.
5) удаление вершины:
if((head->v1==i) ||(head->v2==i))
head=head->next;
else{
temp=head;
g=head->next;
while(g) {
if((g->v1==i) ||(g->v2==i)) {
temp->next=g->next;
free(g);
break; }
temp=g;
g=g->next; }}
Удалить вершину означает разрушить связь со смежными ей вершинами и создать новую связь уже без этой вершины. Схема удаления вершины графа, следующей за узлом, на который указывает р находится на рисунке 3.3.
Рисунок 3.5– Схема удаления вершины графа
ВЫВОДЫ
Желание каждого программиста быть востребованным ставит перед ним определенную цель: идти в одну ногу со временем. С каждым годом это делать становиться все сложнее и сложнее, так как за определенные промежутки времени темпы развития компьютерных технологий постоянно увеличиваются. Задача, которую ставит перед собой программист при разработке нового продукта остается неизменной уже на протяжении долгого времени: получение максимального результата при минимуме затрат времени и средств. Выполнение данной задачи становится возможной только при постоянном самосовершенствовании и самообразовании программиста.
Задание, выданное на летнюю практику, поставило определенные задачи:
1) Научится создавать связные структуры данных, используя указатели;
2) научится создавать и манипулировать динамическими структурами данных, такими как связные списки, очереди и стеки;
3) понять работу различных приложений со связными структурами данных.
Решение выданного задания было реализовано с помощью языка программирования С.
С обладает множеством преимуществ. Он является современным языком программирования, включающим в себя управляющие структуры, наличие которых в языке считается желательным с точки зрения теории и практики программирования. Этот язык построен так, что позволяет естественным образом применять планирование сверху – вниз, структурный подход к программированию, модульное проектирование программ. В результате на С получаются более надежные и “прозрачные программы”.
Вот почему именно язык С был выбран автором для реализации данной задачи.
Структуры – это составные типы данных, построенные с использованием других типов. Классы в С++ являются естественным продолжением структуры struct в С. Вот почему детальное изучение этого раздела является таким необходимым для дальнейшего изучения других языков программирования. Так как прежде чем рассматривать специфику разработки классов на С++ нужно более глубоко разобраться со структурами в С.
Приложение А
ЛИСТИНГ ПРОГРАММЫ
Задание №1:
#include<stdio. h>
#include<conio. h>
#include<alloc. h>
#include<string. h>
#include<stdlib. h>
// ------------<Структура>---------
typedef struct sp
{
char inf [100] ;
struct sp *next;
} sp;
sp *g,*head,*teil;
// -----------</Структура>---------
void titl()
{
clrscr();
gotoxy(20,1);
printf("МИHИСТЕРСТВО ОБРАЗОВАHИЯ И HАУКИ УКРАИHЫ");
gotoxy(12,2);
printf("Донецкий государственный институт искусственного интеллекта");
gotoxy(27,8);
printf("Здание на летнюю практику #1");
gotoxy(35,9);
printf("по дисциплине: ");
gotoxy(17,10);
printf("\"Основы программирования и алгоритмические языки. \"");
gotoxy(50,15);
printf("Выполнил: ");
gotoxy(50,16);
printf("студент группы ПО-05г");
gotoxy(50,17);
printf("Пивоваров Артем Генадиевич");
gotoxy(50, 19);
printf("Проверил: ");
gotoxy(50, 20);
printf("асс. Мамбетова Лилия Сергеевна");
gotoxy(2,25);
printf("Для продолжения нажмите любую клавишу... ");
getch();
clrscr();
gotoxy(15,10);
printf("ЗАДАHИЕ: ");
gotoxy(10,12);
printf(" Описать функцию, которая в списке меняет местами");
gotoxy(10,13);
printf("первый и предпоследний элементы. ");
gotoxy(2,25);
printf("Для продолжения нажмите любую клавишу... ");
getch();
}
void program()
{
int kol=1;
char key;
clrscr();
printf("Введите элементы стрруктуры: \n");
head=(sp*) malloc(sizeof(sp));
g=head;
printf("Введите%i-элемент: ",kol);
scanf("%s",&g->inf);
g->next=0;
teil->next=0;
teil=head;
// --------Ввод остальных эл-тов структуры--------------
kol++;
printf("Введите%i-элемент: ",kol);
g=(sp*) malloc(sizeof(sp));
scanf("%s",&g->inf);
g->next=0;
teil->next=g;
teil=teil->next;
do
{
if (key! =27)
{
kol++;
printf("Введите%i-элемент: ",kol);
g=(sp*) malloc(sizeof(sp));
scanf("%s",&g->inf);
g->next=0;
teil->next=g;
teil=teil->next;
}
printf("Для прекращения ввода нажмите ESC; Для продолжения любую клавишу\n");
key=getch();
}
while (key! =27);
printf("Вы ввели такие элементы: \n");
g=head;
kol=0;
while (g! =0)
{
kol++;
printf("Эллемент%i=%s\n",kol,g->inf);
g=g->next;
}
getch();
}
void zamena()
{
char *tmp;
g=head;
while (g->next! =NULL)
{
if (g->next->next==NULL)
{
strcpy(tmp,g->inf);
strcpy(g->inf,head->inf);
strcpy(head->inf,tmp);
}
g=g->next;
}
// --------------Вывод результата----------------
g=head;
int kol=1;
printf("\nРезультат: ");
while (g! =NULL)
{
printf("\n%i-й элемент равен:%s",kol,g->inf);
kol++;
g=g->next;
}
getch();
}
void cleen()
{
g=head;
while (g! =NULL)
{
free(g);
g=g->next;
}
}
void main()
{
titl();
program();
zamena();
cleen();
}
Задание №2:
// --------------------------------Библиотеки--------------------------------
#include <stdio. h>
#include <conio. h>
#include <alloc. h>
#include <string. h>
#include <stdlib. h>
// --------------------------------------------------------------------------
// ===============
char *fname [12] ;
FILE *in,*out;
int n, i,j;
int v [10] ;
char s [6],s1 [6] ;
// ===============
// ***********************************
typedef struct graf
{
int v1,v2;
struct graf *next;
} Graf;
Graf *g,*head;
// ***********************************
// --------------------------------Реквизиты---------------------------------
// --------------------------------------------------------------------------
void tit()
{
clrscr();
gotoxy(20,1);
printf("МИHИСТЕРСТВО ОБРАЗОВАHИЯ И HАУКИ УКРАИHЫ");
gotoxy(12,2);
printf("Донецкий государственный институт искусственного интеллекта");
gotoxy(27,8);
printf("Здание на летнюю практику #2");
gotoxy(35,9);
printf("по дисциплине: ");
gotoxy(17,10);
printf("\"Основы программирования и алгоритмические языки. \"");
gotoxy(50,15);
printf("Выполнил: ");
gotoxy(50,16);
printf("студент группы ПО-05г");
gotoxy(50,17);
printf("Пивоваров Артем Генадиевич");
gotoxy(50, 19);
printf("Проверил: ");
gotoxy(50, 20);
printf("асс. Мамбетова Лилия Сергеевна");
gotoxy(2,25);
printf("Для продолжения нажмите любую клавишу... ");
getch();
return;
}
// --------------------------------------------------------------------------
// --------------------------------Задание-----------------------------------
// --------------------------------------------------------------------------
void work_window()
{
clrscr();
gotoxy(35,1);
printf("ЗАДАHИЕ: ");
gotoxy(12,2);
printf(" Определить количество");
gotoxy(12,3);
printf(" изолированных вершин нориентированного графа,");
gotoxy(12,4);
printf("вывести их список. Сделать выбраную вершину неизолированной! \n");
return;
}
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
// ----------------------Ввод данных с клавиатуры---------------------------
void klava()
{
do
{
printf("\nВведите количество вершин: ");
scanf("%s",&s);
n=atoi(s);
itoa(n,s1,10);
if((n<2) ||(n>5))
printf("Ошибка! Выход из диапазона: '2<n<=5'\n");
}
while((n<2) ||(n>5) ||strcmp(s,s1));
// --------------------------------------------------------------------------
for (i=0; i<n; i++)
v [i] =0;
// --------------------------------------------------------------------------
// --------------------Ввод первого элемента списка--------------------------
// --------------------------------------------------------------------------
printf("Введите ребра графа: \n");
head=(Graf *) malloc(sizeof(Graf));
// ======================================================
do
{
printf("v1=");
scanf("%s",&s);
head->v1=atoi(s);
itoa(head->v1,s1,10);
if (((head->v1) <1) ||((head->v1) >n))
printf("Ошибка! Выход из диапазона: '1<v1<=n'\n");
}
while(((head->v1) <1) ||((head->v1) >n) ||strcmp(s,s1));
// ======================================================
do
{
printf("v2=");
scanf("%s",&s);
head->v2=atoi(s);
itoa(head->v2,s1,10);
if (((head->v2) <1) ||((head->v2) >n))
printf("Ошибка! Выход из диапазона: '1<v2<=n'\n");
}
while(((head->v2) <1) ||((head->v2) >n) ||strcmp(s,s1));
// ======================================================
head->next=NULL;
// --------------------------------------------------------------------------
// -------------------Ввод остальных элементов списка------------------------
// --------------------------------------------------------------------------
char ch=1;
while(ch! =27)
{
printf("Хотите продолжить ввод вершин? \n");
ch=getch();
if (ch! =27)
{
g=(Graf *) malloc(sizeof(Graf));
// ======================================================
do
{
printf("v1=");
scanf("%s",&s);
g->v1=atoi(s);
itoa(g->v1,s1,10);
if (((g->v1) <1) ||((g->v1) >n))
printf("Ошибка! Выход из диапазона: '1<v1<=n'\n");
}
while(((g->v1) <1) ||((g->v1) >n) ||strcmp(s,s1));
// ======================================================
do
{
printf("v2=");
scanf("%s",&s);
g->v2=atoi(s);
itoa(g->v2,s1,10);
if (((g->v2) <1) ||((g->v2) >n))
printf("Ошибка! Выход из диапазона: '1<v2<=n'\n");
}
while(((g->v2) <1) ||((g->v2) >n) ||strcmp(s,s1));
// ======================================================
g->next=head;
head=g;
}
}
}
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
int raschet()
{
printf("Ребра графа: \n");
g=head;
i=0;
while(g! =NULL)
{
i++;
printf("РЕБРО%d: v1=%d v2=%d\n", i,g->v1,g->v2);
g=g->next;
}
// --------------------------------------------------------------------------
// --------------Просмотр графа и поиск изолированых вершин------------------
// --------------------------------------------------------------------------
g=head;
while(g! =NULL)
{
v [g->v1-1] ++;
v [g->v2-1] ++;
g=g->next;
}
int f=0;
for(i=1; i<=n; i++)
printf("v [%d] =%d\n", i,v [i-1]);
printf("Изолированные вершины: ");
for(i=1; i<=n; i++)
if (v [i-1] ==0)
printf("%d ", i);
else
if (v [i-1] ! =0)
f=f+1;
// ********************************************
if (f==n)
{
printf("\nИзолированных вершин HЕТ! ");
// ----------------------------Сохранение в файл------------------------------
i=0;
if ((out=fopen("1. txt", "w")) == NULL)
{
printf("Ошибка открытия входного файла! \n");
return 1;
}
g=head;
while(g! =NULL)
{
i++;
fprintf(out,"Изолированных вершин HЕТ! ");
fprintf(out,"РЕБРО%d: v1=%d v2=%d\n", i,g->v1,g->v2);
g=g->next;
}
fclose(out);
// --------------------------------------------------------------------------
getch();
exit(1);
}
else
// --------------------------------------------------------------------------
// -----------------Добавление вершины в голову списка-----------------------
// --------------------------------------------------------------------------
printf("\nКакую вершину вы хотите сделать не изолированной? \n");
// ======================================================
do
{
printf("Укажите вершину: ");
scanf("%s",&s);
i=atoi(s);
itoa(i,s1,10);
if ((i>n) ||(i<1) ||(v [i-1] ! =0))
printf("Ошибка! \n");
}
while((v [i-1] ! =0) ||strcmp(s,s1) ||(i>n) ||(i<1));
// ======================================================
g=(Graf *) malloc(sizeof(Graf));
g->v1=i;
g->v2=head->v1;
g->next=head;
head=g;
printf("Ребра графа после добавления одного ребра: \n");
g=head;
i=0;
while(g! =NULL)
{
i++;
printf("РЕБРО%d: v1=%d v2=%d\n", i,g->v1,g->v2);
g=g->next;
}
// ********************************************
// ----------------------------Сохранение в файл------------------------------
i=0;
if ((out=fopen("1. txt", "w")) == NULL)
{
printf("Ошибка открытия входного файла! \n");
return 1;
}
g=head;
while(g! =NULL)
{
i++;
fprintf(out," РЕБРО%d: v1=%d v2=%d\n", i,g->v1,g->v2);
g=g->next;
}
fclose(out);
}
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
void main()
{
clrscr();
// ==============
tit();
work_window();
klava();
raschet();
// ==============
getch();
}
ВВЕДЕНИЕ
На сегодняшний день всё большее количество людей сталкивается с компьютером, прогресс неумолимо движет нас вперёд. В данное время это обусловлено большими информационными потоками, и необходимо обеспечивать эту отрасль специалистами информационных технологий.
Одно из наиболее мощных свойств языка программирования – указатели. Указатели – одна из наиболее трудных для освоения возможностей С. Указатели предоставляют программам возможность моделировать передачу по ссылке и создавать и манипулировать динамическими структурами данных, т.е. структурами данных, которые могут нарастать и сокращаться, например, такими как связные списки, очереди, стеки и деревья.
Переменные-указатели содержат в качестве своих значений адреса памяти. Обычно переменная содержит определенное значение. С другой стороны, указатель содержит адрес переменной, которая содержит определенное значение. В этом смысле имя переменной отсылает к значению прямо, а указатель – косвенно. Ссылка на значение посредством указателя называется косвенной адресацией.
Указатель – это переменная, содержащая адрес в памяти компьютера. Если удастся осознать смысл этого простого предложения, то это и все, что необходимо знать об указателях. Указатель – это переменная, которая содержит адрес оперативной памяти.
Чтобы лучше понять указатели, рассмотрим устройство оперативной памяти компьютера. Оперативная память разделена на последовательно пронумерованные ячейки. Каждая переменная размещается в одной или нескольких последовательно расположенных отдельных ячейках памяти, адрес первой из них называется адресом переменной. Каждая ячейка в оперативной памяти занимает 1 байт или 8 бит.
ПОСТАНОВКА ЗАДАЧИ
Задание №1:
Описать функцию, которая меняет местами первый и предпоследний элемент непустой очереди.
Входные данные:
Запись{inf}: цел – элементы очереди;
Промежуточные данные:
kol: цел – счетчик(номера элементов очереди);
key: сим – клавиша события;
tmp: сим – временный массив символов;
Ограничения:
нет
Задание №2:
Определить количество изолированных вершин неориентированного графа, вывести их список. Сделать выбранную вершину неизолированной.
Входные данные:
Запись {v1, v2}: цел – 1-я и 2-я вершины одного ребра;
n: цел – общее количество вершин в графе.
Промежуточные данные:
i: цел – счетчик(номера элементов 1-ой очереди);
f: цел – счетчик(проверка на существование висячих вершин);
ch: сим – клавиша события;
s,s1: сим – строки, которые нужны для проверки введенных результатов;
v [10]: сим – показатель степени данной вершины.
Ограничения:
2<=n<=5;
1<=v1<=n;
1<=v2<=n;
v1<>v2.
Выходные данные:
Запись {v1, v2}: цел – граф после удаления одной из висячих вершин.
ОБРАБОТКА СПИСКОВ
Описание структуры списка
Линейный список - это конечная последовательность однотипных элементов (узлов), возможно, с повторениями. Количество элементов в последовательности называется длиной списка, причем длина в процессе работы программы может изменяться. Линейный список F, состоящий из элементов D1,D2,...,Dn, записывают в виде последовательности значений заключенной в угловые скобки F=, или представляют графически (рисунок 2.1).
D1 | | D2 | | D3 | | ... | | Dn |
Рисунок 2.1. - Изображение линейного списка
Например, F1=< 2,3,1>,F2=< 7,7,7,2,1,12 >, F3=< >. Длина списков F1, F2, F3 равна соответственно 3,6,0. В реальных языках программирования нет какой-либо структуры данных для представления линейного списка. Поэтому при работе с линейными списками важным является представление используемых в программе линейных списков таким образом, чтобы была обеспечена максимальная эффективность и по времени выполнения программы, и по объему требуемой памяти. Методы хранения линейных списков разделяются на методы последовательного и связанного хранения. При последовательном хранении элементы линейного списка размещаются в массиве d фиксированных размеров, например, 100, и длина списка указывается в переменной l, т.е. в программе необходимо иметь объявления вида
float d [100] ; int l;
Размер массива 100 ограничивает максимальные размеры линейного списка. Список F в массиве d формируется так:
d [0] =7; d [1] =10; l=2;
Полученный список хранится в памяти согласно схеме на рисунке 2.2.
l: | 2 | ||||||
d: | 7 | 10 | ... | ||||
[0] | [1] | [2] | [3] | [98] | [99] | ||
Рисунок 2.2. – Последовательное хранение линейного списка |
При связанном хранении в качестве элементов хранения используются структуры, связанные по одной из компонент в цепочку, на начало которой (первую структуру) указывает указатель dl. Структура образующая элемент хранения, должна кроме соответствующего элемента списка содержать и указатель на соседний элемент хранения.
Описание структуры и указателя в этом случае может имееть вид:
typedef struct snd /* структура элемента хранения */
{ float val; /* элемент списка */
struct snd *n; /* указатель на элемент хранения */
} DL;
DL *p; /* указатель текущего элемента */
DL *dl; /* указатель на начало списка */
Для выделения памяти под элементы хранения необходимо пользоваться функцией malloc(sizeof(DL)) или calloc(l,sizeof(DL)). Формирование списка в связанном хранении может осуществляется операторами:
p=malloc(sizeof(DL));
p->val=10; p->n=NULL;
dl=malloc(sizeof(DL));
dl->val=7; dl->n=p;
В последнем элементе хранения (конец списка) указатель на соседний элемент имеет значение NULL. Получаемый список изображен на рисунке 2.3.
Рисунок 2.3. – Связное хранение линейного списка
Операции над элементами списка
При простом связанном хранении каждый элемент списка представляет собой структуру graf, состоящую из двух элементов: v - предназначен для хранения элемента списка, next - для указателя на структуру, содержащую следующий элемент списка. На первый элемент списка указывает указатель head. Для всех операций над списком используется описание:
typedef struct graf
{ int v;
struct graf* next;
} Graf;
Graf *g, *head, *teil;
Для реализации операций могут использоваться следующие фрагменты программ:
1) определить первый элемент в линейном списке (рисунок 2.4):
printf("v=");
scanf("%d",&head->v);
head->next=0;
teil->next=0;
teil=head;
head: NULL
Рисунок 2.4. – Создание первого элемента в списке
2) вставить дополнительный элемент после указанного узла (рисунок 2.5):
printf("v=");
scanf("%d",&g->v);
teil->next=g;
teil=teil->next;
head: NULL
Рисунок 2.5. – Вставка дополнительного элемента
3) печать всех элементов списка:
g=head;
i=0;
while(g! =NULL)
{
i++;
printf("Эллемент%d:%d\n", i,g->v1);
g=g->next;
}
Дата: 2019-07-31, просмотров: 165.