1 2 3 4 5 6 7 8 9 10 11 12 |
//Листинг #a1 Скелет очереди для вставки в очередь целых чисел struct MyFIFO{ int val; //Значение как элемент очереди: оно будет вставляться в очередь int size; //Размер очереди MyFIFO *Head, *Tail, *Next; //Указатели на начало очереди, на конец очереди и на следующий элемент очереди. }; int main(){ return 0; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
//Листинг #1 Пример организации FIFO struct MyFIFO{ int val; int size; MyFIFO *Head,*Tail,*Next; void Add(const int x); //Добавил функцию добавления для очереди }; void MyFIFO::Add(int x){ MyFIFO *temp = new MyFIFO; //Создаем вообще новый элемент temp Next = NULL; //Задаём указателю настоящей очереди, указывающему на следующий элемент, направление на нулевой адрес. (Это не указатель temp->Next, это указатель очереди, обрабатываемой снаружи функции) temp->val = x; //Записываем принятый элемент в temp, точнее в нужную переменную вовнутрь temp if (Head != NULL){ //Проверка на пустоту. Если не пусто Tail->Next = temp; //Записываем, что следующий элемент в хвосте имеет адрес temp Tail = temp; //Перемещаем хвост на свой следующий элемент. Получается, что хвост теперь начинается в последнем созданном temp } else Head = Tail = temp; //Если же очередь пустая, то тогда, адреса начала, конца очереди и первого созданного элемента должны быть одинаковыми } int main(){ return 0; } |
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 |
#include <iostream> //для cout using std::cout; //Листинг #2 FIFO Не кольцевая очередь struct MyFIFO{ int val; int size; MyFIFO *Head, *Tail, *Next; void Add(const int x); void Show(); }; void MyFIFO::Add(int x){ static int count=0; ///////////////////////////////////////////// MyFIFO *temp = new MyFIFO; //Выделяем память новому узлу, каждый новый добавляемый элемент требует выделение себе участка в памяти! Каждое такое выделение даёт нам узел списка. Next = NULL; //Сразу обозначаем, что следующий элемент обрабтываемого сейчас списка не сформирован, делаем это путём указания на нулевой адрес temp->val = x; //Копируем значение x вовнутрь созданного нами сейчас узла списка if (Head != NULL){ Tail->Next = temp; Tail = temp; } else Head = Tail = temp; //////////////////////////////////////////// } void MyFIFO::Show(){ MyFIFO *temp = Head; //Получаем адрес начала очереди while (temp != Tail->Next){ //Пока адрес указателя не совпадет со следующим элементом за хвостом очереди cout << temp->val << "\n"; //Будем выбирать элементы, использя указатель temp temp = temp->Next; //Как только выбрали элемент, переходим по новому адресу к следующему элементу } } int main(){ return 0; } |
Вот и всё. Теперь осталось написать функцию удаления очереди из памяти. Вместе с удалением я буду выводить информацию по удаляемому элементу:
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 |
//Листинг #3 Пример организации FIFO Некольцевая очередь Полный пример #include <iostream> //для cout using std::cout; struct MyFIFO{ int val; int size; MyFIFO *Head, *Tail, *Next; void Add(const int x); void Show(); void Del(); }; void MyFIFO::Add(int x){ static int count=0; ///////////////////////////////////////////// MyFIFO *temp = new MyFIFO; //Выделяем память новому узлу, каждый новый добавляемый элемент требует выделение себе участка в памяти! Каждое такое выделение даёт нам узел списка. Next = NULL; //Сразу обозначаем, что следующий элемент обрабтываемого сейчас списка не сформирован, делаем это путём указания на нулевой адрес temp->val = x; //Копируем значение x вовнутрь созданного нами сейчас узла списка if (Head != NULL){ Tail->Next = temp; Tail = temp; } else Head = Tail = temp; //////////////////////////////////////////// } void MyFIFO::Show(){ MyFIFO *temp = Head; //Получаем адрес начала очереди while (temp != Tail->Next){ //Пока адрес указателя не совпадет со следующим элементом за хвостом очереди cout << temp->val << "\n"; //Будем выбирать элементы, использя указатель temp temp = temp->Next; //Как только выбрали элемент, переходим по новому адресу к следующему элементу } } void MyFIFO::Del(){ MyFIFO *temp = Head; //Создаём указатель, направляем его на начало очереди while (temp != Tail){ temp = Head; //Нашли текущее начало очереди и запомнили адрес в сторонюю переменую Head = Head->Next; //Сместили фактическое начало на адрес следующего поступившего элемента cout << "Udalena swiaz s: " << temp->val << "\n"; //Для наглядности delete temp; //Очистили связь } } int main(){ return 0; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
int main(){ MyFIFO Q1; //Объявили переменную типа нашей очереди FIFO (имя структуры) Q1.Head = NULL; //Обозначили что голова пустая, ибо очередь пуста (можно в конструкторе) Q1.Add(100); //Добавляем элементы Q1.Add(200); Q1.Add(300); Q1.Show(); //Показываем нашу очередь Q1.Del(); //Очищаем память cin.get(); return 0; } |
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 |
//Листинг #3.1 Пример организации FIFO Некольцевая очередь Полный пример #include <iostream> //для cout using std::cout; //Листинг #2 FIFO Не кольцевая очередь struct MyFIFO{ int val; int size; MyFIFO *Head, *Tail, *Next; void Add(const int x); void Show(); void Del(); MyFIFO():Head(NULL), Tail(NULL), Next(NULL){}; //При создании очереди Head, Tail и Next инициализируются нулевым адресом. Это конструктор класса }; void MyFIFO::Add(int x){ static int count=0; ///////////////////////////////////////////// MyFIFO *temp = new MyFIFO; //Выделяем память новому узлу, каждый новый добавляемый элемент требует выделение себе участка в памяти! Каждое такое выделение даёт нам узел списка. Next = NULL; //Сразу обозначаем, что следующий элемент обрабтываемого сейчас списка не сформирован, делаем это путём указания на нулевой адрес temp->val = x; //Копируем значение x вовнутрь созданного нами сейчас узла списка if (Head != NULL){ Tail->Next = temp; Tail = temp; } else Head = Tail = temp; //////////////////////////////////////////// } void MyFIFO::Show(){ MyFIFO *temp = Head; //Получаем адрес начала очереди while (temp != Tail->Next){ //Пока адрес указателя не совпадет со следующим элементом за хвостом очереди cout << temp->val << "\n"; //Будем выбирать элементы, использя указатель temp temp = temp->Next; //Как только выбрали элемент, переходим по новому адресу к следующему элементу } } void MyFIFO::Del(){ MyFIFO *temp = Head; while (temp != Tail){ temp = Head; //Нашли текущее начало очереди и запомнили адрес в сторонюю переменую Head = Head->Next; //Сместили фактическое начало на адрес следующего поступившего элемента cout << "Udalen uzel s: " << temp->val << "\n"; //Для наглядности delete temp; //Зачистили узел } } int main(){ MyFIFO Q1; //Объявили переменную типа нашей очереди FIFO (имя структуры) Q1.Add(100); //Добавляем элементы Q1.Add(200); Q1.Add(300); Q1.Show(); //Показываем нашу очередь Q1.Del(); //Очищаем память return 0; } |
1 |
cout << NULL; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
void MyFIFO::Show(){ if (!Head) { //Если Head != NULL (головной узел не направлен на нулевой адрес), то cout << "Empty list"; //сообщаем о том, что список пуст return; //и выходим из функции ничего не делая } //Иначе функция выполняет, что должна: MyFIFO *temp = Head; //Получаем адрес начала очереди while (temp != Tail->Next){ //Пока адрес указателя не совпадет со следующим элементом за хвостом очереди cout << temp->val << "\n"; //Будем выбирать элементы, использя указатель temp temp = temp->Next; //Как только выбрали элемент, переходим по новому адресу к следующему элементу } } |
А теперь к тому, что есть, сделаем маленький апгрэйд. Из обычной очереди сделаем кольцевую. Для этого хвост должен указывать на начало, а вовнутрь функции приниматься аргумент, который сообщает количество итераций (количество повторений цикла). Весь код абсолютно такой же, за исключением некоторых незначительных поправок:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
//Листинг #b1 Организуем кольцевую очередь FIFO, пишем функцию добавления элемента void MyFIFO::Add(int x){ static int count=0; ///////////////////////////////////////////// MyFIFO *temp = new MyFIFO; Next = temp->Head; temp->val = x; if (Head != NULL){ Tail->Next = temp; Tail = temp; } else Head = Tail = temp; //////////////////////////////////////////// count++; size = count; Tail->Next = Head; //Поправка №1. Из-за нее текущая функция вывода на экран перестанет работать. } |
1 2 3 4 5 6 7 8 9 |
//Листинг #b2 Из-за закольцованности обход выполняется немного иначе чем было показано для некольцевого списка void MyFIFO::Show(const int count){ MyFIFO *temp = Head; //Получаем адрес начала очереди for (int i=0; i<count;i++){ //Обходим по известному числу элементов cout << temp->val << " "; temp = temp->Next; } cout << "\n"; } |
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 |
//Листинг #4 Кольцевой список FIFO #include <iostream> using namespace std; struct MyFIFO{ int val; int size; MyFIFO *Head, *Tail, *Next; void Add(const int x); void Show(const int count); //Изменилась функция Show/ Теперь она принимает параметр void Del(); }; void MyFIFO::Add(int x){ static int count=0; ///////////////////////////////////////////// MyFIFO *temp = new MyFIFO; Next = temp->Head; temp->val= x; if (Head != NULL){ Tail->Next = temp; Tail = temp; } else Head = Tail = temp; //////////////////////////////////////////// count++; size = count; Tail->Next = Head; } void MyFIFO::Show(const int count){ //Появился аргумент (получаемый параметр) if (!Head) { //Если Head != NULL (головной узел не направлен на нулевой адрес), то cout << "Empty list"; //сообщаем о том, что список пуст return; //и выходим из функции ничего не делая } MyFIFO *temp = Head; for (int i=0; i<count; i++){ //Количество итераций будет равно этому аргументу cout << temp->val << " "; temp = temp->Next; } cout << "\n"; } void MyFIFO::Del(){ if (!Head) return; //Если очередь пустая, то удалять нечего //Если не пустая, то организуем удаление int count = 0; MyFIFO *temp = Head; while (temp != Tail){ temp = Head; //Нашли текущее начало очереди и запомнили адрес в сторонюю переменую Head = Head->Next; //Сместили фактическое начало на адрес следующего поступившего элемента cout << "Udalena swiaz s: " << temp->val << "\n"; //Для наглядности delete temp; //Очистили связь } size = 0; //Обозначили, что в очереди ноль элементов } int main(){ MyFIFO Q1; Q1.Head = NULL; Q1.Add(100); Q1.Add(200); Q1.Add(300); Q1.Show(5); //Сама функция вызывается с указанным количеством. сейчас 5, но можно другие значения Q1.Del(); cin.get(); return 0; } |
Долго, очень долго искала информацию в интернете о программировании списков!!! И… вот, наконец-то нашла!!! Спасибо за скрупулезность и доброту! Вы мне очень помогли! Желаю удачи, здоровья, благополучия…
Спасибо автору за статьи, очень нужное дело для начинающих. Обязательно продолжайте писать.
Дополню в Show утечка памяти и ненужное копирование, можно написать так:
void List::Show() //метод отображения списка на экране
{
element *temp=Head; //прыгаем этим указателем к голове списка
while (temp!=NULL) //пока что-то встречается
{
cout<x<Next; //и переходим к следующему элементу
}
}
редактор подвел 🙁
void List::Show() //метод отображения списка на экране
{
element *temp=Head; //прыгаем этим указателем к голове списка
while (temp!=NULL) //пока что-то встречается
{
cout<x<Next; //и переходим к следующему элементу
}
}
Да уж в тэги не взял код. В общем в Show()
element *temp=Head; //прыгаем этим указателем к голове списка
вместо
element *temp=new element; //выделяем память указателю
temp=Head; //прыгаем этим указателем к голове списка
temp->x=Head->x; //присваиваем в x нашего указателя x головы
Благодарю. Исправил.
Спасибо огромное за такую легкоусвояемую информацию)))
а зачем делать постоянное изменение указателя в 13 строке второго примера, Next=temp->Head; там же движение по хвосту все равно только, если не кольцевать то temp->Next=null; я бы еще понял, но вот здесь то зачем
Низачем, да и кроме этого с кодом не всё в порядке: удаление некорректное. Так получилось, что не особо понимал, что к чему, когда писал статью. Буду на предстоящей неделе вспоминать, что к чему, и пробовать исправить свои упущения. Спасибо, что обратили внимание.
Внесены некоторые исправления.
А у вас функция удаления одного элемента есть?То есть сдвигать нго в конец