0 / 0 / 0
Регистрация: 07.03.2012
Сообщений: 14
1

Двунаправленные кольцевые списки

18.04.2013, 17:09. Показов 1850. Ответов 6
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте, уважаемые форумчане! Нужна помощь в доработке Двунаправленного кольцевого списка Delphi.
Коды взяти с предыдуших тем Однонаправленные кольцевые списки и Двунаправленный список
Двунаправленный список у меня работает а кольцевой не получается.
Задача мне вот это неясна.
программа должна демонстировать прямой и обратный проход по этому списку?
Вложения
Тип файла: rar двухнаправл.rar (163.8 Кб, 17 просмотров)
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
18.04.2013, 17:09
Ответы с готовыми решениями:

Однонаправленные кольцевые списки
Помогите пожалуйста с кольцевыми списками!!! Нужно написать процедуру которая создает...

списки двунаправленные
Вечер добрый, подскажите пожалуйста правильно ли я задала список? program Spis_dn; type...

Консольное приложение (двунаправленные списки)
Я приложил вордовский файл, там описание задания и код, не получается сделать автоматическую...

Двунаправленные списки
Уважаемые, помогите чем можите. Надо информацию по "двунаправленные списки с заглавным звеном" если...

6
0 / 0 / 0
Регистрация: 07.03.2012
Сообщений: 14
18.04.2013, 23:07  [ТС] 2
люди помогите!
0
13100 / 5881 / 1706
Регистрация: 19.09.2009
Сообщений: 8,808
19.04.2013, 00:31 3
Двунаправленный кольцевой динамический список без головного элемента. Реализовано добавление элементов в начало и в конец списка, проход списка в прямом и обратном направлении, освобождение памяти, занятой под список.
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
program Project1;
 
{$APPTYPE CONSOLE}
 
uses
  SysUtils, Windows;
 
type
  //Тип основных данных списка.
  TData = Integer;
  //Указатель на элемент списка.
  TPElem = ^TElem;
  //Элемент списка.
  TElem = record
    Data : TData; //Основные данные.
    PNext, PPrev : TPElem; //Указатели на следующий и на предыдущий элеметы списка.
  end;
  //Список.
  TDList = record
    Cnt : Integer;   //Количество элементов в списке.
    PFirst : TPElem; //Указатель на первый элемент списка.
  end;
 
//Процедуры для работы с двунаправленным кольцевым списоком.
 
//Процедура начальной инициализации. Внимание! Эту процедуру можно выполнять
//только в отношении пустого списка. Иначе, будут утечки памяти.
procedure Init(var aList : TDList);
begin
  aList.Cnt := 0;
  aList.PFirst := nil;
end;
 
//Освобождение памяти, занятой списком (очистка списка).
procedure ListFree(var aList : TDList);
var
  PElem, PDel : TPElem;
begin
  if aList.PFirst = nil then Exit;
 
  PElem := aList.PFirst;
  repeat
    PDel := PElem;
    PElem := PElem^.PNext;
    Dispose(PDel);
  until PElem = aList.PFirst;
  Init(aList);
end;
 
//Добавление элемента в начало двунаправленного кольцевого списка.
procedure AddF(var aList : TDList; const aData : TData);
var
  PElem : TPElem;
begin
  New(PElem);
  PElem^.Data := aData;
  if aList.PFirst = nil then begin //Если список пуст.
    PElem^.PNext := PElem; //Указатель на самого себя.
    PElem^.PPrev := PElem; //Указатель на самого себя.
  end else begin //Если список не пуст.
    PElem^.PNext := aList.PFirst;
    PElem^.PPrev := aList.PFirst^.PPrev;
    PElem^.PPrev^.PNext := PElem;
    PElem^.PNext^.PPrev := PElem;
  end;
  aList.PFirst := PElem;
  Inc(aList.Cnt);
end;
 
//Добавление элемента в конец двунаправленного кольцевого списка.
//Если список пуст, то новый элемент становится первым элементом списка.
//Если список не пуст, то новый элемент добавляется перед первым элементом списка.
procedure AddL(var aList : TDList; const aData : TData);
var
  PElem : TPElem;
