რიგი (FIFO) და დეკი

საბეჭდი დავალებები, ვებმოთხოვნები, სერვისებს შორის შეტყობინებები: ყველაფერი, რაც მოსვლის რიგით უნდა დამუშავდეს, რიგში ელოდება. ის სიგანეში ძებნის (BFS) ძრავიცაა, ამიტომ გრაფების ყოველ გაკვეთილში შეგხვდება.

დამწყები⏱ 8 წთ
01

ისწავლე

იდეა, მექანიზმი და ფასი.

01პირველი მოვიდა, პირველი წავიდა

რიგი მაღაზიის სალაროსთან მდგარი ხალხია. ახალი ელემენტები ბოლოში დგება, გადის კი სათავიდან. ვინც ყველაზე დიდხანს ელოდა, პირველი ემსახურება: „პირველი მოვიდა, პირველი წავიდა“ (FIFO).

C++-ში: #include <queue> და queue<int> q;. ფუნქციები სტეკისას ჰგავს:

  • push(x): x-ის დამატება ბოლოში;
  • pop(): სათავის ელემენტის წაშლა (არაფერს აბრუნებს);
  • front() / back(): უძველესი / უახლესი ელემენტის წაკითხვა;
  • size(), empty().

ყველა O(1)-ია. როგორც სტეკში, ცარიელ რიგზე front() ან pop() განუსაზღვრელი ქცევაა.

FIFO: პირველი მოვიდა, პირველი წავიდა372229pop() / front()push(16)სათავე (front)ბოლო (back)

02იგივე ბრძანებები, საპირისპირო პასუხი

სტეკის ლექციის პროგრამა რიგზე გავუშვათ: push 37, 22, 29, შემდეგ pop(). სტეკი წაშლიდა 29-ს, უახლესს. რიგი შლის 37-ს, უძველესს, და front() ახლა 22-ს აჩვენებს.

ეს ერთი განსხვავება წყვეტს, რომელი სტრუქტურა სჭირდება ალგორითმს:

  • სტეკი ჯერ სიღრმეში მიდის: უახლესი დავალება პირველი სრულდება (სიღრმეში ძებნა, გაუქმება, რეკურსია);
  • რიგი ჯერ სიგანეში მიდის: დავალებები გამოჩენის რიგით სრულდება (სიგანეში ძებნა, დაგეგმვა, ბუფერიზაცია).

BFS-ში რიგი ინახავს აღმოჩენილ, მაგრამ ჯერ დაუმუშავებელ წვეროებს. რადგან ისინი მოსვლის რიგით გამოდიან, წვეროები შრეებად მუშავდება, სწორედ ამიტომ პოულობს BFS უწონო გრაფში უმოკლეს გზებს.

push 37, 22, 29სტეკი: pop() იღებს უახლესს37222929რიგი: pop() იღებს უძველესს37222937

03დეკი: ორივე ბოლო ერთდროულად

დეკი (ორბოლოიანი რიგი, #include <deque>) იძლევა push_front, push_back, pop_front და pop_back ოპერაციებს, ყველას O(1)-ში, და ინდექსით წვდომასაც d[i]. მას შეუძლია იყოს სტეკი, რიგი ან ორივე ერთად.

ორი კლასიკური გამოყენება:

  • მცოცავი ფანჯრის მინიმუმი: დეკში ინდექსები ზრდადი მნიშვნელობებით ინახება; სათავეს ვაგდებთ, როცა ფანჯრიდან გადის, ბოლოს კი ვაგდებთ, სანამ ახალ ელემენტზე მეტია. ეს მონოტონური სტეკია, რომელსაც მეორე ბოლოშიც აქვს გასასვლელი.
  • 0-1 BFS: გრაფებში, სადაც წიბოების წონა 0 ან 1-ია, 0-წიბოსთვის წვეროს წინ ვდებთ, 1-წიბოსთვის კი ბოლოში.

შიგნიდან std::queue და std::stack ნაგულისხმევად დეკზე აგებული თხელი გარსებია.

deque: ორივე ბოლოში ჩამატება და ამოღება, O(1)5381push_frontpop_frontpush_backpop_backგამოყენება: მცოცავი ფანჯრის მინიმუმი, 0-1 BFS

ფასი ერთი შეხედვით

push / pop / front / backO(1)
დეკი ნებისმიერ ბოლოშიO(1)
შიგნით ძებნაO(n)

დაიმახსოვრე

  1. რიგი ბოლოში ამატებს და სათავიდან შლის, ამიტომ ელემენტები მოსვლის რიგით გადიან.
  2. სტეკი უახლეს ელემენტს ამუშავებს პირველად (სიღრმე), რიგი უძველესს (სიგანე); სწორედ ესაა DFS-სა და BFS-ს შორის განსხვავება.
  3. დეკი ორივე ბოლოში O(1) ჩამატებასა და წაშლას უზრუნველყოფს და მცოცავი ფანჯრისა და 0-1 BFS-ის ხრიკებს ემსახურება.
02

ითამაშე

გაიარე ალგორითმი ბიჯ-ბიჯ, მერე სცადე შენს მონაცემებზე.

👀 რას უყურო: შეადარე სტეკის გაკვეთილს: იგივე ბრძანებებია, მაგრამ pop ახლა 37-ს შლის, უძველეს ელემენტს. სცადე საკუთარი ბრძანებები, back-ის ჩათვლით.

ინტერაქტიული ვიზუალიზატორიაქ დააწკაპე, მერე space ← →
✎ შენი მონაცემები14 ბრძანებამდე: push N (ან უბრალოდ N), pop, front, back, size, empty.

რიგი q (FIFO: „პირველი მოვიდა, პირველი წავიდა“)

(ცარიელია)
გამოტანილი (cout)
რიგი არის „პირველი მოვიდა, პირველი წავიდა“: ბოლოში ამატებ, სათავიდან იღებ. სტეკის სარკისებრი ანარეკლი.

ფსევდოკოდი

 1 queue<int> q; 2 q.push(x);    // join at the BACK 3 q.pop();      // leave from the FRONT 4 q.front();    // read the oldest element 5 q.back();     // read the newest element 6 q.size();     // how many are waiting 7 q.empty();    // true / false
1 / 1
03

შეამოწმე

სამი კითხვა. აირჩიე პასუხი და ნახე ახსნა.

№1

ცარიელი რიგი: push 4, push 7, push 1, pop, push 9. რას უდრის front()?

№2

BFS გრაფს შრეებად იკვლევს. რიგის რომელი თვისება იწვევს ამას?

№3

დავალებების დამატება და აღება ორივე ბოლოში O(1)-ში გჭირდება. რას გამოიყენებ?

04

ივარჯიშე

რეალური ამოცანები გასამყარებლად, მარტივიდან რთულისკენ.