Форум программистов, компьютерный форум, киберфорум
PascalABC.NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.57/7: Рейтинг темы: голосов - 7, средняя оценка - 4.57
5 / 4 / 3
Регистрация: 18.08.2019
Сообщений: 108

Как работать с очередями? Не могу понять

14.03.2021, 07:48. Показов 2258. Ответов 1
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем привет.
Есть задание, где нужно сформировать две очереди с элементами - фамилиями. Затем нужно удалить из второй очереди все фамилии, которые встречаются в первой.

Я написал (скопировал все процедуры с методички) код, но не понимаю в чем ошибка. В определенный момент программа работает не правильно и я уже 5 часов не могу понять в чем проблема.
Вот скриншот неправильной работы программы (не выводит фамилию Цветков во второй очереди):
Кликните здесь для просмотра всего текста


Я понимаю, что такое очередь в программировании и как она в теории должна работать.
Кликните здесь для просмотра всего текста
Первый зашел, первый вышел. Можно обратиться к началу или концу очереди. Не можем перебрать все элементы, вставить убрать эл. в середину и т.д. Добавление нового элемента только в конец очереди
Но на практике я вообще не понимаю что и как.
Буду очень благодарен, если вы объясните на примерах кода как работают очереди и как их использовать.

Вот весь код:
Pascal
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
program queue;
 
const
  n = 3;
 
type
  pnode = ^node;
  node = record { элемент очереди }
    d: word;
    s: string;
    p: pnode;     //сюда идёт адрес следующего элемента
  end;
 
var
  beg1, fin1,beg2,fin2: pnode; { указатели на начало и конец очереди }
  i: word;
  s: string;
 
{const 
  text: array [1..n] of string = ('one', 'two', 'three', 'four', 'five');}
  
  
{ начальное формирование очереди}
procedure first(var beg, fin: pnode; d: word; const s: string);
begin
  new(beg);
  beg^.d := d;
  beg^.s := s; 
  beg^.p := nil;   //адрес следующего элемента - пуст (неизвестен)
  fin := beg;      //последний элемент = начальный
end;
{добавление элемента в конец}
procedure add(var fin: pnode; d: word; const s: string);
var
  p: pnode;
begin
  new(p);
  p^.d := d; 
  p^.s := s; 
  p^.p := nil; //адрес следующего элемента очереди = 0 (пуст (неизвестен))
  fin^.p := p; //присвоение последнему элементу  адреса следующего p (нового) элемента очереди
  fin := p;    //последний элемент очереди = новому p элементу очереди
end;
{ выборка элемента из начала}
procedure get(var beg: pnode; var d: word; var s: string);
var
  p: pnode;
begin
  d := beg^.d; 
  s := beg^.s;
  p := beg; 
  beg := beg^.p;        //начальный элемент очереди = следующий элемент очереди 
end;
 
procedure get2(var beg: pnode; var d: word; var s: string);
var
  p: pnode;
begin
  d := beg^.d; 
  s := beg^.s;  
  p := beg; 
  beg := beg^.p;        //начальный элемент очереди = следующий элемент очереди
  dispose(p);           //удаление p (текущего) элемента из очереди
end;
 
