Topologinen lajittelualgoritmi: Python, C++ esimerkki
โก รlykรคs yhteenveto
Topologinen lajittelu jรคrjestรครค suunnatun asyklisen graafin solmut siten, ettรค jokainen solmu nรคkyy ennen niitรค, joihin se osoittaa, kรคyttรคen Kahnin algoritmia poimimaan toistuvasti solmuja, joiden epรคsuhta on nolla.

Mikรค on topologinen lajittelualgoritmi?
Topologinen lajittelu tunnetaan myรถs nimellรค Kahnin algoritmi, ja se on suosittu lajittelualgoritmi. Kรคyttรคmรคllรค suunnattua kuvaajaa syรถtteenรค Topologinen lajittelu lajittelee solmut siten, ettรค jokainen nรคkyy ennen sitรค, johon se osoittaa.
Tรคtรค algoritmia sovelletaan DAG-taulukkoon (Directed Acyclic Graph) siten, ettรค jokainen solmu esiintyy jรคrjestetyssรค taulukossa ennen kaikkia muita solmuja, joihin se osoittaa. Tรคmรค algoritmi noudattaa tiettyjรค sรครคntรถjรค toistuvasti, kunnes lajittelu on valmis.
Yksinkertaistaaksesi, katso seuraava esimerkki:
Ohjattu graafi
Tรคssรค nรคemme, ettรค โAโ:lla ei ole sisรครคnpรคin suuntautuvaa astetta. Sisรครคnpรคin suuntautuva aste tarkoittaa reunaa, joka osoittaa solmuun. โBโ:llรค ja โCโ:llรค on edellytys โAโ:lle, ja โEโ:llรค on edellytys โDโ:lle ja โFโ:lle. Jotkut solmut ovat riippuvaisia โโtoisista solmuista.
Tรคssรค on toinen esitys yllรค olevasta kaaviosta:
Jokaisen solmun riippuvuus (lineaarinen jรคrjestys)
Joten kun siirrรคmme DAG:n (Directed Acyclic Graph) topologiseen lajitteluun, se antaa meille taulukon lineaarisella jรคrjestyksellรค, jossa ensimmรคisellรค elementillรค ei ole riippuvuutta.
Voit tehdรค tรคmรคn seuraavasti:
Vaihe 1) Etsi solmu, jolla on nolla saapuvaa reunaa, solmu, jolla on nolla astetta.
Vaihe 2) Tallenna kyseinen nolla-astesolmu jonoon tai pinoon ja poista solmu graafista.
Vaihe 3) Poista sitten kyseisen solmun lรคhtevรค reuna. Tรคmรค vรคhentรครค seuraavan solmun sisรครคnpรคin suuntautuvien asteiden mรครคrรครค.
Topologinen jรคrjestys edellyttรครค, ettรค graafin tietorakenteessa ei ole sykliรค. Graafia pidetรครคn DAG:na, jos se tรคyttรครค seuraavat vaatimukset:
- Yksi tai useampi solmu, jonka asteen arvo on nolla.
- Graafi ei sisรคllรค yhtรครคn sykliรค.
Niin kauan kuin graafissa on solmuja ja graafi on edelleen DAG, suoritamme yllรค olevat kolme vaihetta. Muuten algoritmi joutuu sykliseen riippuvuuteen, eikรค Kahnin algoritmi lรถydรค solmua, jonka aste on nolla.
Kuinka topologinen lajittelu toimii
Tรคssรค kรคytรคmme Kahnin algoritmia topologiseen lajitteluun. Oletetaan, ettรค meillรค on seuraava graafi:
Tรคssรค ovat Kahnin algoritmin vaiheet:
Vaihe 1) Laske kaavion kaikkien solmujen inaste tai sisรครคntuleva reuna.
Huomautus:
- Indegree tarkoittaa suunnattuja reunoja, jotka osoittavat solmuun.
- Outdegree tarkoittaa suunnattuja reunoja, jotka tulevat solmusta.
Tรคssรค on yllรค olevan graafin sisรครคn- ja ulospรคinsuuntautuminen:
Vaihe 2) Etsi solmu, jossa on nolla sisรครคnpรคin suuntautuvaa astetta tai nolla sisรครคnpรคin suuntautuvaa kaarraa. Solmu, jossa on nolla sisรครคnpรคin suuntautuvaa astetta, tarkoittaa, ettรค solmua kohti ei ole tulossa kaaria. Solmulla "A" on nolla sisรครคnpรคin suuntautuvaa astetta, mikรค tarkoittaa, ettรค solmuun "A" ei ole osoittavaa kaarraa. Joten teemme seuraavat toimenpiteet:
- Poista tรคmรค solmu ja sen ulkoreunat (lรคhtevรคt reunat).
- Aseta solmu tilausjonoon.
- Pรคivitรค "A":n naapurisolmun asteluku.
Vaihe 3) Meidรคn on lรถydettรคvรค solmu, jonka sisรครคntuloaste on nolla. Tรคssรค esimerkissรค solmuilla "B" ja "C" on sisรครคntuloaste nolla. Tรคssรค voimme valita jommankumman nรคistรค kahdesta. Otetaan "B" ja poistetaan se graafista. Pรคivitetรครคn sitten muiden solmujen sisรครคntuloastearvot. Nรคiden toimintojen suorittamisen jรคlkeen graafi ja jono nรคyttรคvรคt seuraavalta:
Vaihe 4) Solmulla โCโ ei ole sisรครคntulevaa kaarretta. Joten poistamme solmun โCโ graafista ja siirrรคmme sen jonoon. Voimme myรถs poistaa solmusta โCโ lรคhtevรคn kaaren. Nyt graafimme nรคyttรครค tรคltรค:
Vaihe 5) Nรคemme, ettรค solmujen โDโ ja โFโ astearvo on nolla. Laitamme yhden solmun jonoon. Poistetaan ensin โDโ. Tรคllรถin solmun โEโ astearvo on 1. Nyt solmujen D ja E vรคlillรค ei ole solmuja. Meidรคn on tehtรคvรค sama solmulle โFโ, ja tuloksemme on seuraavanlainen:
Vaihe 6) Solmun โEโ sisรครคnpรคin suuntautuvat reunat ja ulospรคin suuntautuvat reunat nollautuivat. Nรคin ollen kaikki solmun โEโ edellytykset ovat tรคyttyneet. Tรคssรค solmu โEโ sijoitetaan jonon loppuun. Solmuja ei siis ole enรครค jรคljellรค, ja algoritmi pรครคttyy tรคhรคn.
Pseudo Code topologista lajittelua varten
Tรคssรค on pseudokoodi topologiselle lajittelulle Kahnin algoritmia kรคyttรคen.
function TopologicalSort( Graph G ): for each node in G: calculate the indegree start = Node with 0 indegree G.remove(start) topological_list = [start] while node with 0 indegree present: topological_list.append(node) G.remove(node) // Update indegree of present nodes return topological_list
Topologinen lajittelu voidaan toteuttaa myรถs DFS:n (Syvyys Ensimmรคinen haku) menetelmรค. Tรคmรค lรคhestymistapa on kuitenkin rekursiivinen menetelmรค. Kahnin algoritmi on tehokkaampi kuin DFS-lรคhestymistapa.
C++ Topologisen lajittelun toteutus
#include<bits/stdc++.h> using namespace std; class graph{ int vertices; list<int> *adjecentList; public: graph(int vertices){ this->vertices = vertices; adjecentList = new list<int>[vertices]; } void createEdge(int u, int v){ adjecentList[u].push_back(v); } void TopologicalSort(){ // filling the vector with zero initially vector<int> indegree_count(vertices,0); for(int i=0;i<vertices;i++){ list<int>::iterator itr; for(itr=adjecentList[i].begin(); itr!=adjecentList[i].end();itr++){ indegree_count[*itr]++; } } queue<int> Q; for(int i=0; i<vertices;i++){ if(indegree_count[i]==0){ Q.push(i); } } int visited_node = 0; vector<int> order; while(!Q.empty()){ int u = Q.front(); Q.pop(); order.push_back(u); list<int>::iterator itr; for(itr=adjecentList[u].begin(); itr!=adjecentList[u].end();itr++){ if(--indegree_count[*itr]==0){ Q.push(*itr); } } visited_node++; } if(visited_node!=vertices){ cout<<"There's a cycle present in the Graph.\nGiven graph is not DAG"<<endl; return; } for(int i=0; i<order.size();i++){ cout<<order[i]<<"\t"; } } }; int main(){ graph G(6); G.createEdge(0,1); G.createEdge(0,2); G.createEdge(1,3); G.createEdge(1,5); G.createEdge(2,3); G.createEdge(2,5); G.createEdge(3,4); G.createEdge(5,4); G.TopologicalSort(); }
ulostulo
0 1 2 3 5 4
Python Topologisen lajittelun toteutus
from collections import defaultdict class graph: def __init__(self, vertices): self.adjacencyList = defaultdict(list) self.Vertices = vertices # No. of vertices # function to add an edge to adjacencyList def createEdge(self, u, v): self.adjacencyList[u].append(v) # The function to do Topological Sort. def topologicalSort(self): total_indegree = [0]*(self.Vertices) for i in self.adjacencyList: for j in self.adjacencyList[i]: total_indegree[j] += 1 queue = [] for i in range(self.Vertices): if total_indegree[i] == 0: queue.append(i) visited_node = 0 order = [] while queue: u = queue.pop(0) order.append(u) for i in self.adjacencyList[u]: total_indegree[i] -= 1 if total_indegree[i] == 0: queue.append(i) visited_node += 1 if visited_node != self.Vertices: print("There's a cycle present in the Graph.\nGiven graph is not DAG") else: print(order) G = graph(6) G.createEdge(0,1) G.createEdge(0,2) G.createEdge(1,3) G.createEdge(1,5) G.createEdge(2,3) G.createEdge(2,5) G.createEdge(3,4) G.createEdge(5,4) G.topologicalSort()
ulostulo
[0, 1, 2, 3, 5, 4]
Topologisen lajittelualgoritmin sykliset kuvaajat
Syklin sisรคltรคvรครค graafia ei voida topologisesti jรคrjestรครค, koska syklisellรค graafilla on riippuvuus syklisellรค tavalla. Tarkastellaan esimerkiksi tรคtรค graafia:
Tรคmรค graafi ei ole DAG (Directed Acyclic Graph), koska A, B ja C muodostavat syklin. Huomaathan, ettei missรครคn solmussa ole nollaa astearvoa. Kahnin algoritmin mukaan, jos analysoimme yllรค olevaa graafia:
- Etsi solmu, jossa on nolla astetta (ei sisรครคntulevia reunoja).
- Poista kyseinen solmu graafista ja siirrรค se jonoon. Yllรค olevassa graafissa ei kuitenkaan ole solmua, jonka sisรครคntuloaste olisi nolla. Jokaisen solmun sisรครคntuloasteen arvo on suurempi kuin 0.
- Palauttaa tyhjรคn jonon, koska ei lรถytรคnyt solmua, jonka sisรครคntuloaste olisi nolla.
Voimme havaita syklit kรคyttรคmรคllรค topologista jรคrjestystรค seuraavilla vaiheilla:
Vaihe 1) Suorita topologinen lajittelu.
Vaihe 2) Laske topologisesti jรคrjestetyn listan elementtien kokonaismรครคrรค.
Vaihe 3) Jos elementtien lukumรครคrรค on yhtรค suuri kuin solmujen kokonaismรครคrรค, sykliรค ei ole.
Vaihe 4) Jos se ei ole yhtรค suuri kuin solmujen lukumรครคrรค, annetussa graafin tietorakenteessa on ainakin yksi sykli.
Topologisen lajittelun monimutkaisuusanalyysi
Algoritmeja on kahdenlaisia โโmonimutkaisuuksia. Ne ovat:
- Ajan monimutkaisuus
- Avaruuden monimutkaisuus
Nรคmรค monimutkaisuudet esitetรครคn funktiolla, joka tarjoaa yleisen monimutkaisuuden.
Ajan monimutkaisuus: Topologisessa lajittelussa aikakompleksisuus on aina sama. Aikakompleksisuudelle on olemassa pahin, keskimรครคrรคinen ja paras tapaus. Topologisen lajittelun aikakompleksisuus on O(E + V), jossa E tarkoittaa graafin kaarien lukumรครคrรครค ja V tarkoittaa graafin solmujen lukumรครคrรครค.
Murtaudutaanpa tรคmรคn monimutkaisuuden lรคpi:
Vaihe 1) Aluksi laskemme kaikki asteet. Tรคtรค varten meidรคn tรคytyy kรคydรค lรคpi kaikki reunat, ja aluksi mรครคritรคmme kaikki V-pistein asteet nollaan. Joten suorittamamme vaiheet ovat O(V+E).
Vaihe 2) Lรถydรคmme solmun, jonka inastearvo on nolla. Meidรคn tรคytyy etsiรค kรคrjen V-numerosta. Joten vaiheet on suoritettu O (V).
Vaihe 3) Jokaisen solmun, jolla on nolla astetta, poistamme kyseisen solmun ja vรคhennรคmme astetta. Tรคmรคn toiminnon suorittaminen kaikille solmuille kestรครค O(E).
Vaihe 4) Lopuksi tarkistamme, onko sykliรค vai ei. Tarkistamme, onko lajitellun taulukon elementtien kokonaismรครคrรค yhtรค suuri kuin solmujen kokonaismรครคrรค. Se tulee ottamaan O (1).
Nรคmรค olivat siis topologisen lajittelun tai topologisen jรคrjestรคmisen kunkin vaiheen yksittรคiset aikakompleksisuudet. Voimme sanoa, ettรค yllรค olevan laskelman mukainen aikakompleksisuus on O(V + E); tรคssรค O tarkoittaa kompleksisuusfunktiota.
Avaruuden monimutkaisuus: Tarvitsimme O(V) avaruuksia topologisen lajittelualgoritmin suorittamiseen. Tรคssรค ovat vaiheet, joissa tarvitsimme tilaa ohjelmalle:
- Meidรคn piti laskea kaikki kaaviossa olevien solmujen asteet. Koska kaaviossa on yhteensรค V-solmuja, meidรคn on luotava joukko, jonka koko on V. Tarvittava tila oli siis O (V).
- Jonotietorakennetta kรคytettiin solmun tallentamiseen nolla-asteella. Poistimme nolla-astetta sisรคltรคvรคt solmut alkuperรคisestรค kaaviosta ja asetimme ne jonoon. Tรคtรค varten tarvittava tila oli O (V).
- Taulukon nimi on โorderโ, ja se tallentaa solmut topologisessa jรคrjestyksessรค. Tรคmรค edellytti myรถs O (V) tilat.
Nรคmรค olivat yksittรคisiรค avaruuskompleksisuuksia. Joten meidรคn tรคytyy maksimoida nรคmรค avaruudet suorituksen aikana. Avaruuskompleksisuus on lyhenne O(V):stรค, jossa V tarkoittaa graafin solmun numeroa.
Topologisen lajittelun soveltaminen
Topologiselle lajittelulle on valtavasti kรคyttรถรค. Tรคssรค on joitakin niistรค:
- Sitรค kรคytetรครคn, kun Operating-jรคrjestelmรค tรคytyy suorittaa resurssien allokointi.
- Syklin lรถytรคminen graafista. Voimme varmistaa topologisella lajittelulla, onko graafi DAG vai ei.
- Lausejรคrjestys automaattisen tรคydennyksen sovelluksissa.
- Sitรค kรคytetรครคn havaitsemiseen umpikujaan.
- Erilaiset aikataulutustyypit tai kurssien aikataulutus kรคyttรคvรคt topologista lajittelua.
- Riippuvuuden ratkaiseminen. Jos esimerkiksi yritรคt asentaa paketin, se saattaa tarvita myรถs muita paketteja. Topologinen jรคrjestys selvittรครค kaikki nykyisen paketin asentamiseen tarvittavat paketit.
- Linux kรคyttรครค topologista lajittelua "apt":ssa tarkistaakseen pakettien riippuvuuden.











