Radha (lloji abstrakt i të dhënave)

Në shkencën kompjuterike, një radhë është një koleksion entitetesh që mbahen në një sekuencë dhe mund të modifikohen duke shtuar entitete në njërin skaj të sekuencës dhe heqjen e entiteteve nga skaji tjetër i sekuencës. Sipas konventës, fundi i sekuencës në të cilën shtohen elementët quhet pjesa e pasme, bishti ose pjesa e pasme e radhës, dhe fundi në të cilin hiqen elementët quhet kreu ose pjesa e përparme e radhës, në mënyrë analoge me fjalët e përdorura kur njerëzit rreshtohen për të pritur mallra ose shërbime.

Veprimi i shtimit të një elementi në pjesën e pasme të radhës njihet si enqueue, dhe operacioni i heqjes së një elementi nga pjesa e përparme njihet si dequeue . Veprimi të tjera mund të lejohen gjithashtu, shpesh duke përfshirë një veprim të shikimit ose të përparmë që kthen vlerën e elementit tjetër që do të hiqet pa e hequr atë.

Operacionet e një radhe e bëjnë atë një strukturë e para hyn, e para del (FIFO) . Në një strukturë të dhënash FIFO, elementi i parë i shtuar në radhë do të jetë i pari që hiqet. Kjo është e njëvlerëshme me kërkesën që pasi të shtohet një element i ri, të gjithë elementët që janë shtuar më parë duhet të hiqen përpara se të hiqet elementi i ri. Një radhë është një shembull i një strukture lineare të të dhënave. Radhët janë të zakonshme në programet kompjuterike, ku ato zbatohen si struktura të dhënash të shoqëruara me rutinat e aksesit, si një strukturë abstrakte e të dhënave ose në gjuhët e orientuara nga objekti si klasa. Implementimet e zakonshme janë buferat rrethorë dhe listat e lidhura.

Radhët ofrojnë shërbime në shkencë kompjuterike, transport dhe kërkime operacional ku entitete të ndryshme si të dhëna, objekte, persona ose ngjarje ruhen dhe mbahen për t'u përpunuar më vonë. Në këto kontekste, radha kryen funksionin e një buffer-i . Një përdorim tjetër i radhëve është në zbatimin e kërkimit të parë në gjerësi.
 Implementimi i radhës 
Teorikisht, një karakteristikë e një radhe është se ajo nuk ka një nxënësi specifike. Pavarësisht se sa elementë janë përfshirë tashmë, një element i ri mund të shtohet gjithmonë. Mund të jetë gjithashtu bosh, në të cilën pikë heqja e një elementi do të jetë e pamundur derisa të shtohet përsëri një element i ri.

Ka disa implementime efikase të radhëve FIFO. Një zbatim efikas është ai që mund të kryejë veprimet - enqueue dhe dequeue - në kohën O(1) .

 Lista e lidhur
 Një listë e lidhur dyfish ka futje dhe fshirje O(1) në të dy skajet, kështu që është një zgjedhje e natyrshme për radhët.
 Një listë e rregullt e lidhur veçmas ka vetëm futje dhe fshirje efikase në një fund. Sidoqoftë, një modifikim i vogël - duke mbajtur një tregues në nyjen e fundit përveç të parës - do t'i mundësojë atij të zbatojë një radhë efikase.
 Një deque e implementuar duke përdorur një vektor dinamik të modifikuar

 Radhët dhe gjuhët e programimit 
Radhët mund të zbatohen si një lloj i veçantë i të dhënave, ose mund të konsiderohet një rast i veçantë i një radhe të dyfishtë (deque) dhe nuk jo të zbatuara veçmas. Për shembull, Perl dhe Ruby lejojnë shtyrjen dhe heqjen nga një vektor tek të dyja skajet, kështu që mund të përdoren funksionet shtytje dhe zhvendosje për enqueue dhe dequeue në radhë një listë (ose, në të kundërt, mund të përdoren unshift dhe pop ),  edhe pse në disa në rastet kur këto veprime nuk janë efikase.