{главная программа}
begin
  var fam:='';
  writeln('Фамилии клиентов - 1-ая очередь');
  { занесение в очередь 1: }
  i:=1;
  while (fam<>'.') and (i<=n) do
  begin
    fam:=ReadString();
    if i=1 then
      first(beg1,fin1,i,fam)
    else
      add(fin1,i,fam);
   // write(a,'; ')
   
    Inc(i);
  end;
  writeln();
  
  writeln('Фамилии клиентов - 2-ая очередь');
  
  { занесение в очередь 2: }
  i:=1;
  while (fam<>'.') and (i<=n) do
  begin
    fam:=ReadString();
    if i=1 then
      first(beg2,fin2,i,fam)
    else
      add(fin2,i,fam);
   // write(a,'; ')
   
    Inc(i);
  end;  
  
  var adrBeg1:=beg1;
  var adrBeg2:=beg2;
  
  var eqFam:=0;         //количество повторяющихся фамилий
  
  while beg1 <> nil do
  begin
    get(beg1,i,fam);
    var famtemp:=fam;
    while beg2 <> nil do 
    begin
      var temBeg2:=beg2;
      get(beg2,i,fam);
 
      if famtemp=fam then
      begin
        inc(eqFam);
        dispose(temBeg2);
      end;
      if beg2=nil then
        break;
 
    end;
    if (adrBeg2<>nil) and (eqFam<>i) then
    begin
      beg2:=adrBeg2
    end;
    
  end;
  
  beg1:=adrBeg1;
  writeln();
  writeln('Первая очередь: ');
  while beg1 <> nil do
  begin
    get2(beg1,i,fam);
    write(fam,'; ');
  end;
  writeln();
  writeln();
  if beg2=nil then
    writeln('Все фамилии из 2-ой очереди совпадают с фамилиями из 1-ой очереди ')
  else
  begin
    writeln('Вторая очередь: ');
    while beg2 <> nil do
    begin
      get2(beg2,i,fam);
      write(fam,'; ');
    end;
   writeln();
  end;
 dispose(adrBeg1);
 dispose(adrBeg2);
end.


p.s. пожалуйста без шуток про очереди (да, да заголовок темы выглядит смешно, я знаю)...
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
14.03.2021, 07:48
Ответы с готовыми решениями:

Не могу понять, как работать с графикой
Есть примитивная программа. Создаётся Frame, в нём создаётся Panel, далее в методе paintComponent рисуется линия. Как теперь человеческими...

Не могу понять как работать с событиями
Здравствуйте. Подскажите пожалуйста такую вещь: У меня при нажатии на кнопку выбора файла , появляется лэйбл на форме и после выбора файла...

Не могу понять, как должна работать модель
Не могу понять алгоритм работы модели, кто может, подскажите как данная модель должна функционировать. Что это за терминалы, где...

1
 Аватар для JuriiMW
5095 / 2661 / 2355
Регистрация: 10.12.2014
Сообщений: 10,060
14.03.2021, 09:26
Лучший ответ Сообщение было отмечено pahom6233 как решение

Решение

Очередь — это по сути одно- или двунаправленный динамический список.
Следовательно можно создать саму очередь так:
Pascal
1
2
3
4
type
  типОчередь = class
    первый, последний : элементОчереди;
  end;
Элементы очереди у нас будут:
Pascal
1
2
3
4
5
type
  элементОчереди = class
    фамилия : String;
    предыущий, следующий : элементОчереди;
  end;
(Зачем там у вас в очереди d я так и не понял. Если порядковый номер, то его нужно при любом изменении очереди изменять…)

Теперь нужно инициализировать очередь:
Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
type
  элементОчереди = class
    фамилия : String;
    предыущий, следующий : элементОчереди;
  end;
 
type
  типОчередь = class
    первый, последний : элементОчереди;
    
    constructor;
    begin
      первый := nil;
      последний := nil;
    end;
  end;
  
begin
  var очередь1 := New типОчередь;
  if очередь1.первый = nil then 'Очередь пуста!'.Println;
end.
Добавление элемента в хвост очереди:
Pascal
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
type
  элементОчереди = class
    фамилия : String;
    предыущий, следующий : элементОчереди;
    
    constructor (фамилия : String);
    begin
      self.фамилия   := фамилия;
      self.предыущий := nil;
      self.следующий := nil;
    end;
  end;
 
type
  типОчередь = class
    первый, последний : элементОчереди;
    
    constructor;
    begin
      первый := nil;
      последний := nil;
    end;
    
    procedure добавить(фамилия : String);
    begin
      var новый := New элементОчереди(фамилия);
      if первый = nil then
        первый := новый
      else
        последний.следующий := новый;
      новый.предыущий := последний;
      последний := новый;
    end;
    
    procedure вывести(msg : String := '');
    begin
      if msg <> '' then msg.Println;
      var текущий := первый;
      if текущий = nil then
        'Очередь пуста!'.Println
      else
        repeat
          текущий.фамилия.Println;
          текущий := текущий.следующий;
        until текущий = nil;
    end;
    
  end;
  