begin
  New(PElem);
  PElem^.Data := aData;
  if aList.PFirst = nil then begin //Если список пуст.
    aList.PFirst := PElem;
    PElem^.PNext := PElem; //Указатель на самого себя.
    PElem^.PPrev := PElem; //Указатель на самого себя.
  end else begin //Если список не пуст.
    PElem^.PNext := aList.PFirst;
    PElem^.PPrev := aList.PFirst^.PPrev;
    PElem^.PPrev^.PNext := PElem;
    PElem^.PNext^.PPrev := PElem;
  end;
  Inc(aList.Cnt);
end;
 
//Диалог для добавления элементов в список.
procedure WorkAdd(var aList : TDList);
var
  S : String;
  Data : TData;
  Code : Integer;
begin
  Writeln('Ввод каждого значения завершайте нажатием Enter.');
  Writeln('Чтобы прекратить ввод, оставьте пустую строку и нажмите Enter.');
  repeat
    Write('Элемент №', aList.Cnt + 1, ': ');
    Readln(S);
    if S <> '' then begin
      Val(S, Data, Code);
      if Code = 0 then
        AddL(aList, Data)
      else
        Writeln('Неверный ввод. Повторите.');
    end;
  until S = '';
  Writeln('Ввод элементов списка завершён.');
end;
 
var
  L : TDList;
  PElem : TPElem;
  i, Cmd : Integer;
begin
  //Переключение окна консоли на кодовую страницу CP1251 (Win-1251).
  //Если после переключения русские буквы показываются неверно,
  //следует открыть системное меню консольного окна - щелчком мыши в левом
  //верхнем углу окна консоли и выбрать:
  //Свойства - закладка "Шрифт" - выбрать шрифт: "Lucida Console".
  SetConsoleCP(1251);
  SetConsoleOutputCP(1251);
 
  //Начальная инициализация списка.
  Init(L);
 
  repeat
    //Меню
    Writeln('Выберите действие:');
    Writeln('1: Добавление элементов в список.');
    Writeln('2: Перебор элементов в прямом направлении.');
    Writeln('3: Перебор элементов в обратном направлении.');
    Writeln('4: Сколько элементов в списке.');
    Writeln('5: Очистка списка.');
    Writeln('6: Выход.');
    Write('Введите команду: ');
    Readln(Cmd);
    case Cmd of
      1: WorkAdd(L);
      2:
        if L.PFirst = nil then
          Writeln('Список пуст')
        else begin
          Writeln('Перебор элементов в прямом направлении:');
          PElem := L.PFirst;
          i := 0;
          repeat
            Inc(i);
            if i > 1 then Write(', ');
            Write(PElem^.Data);
            PElem := PElem^.PNext;
          until PElem = L.PFirst;
          Writeln;
        end;
      3:
        if L.PFirst = nil then
          Writeln('Список пуст')
        else begin
          Writeln('Перебор элементов в обратном направлении:');
          PElem := L.PFirst;
          i := 0;
          repeat
            Inc(i);
            if i > 1 then Write(', ');
            Write(PElem^.Data);
            PElem := PElem^.PPrev;
          until PElem = L.PFirst;
          Writeln;
        end;
      4: Writeln('Количество элементов в списке: ', L.Cnt);
      5, 6:
      begin
        ListFree(L);
        Writeln('Память, занятая списком, освобождена (список очищен).');
      end;
      else
        Writeln('Незарегистрированная команда. Повторите ввод.');
    end;
  until Cmd = 6;
 
  Writeln('Работа программы завершена. Для выхода нажмите Enter.');
  Readln;
end.
Перебор элементов в обратном направлении реализован так:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
        if L.PFirst = nil then
          Writeln('Список пуст')
        else begin
          Writeln('Перебор элементов в обратном направлении:');
          PElem := L.PFirst;
          i := 0;
          repeat
            Inc(i);
            if i > 1 then Write(', ');
            Write(PElem^.Data);
            PElem := PElem^.PPrev;
          until PElem = L.PFirst;
          Writeln;
        end;
При этом, если в списке имеются элементы:
1, 2, 3, 4, 5
то в обратном направлении эти элементы будут распечатаны так:
1, 5, 4, 3, 2
Так и должно быть - потому что переменная списка указывает на элемент со значением 1.
Если надо, чтобы распечатка прошла по правилу "от конца - к началу", то код перебора следует оформить так:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
        if L.PFirst = nil then
          Writeln('Список пуст')
        else begin
          Writeln('Перебор элементов в обратном направлении:');
          PElem := L.PFirst;
          i := 0;
          repeat
            Inc(i);
            if i > 1 then Write(', ');
            PElem := PElem^.PPrev;
            Write(PElem^.Data);
          until PElem = L.PFirst;
          Writeln;
        end;
0
0 / 0 / 0
Регистрация: 07.03.2012
Сообщений: 14
19.04.2013, 08:48  [ТС] 4
а продемонстрировать в вашем коде можно обход кольцевого списка с распечаткой как это сделано в этой теме Однонаправленные кольцевые списки
0
13100 / 5881 / 1706
Регистрация: 19.09.2009
Сообщений: 8,808
19.04.2013, 09:48 5
Здесь это реализовано - перебор элементов в прямом и обратном направлении. При этом выполняется распечатка элементов:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
      2:
        if L.PFirst = nil then
          Writeln('Список пуст')
        else begin
          Writeln('Перебор элементов в прямом направлении:');
          PElem := L.PFirst;
          i := 0;
          repeat
            Inc(i);
            if i > 1 then Write(', ');
            Write(PElem^.Data);
            PElem := PElem^.PNext;
          until PElem = L.PFirst;
          Writeln;
        end;
      3:
        if L.PFirst = nil then
          Writeln('Список пуст')
        else begin
          Writeln('Перебор элементов в обратном направлении:');
          PElem := L.PFirst;
          i := 0;
          repeat
            Inc(i);
            if i > 1 then Write(', ');
            Write(PElem^.Data);
            PElem := PElem^.PPrev;
          until PElem = L.PFirst;
          Writeln;
        end;
1
0 / 0 / 0
Регистрация: 07.03.2012
Сообщений: 14
19.04.2013, 09:53  [ТС] 6
Огромное спасибо!!
0
13100 / 5881 / 1706
Регистрация: 19.09.2009
Сообщений: 8,808
19.04.2013, 10:11 7
Здесь, на всякий случай обращу внимание на перебор элементов в обратном направлении.
Предположим в списке у нас 5 элементов: 1, 2, 3, 4, 5.
Если перебор реализован так:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
        if L.PFirst = nil then
          Writeln('Список пуст')
        else begin
          Writeln('Перебор элементов в обратном направлении:');
          PElem := L.PFirst;
          i := 0;
          repeat
            Inc(i);
            if i > 1 then Write(', ');
            Write(PElem^.Data);
            PElem := PElem^.PPrev;
          until PElem = L.PFirst;
          Writeln;
        end;
То элементы будут распечатаны так:
1, 5, 4, 3, 2
Здесь всё правильно - потому что указатель списка указывает на элемент со значением 1.
А если перебор реализован таким образом:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
        if L.PFirst = nil then
          Writeln('Список пуст')
        else begin
          Writeln('Перебор элементов в обратном направлении:');
          PElem := L.PFirst;
          i := 0;
          repeat
            Inc(i);
            if i > 1 then Write(', ');
            PElem := PElem^.PPrev;
            Write(PElem^.Data);
          until PElem = L.PFirst;
          Writeln;
        end;
То элементы будут распечатаны так:
5, 4, 3, 2, 1.
Это тоже правильно, но правило распечатки здесь немного другое - "от конца - к началу".
1
19.04.2013, 10:11
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
19.04.2013, 10:11
Помогаю со студенческими работами здесь

Кольцевые списки
Зачем нужны кольцевые односвязные и двусвязные списки? Когда они могут понадобиться? Ведь, если...

Кольцевые списки
Здравствуйте, как реализовать удаление в кольцевом списке ? Читал, что можно сделать так, чтобы при...

Кольцевые списки
люди добрые, написал программу, теперь надо в ней сделать эти три списка в один кольцевой, но при...

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

Кольцевые списки на базе двунаправленных списков
Всем привет! Помогите решить задачу: Пусть L обозначает кольцевой двунаправленный список с...

Двунаправленные списки
Всем привет! На форуме нашел мануал по работе со списками, но как то не проникся идеей. Помогите...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2023, CyberForum.ru