Libraria standarde e shablloneve të C++ ofron një klasë të modeluar " queue " e cila është e kufizuar vetëm në veprimet push/pop. Që nga J2SE5.0, libraria e gjuhës Java përmban një ndërfaqe Queue që specifikon veprimet e radhës; klasat implementuese përfshijnë LinkedList dhe (që nga J2SE 1.6) ArrayDeque . PHP ka një klasë SplQueue dhe librari të palëve të treta si beanstalk'd dhe Gearman .

UML queue class.svg

 Shembull 
Një radhë e thjeshtë e implementuar në JavaScript :class Queue {
    constructor() {
        this.items = [];
    }

    enqueue(element) {
        this.items.push(element);
    }

    dequeue() {
        return this.items.shift();
    }
}

 Zbatim thjesht funksional 
Radhët mund të zbatohen gjithashtu si një strukturë e pastër funksionale e të dhënave .  Ka dy zbatime. E para arrin vetëm  mesatarisht për veprim. Domethënë koha e amortizuar është , por veprimet individuale mund të zgjasin  ku n është numri i elementeve në radhë. Zbatimi i dytë quhet një radhë në kohë reale  dhe lejon që radha të jetë e qëndrueshme me operacionet në kohën më të keqe O(1). Është një zbatim më i ndërlikuar dhe kërkon lista përtace me memoizim .

 Radhë në kohë reale 
Radha në kohë reale arrin kohë   për të gjitha veprimet, pa amortizim. Ky diskutim do të jetë teknik, ndaj kujtoni se, për një listë ,  shënon gjatësinë e saj, se NIL përfaqëson një listë boshe dhe  paraqet listën koka e së cilës është h dhe bishti t .

Struktura e të dhënave e përdorur për të zbatuar radhët tona përbëhet nga tre lista të lidhura njëshe  ku f është pjesa e përparme e radhës dhe r është pjesa e pasme e radhës në rend të kundërt. Invarianti i strukturës është se s është pjesa e pasme e f pa  elementet e para, pra  . Bishti i radhës  është atëherë pothuajse  dhe duke futur një element x në  është pothuajse  . Thuhet pothuajse, sepse në të dyja këto rezultate,  . Atëherë duhet thirrur një funksion ndihmës  që invarianti të plotësohet. Duhet të merren parasysh dy raste, në varësi të faktit nëse  është lista bosh, në këtë rast , ose jo. Përkufizimi formal është  dhe  ku  është f e ndjekur nga r anasjelltas.

Le të shënojmë  funksionin i cili kthen f të ndjekur nga r e përmbysur. Për më tepër, le të supozojmë se , pasi është rasti kur thirret ky funksion. Më saktësisht, ne përcaktojmë një funksion përtac  i cili merr si hyrje tri lista të tilla që , dhe kthejnë përngjitjen e f, të r të kundërt dhe të a . Pastaj  . Përkufizimi induktiv i rrotullimit është  dhe  . Koha e ekzekutimit të saj është , por, meqë përdoret vlerësimi përtac, llogaritja vonohet derisa rezultatet të detyrohen nga llogaritja.

Lista s në strukturën e të dhënave ka dy qëllime. Kjo listë shërben si një numërues për , me të vërtetë,  nëse dhe vetëm nëse s është lista boshe. Ky numërues na lejon të sigurohemi që pjesa e pasme të mos jetë kurrë më e gjatë se lista e përparme. Për më tepër, duke përdorur s, që është një bisht i f, detyron llogaritjen e një pjese të listës (përtace) f gjatë çdo veprimi tail dhe insert . Prandaj, kur , lista f është totalisht e detyruar. Nëse nuk do të ishte kështu, paraqitja e brendshme e f mund të ishte një shtojcë e shtojcës së ... i shtojcës, dhe detyrimi nuk do të ishte më një veprim i vazhdueshëm në kohë.