begin
  var очередь1 := New типОчередь;
  очередь1.вывести;
  ('~'*20).Println;
  очередь1.добавить('Иванов');
  очередь1.вывести('первая очередь:');
  ('~'*20).Println;
  очередь1.добавить('Петров');
  очередь1.добавить('Сидоров');
  очередь1.вывести('первая очередь:');
end.
За одно и вывод очереди добавили в метод, чтобы больше не возвращаться…
Создание очереди можно сделать из строки с разделителями:
Pascal
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
type
  элементОчереди = class
    фамилия : String;
    предыущий, следующий : элементОчереди;
    
    constructor (фамилия : String);
    begin
      self.фамилия   := фамилия;
      self.предыущий := nil;
      self.следующий := nil;
    end;
  end;
 
type
  типОчередь = class
    первый, последний : элементОчереди;
    
    constructor;
    begin
      первый := nil;
      последний := nil;
    end;
    
    /// список через точку с запятой
    constructor (s : String);
    begin
      первый := nil;
      последний := nil;
      foreach var фамилия in s.ToWords(';').Select(f->f.Trim) do
        if фамилия <> '' then
          добавить(фамилия);
    end;
    
    procedure добавить(фамилия : String);
    begin
      var новый := New элементОчереди(фамилия);
      if первый = nil then
        первый := новый
      else
        последний.следующий := новый;
      новый.предыущий := последний;
      последний := новый;
    end;
    
    procedure вывести(msg : String := '');
    begin
      if msg <> '' then msg.Println;
      var текущий := первый;
      if текущий = nil then
        'Очередь пуста!'.Print
      else
        repeat
          (текущий.фамилия+';').Print;
          текущий := текущий.следующий;
        until текущий = nil;
      Println;
    end;
    
  end;
  
begin
  var очередь1 := New типОчередь('Иванов; Петров; Сидоров');
  очередь1.вывести('первая очередь:');
  ('~'*20).Println;
  var очередь2 := New типОчередь('Петров; Сидоров; Цветков');
  очередь1.вывести('вторая очередь:');
end.
Теперь нам понадобится метод удаления заданной строки из списка:
Pascal
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
type
  элементОчереди = class
    фамилия : String;
    предыущий, следующий : элементОчереди;
    
    constructor (фамилия : String);
    begin
      self.фамилия   := фамилия;
      self.предыущий := nil;
      self.следующий := nil;
    end;
  end;
 
type
  типОчередь = class
    первый, последний : элементОчереди;
    
    constructor;
    begin
      первый := nil;
      последний := nil;
    end;
    
    /// список через точку с запятой
    constructor (s : String);
    begin
      первый := nil;
      последний := nil;
      foreach var фамилия in s.ToWords(';').Select(f->f.Trim) do
        if фамилия <> '' then
          добавить(фамилия);
    end;
    
    procedure добавить(фамилия : String);
    begin
      var новый := New элементОчереди(фамилия);
      if первый = nil then
        первый := новый
      else
        последний.следующий := новый;
      новый.предыущий := последний;
      последний := новый;
    end;
    
    procedure вывести(msg : String := '');
    begin
      if msg <> '' then msg.Println;
      var текущий := первый;
      if текущий = nil then
        'Очередь пуста!'.Print
      else
        repeat
          (текущий.фамилия+';').Print;
          текущий := текущий.следующий;
        until текущий = nil;
      Println;
    end;
    
    procedure удалить(фамилия : String);
    begin
      // обработка головы списка
      while (первый <> nil) and (первый.фамилия = фамилия) do
        begin
          первый := первый.следующий;
          if первый <> nil then
            первый.предыущий := nil;
        end;
      // обработка следующих элементов
      var текущий := первый.следующий;
      while текущий <> nil do
        if текущий.фамилия = фамилия then
          begin
            var предыдущий := текущий.предыущий;
            текущий := текущий.следующий;
            предыдущий.следующий := текущий;
            if текущий <> nil then
              текущий.предыущий := предыдущий;
          end
        else
          текущий := текущий.следующий;
    end;
    
  end;
  
begin
  var очередь1 := New типОчередь('Иванов; Петров; Сидоров');
  очередь1.вывести('первая очередь:');
  ('~'*20).Println;
  очередь1.удалить('Петров');
  очередь1.вывести('первая очередь:');
