Краткие теоретические сведения
двухсвязаный список
Ниже приведен текст учебной программы работы со связанным списком. Принимая имя файла в качестве параметра командной строки, программа читает содержимое указанного файла и на основе записей формирует двухсвязанный список. Звено списка задается структурой sp. Список распечатывается в прямом и обратном "направлении" и "уничтожается".
#include
<conio.h>
#include <stdio.h>
#include <string.h>
struct sp
{ sp * a_up; // указатель на выше стоящее звено
sp * a_down; // указатель на ниже стоящее звено
char info[81]; // информационная часть звена
};
int main(int argv, char * * argc)
{
int k_zap=0, k;
char z;
char nfile[80], buf[80];
FILE *h;
sp *first, *a_tek, *p, *a_next;
if (argv > 1 ) strcpy(nfile,argc[1]);
else { printf("При вызове программы не указано имя
файла для чтения.....\n"); return -2;};
// инициализация списка.....
first=NULL;
//======
h=fopen(nfile, "r");
if (h == NULL )
{ printf( "Cannot open input file <%s> \n",
nfile); return -1; };
//======
next:
if ( fgets(buf, 80, h) == NULL )
{ printf( "Конец файла <%s> \n", nfile);
goto endd;
};
k=strlen(buf)-1; if (k>=0) buf[k]='\0';
k_zap++;
printf("прочитали %d <%s>\n", k_zap, buf);
// поместить новую запись из buf в список
if (first == NULL )
{
p = new sp; // адрес нового
звена
p->a_up=NULL; // в новом звене
указатели вверх и вниз - пустые
p->a_down=NULL;
p->info[0]='\0'; // в новом
звене инф. строка пустая
strcpy(p->info, buf); // запись
из буфера в инф. строку списка
first=p; //голова списка
printf("first=<%p>\n",first);
printf("<%p><%p><%s>\n",p->a_up,p->a_down,p->info);
}
else
{
// поиск последнего звена (показано для примера, на практике в этом нет
необходимости)
printf("***поиск
последнего звена**\n");
a_tek= first; //
адрес текущего (первого) звена
p = a_tek->a_down;
// адрес "вниз" из текущего звена в указателе p
printf("***текущее
звено <%p><%p><%s>\n",a_tek->a_up, a_tek->a_down, a_tek->info);
printf("***ук. на
след. <%p>\n",p);
while ( p != NULL )
{ a_tek=p;
// адрес следующего звена
p=a_tek->a_down; // адрес "вниз" из текущего звена в указателе p
};
// в a_tek - адрес последнего звена
p = new sp; // адрес
нового звена
printf("tek=<%p>
new=<%p>\n", a_tek, p);
a_tek->a_down = p;
//ссылка вниз в предпоследнем звене
p->a_up= a_tek; //ссылка
вверх в последнем (новом) звене
p->a_down=NULL;
strcpy(p->info, buf);
printf("<%p><%p><%s>\n",p->a_up,p->a_down,p->info);
};
goto next;
endd:
fclose(h);
getchar();
// распечатка списка в прямом направлении ......
clrscr();
a_tek= first;
printf("first=<%p>\n",first);
p = a_tek; // ->a_down;
while ( p != NULL )
{
printf("ADD=<%p> ZVENO=<%p><%p><%s>\n",p, p->a_up,p->a_down,p->info);
getchar();
a_tek= p;
p = a_tek->a_down;
};
getchar();
// поиск последнего звена (показано для примера, на практике в этом нет
необходимости)
printf("***поиск последнего звена**\n");
a_tek= first; // адрес текущего (первого) звена
p = a_tek->a_down; // адрес "вниз" из текущего звена в указателе p
printf("***текущее звено <%p><%p><%s>\n",a_tek->a_up, a_tek->a_down, a_tek->info);
printf("***ук. на след. <%p>\n",p);
while ( p != NULL )
{ a_tek=p; // адрес следующего звена
p=a_tek->a_down; // адрес "вниз" из текущего звена в указателе p
};
// в a_tek - адрес последнего звена
// распечатка списка в обратном направлении
p=a_tek->a_up; // адрес "вверх"
printf("*** последнее зв.<%p><%p><%s>\n",a_tek->a_up, a_tek->a_down, a_tek->info);
printf("***ук. на след. вверх <%p>\n",p);
while ( p != NULL )
{
printf("ADD=<%p> ZVENO=<%p><%p><%s>\n",p, p->a_up,p->a_down,p->info);
getchar();
a_tek= p;
p = a_tek->a_up;
};
getchar();
// удалить список из памяти
// поиск последнего звена
a_tek= first;
p = a_tek->a_down;
while ( p != NULL )
{
a_tek= p;
p = a_tek->a_down;
};
// в a_tek - адрес последнего звена
do
{
// адрес предыдущего звена
a_next=a_tek->a_up;
delete a_tek;
a_tek=a_next;
}
while ( a_tek !=NULL);
printf("усёёёё\n");
return 0;
}