end.
Ближе к условию задачи:
Pascal
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
type
  элементОчереди = class
    фамилия : String;
    предыущий, следующий : элементОчереди;
    
    constructor (фамилия : String);
    begin
      self.фамилия   := фамилия;
      self.предыущий := nil;
      self.следующий := nil;
    end;
  end;
 
type
  типОчередь = class
    первый, последний : элементОчереди;
    
    constructor;
    begin
      первый := nil;
      последний := nil;
    end;
    
    /// список через точку с запятой
    constructor (s : String);
    begin
      первый := nil;
      последний := nil;
      foreach var фамилия in s.ToWords(';').Select(f->f.Trim) do
        if фамилия <> '' then
          добавить(фамилия);
    end;
    
    procedure добавить(фамилия : String);
    begin
      var новый := New элементОчереди(фамилия);
      if первый = nil then
        первый := новый
      else
        последний.следующий := новый;
      новый.предыущий := последний;
      последний := новый;
    end;
    
    procedure вывести(msg : String := '');
    begin
      if msg <> '' then msg.Println;
      var текущий := первый;
      if текущий = nil then
        'Очередь пуста!'.Print
      else
        repeat
          (текущий.фамилия+';').Print;
          текущий := текущий.следующий;
        until текущий = nil;
      Println;
    end;
    
    procedure удалить(фамилия : String);
    begin
      // обработка головы списка
      while (первый <> nil) and (первый.фамилия = фамилия) do
        begin
          первый := первый.следующий;
          if первый <> nil then
            первый.предыущий := nil;
        end;
      // обработка следующих элементов
      var текущий := первый.следующий;
      while текущий <> nil do
        if текущий.фамилия = фамилия then
          begin
            var предыдущий := текущий.предыущий;
            текущий := текущий.следующий;
            предыдущий.следующий := текущий;
            if текущий <> nil then
              текущий.предыущий := предыдущий;
          end
        else
          текущий := текущий.следующий;
    end;
    
  end;
  
begin
  var очередь1 := New типОчередь('Иванов; Петров; Сидоров');
  очередь1.вывести('первая очередь:');
  ('~'*20).Println;
  var очередь2 := New типОчередь('Петров; Сидоров; Цветков');
  очередь2.вывести('вторая очередь:');
  ('~'*20).Println;
  var текущий := очередь1.первый;
  while текущий <> nil do
    begin
      очередь2.удалить(текущий.фамилия);
      текущий := текущий.следующий;
    end;
  очередь2.вывести('вторая очередь:');
end.
Всё!
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
14.03.2021, 09:26
Помогаю со студенческими работами здесь

TStyleManager, не могу понять как работать с ним
Ребята! Помогите! Хочу сделать программу покрасивее, но я не могу понять как работать с ним. Класс создаю. Пишет ошибку: Undeclared...

Не могу понять как работать с данным массивом
Добрый день форумчане! Имеется массив ...

длинная арифметика, не могу понять как с ней работать
необходимо написать программу которая могла бы найти остаток от деления, но проблема в том что числа могут быть до 10 в 100 степени. как...

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

Не могу понять как в Visual Studio (C#) работать с "ресурсами"
Начал программировать на C#, установил Visual Studio и встретил там такую графу как &quot;ресурсы&quot;.И у меня возник вопрос как с ними...


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

Или воспользуйтесь поиском по форуму:
2
Ответ Создать тему
Новые блоги и статьи
SDL3 для Desktop (MinGW): Рисуем цветные прямоугольники с помощью рисовальщика SDL3 на Си и C++
8Observer8 17.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-rectangles-sdl3-c. zip finish-rectangles-sdl3-cpp. zip
Символические и жёсткие ссылки в Linux.
algri14 15.03.2026
Существует два типа ссылок — символические и жёсткие. Ссылка в Linux — это запись в каталоге, которая может указывать либо на inode «файла-ИСТОЧНИКА», тогда это будет «жёсткая ссылка» (hard link),. . .
[Owen Logic] Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора
ФедосеевПавел 14.03.2026
Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора ВВЕДЕНИЕ Выполняя задание на управление насосной группой заполнения резервуара,. . .
делаю науч статью по влиянию грибов на сукцессию
anaschu 13.03.2026
прикрепляю статью
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru