diff --git a/graph_implement.cpp b/graph_implement.cpp index 76e1ff8..2eec664 100644 --- a/graph_implement.cpp +++ b/graph_implement.cpp @@ -230,7 +230,7 @@ void ALGraph::ResetDistance(){ } } -void ALGraph::DFS(int strtID){ +void ALGraph::DFS(int strtID, bool generateForest){ if(strtID == -1) return; vector awaitVexList; @@ -254,9 +254,35 @@ void ALGraph::DFS(int strtID){ nextArc->visit(); vexList[nextVex].visit(); } + if(generateForest){ + for(int i = 0; i < vexList.size(); i++){ + if(vexList[i].visited) continue; + awaitVexList.clear(); + awaitArcList.clear(); + awaitVexList.push_back(i); + while(awaitVexList.size() > 0){ + int nextVex = awaitVexList.back(); + ALArc *nextArc = awaitArcList.size() > 0 ? awaitArcList.back() : nullptr; + awaitVexList.pop_back(); + if(nextArc) + awaitArcList.pop_back(); + for(ALArc *p = vexList[nextVex].firstArc; p != nullptr; p = p->nextArc){ + if(vexList[p->eVexID].visited == false){ + awaitVexList.push_back(p->eVexID); + awaitArcList.push_back(p); + if(type == UDG && GetIdOf(p->gArc->edVex()) != p->eVexID) + p->gArc->reverseDirection(); + } + } + if(nextArc && !vexList[nextArc->eVexID].visited) + nextArc->visit(); + vexList[nextVex].visit(); + } + } + } } -void ALGraph::BFS(int strtID){ +void ALGraph::BFS(int strtID, bool generateForest){ if(strtID == -1) return; vector awaitVexList; @@ -280,6 +306,32 @@ void ALGraph::BFS(int strtID){ nextArc->visit(); vexList[nextVex].visit(); } + if(generateForest){ + for(int i = 0; i < vexList.size(); i++){ + if(vexList[i].visited) continue; + awaitVexList.clear(); + awaitArcList.clear(); + awaitVexList.push_back(i); + while(awaitVexList.size() > 0){ + int nextVex = awaitVexList[0]; + ALArc *nextArc = awaitArcList.size() > 0 ? awaitArcList[0] : nullptr; + awaitVexList.erase(awaitVexList.begin()); + if(nextArc) + awaitArcList.erase(awaitArcList.begin()); + for(ALArc *p = vexList[nextVex].firstArc; p != nullptr; p = p->nextArc){ + if(vexList[p->eVexID].visited == false){ + awaitVexList.push_back(p->eVexID); + awaitArcList.push_back(p); + if(type == UDG && GetIdOf(p->gArc->edVex()) != p->eVexID) + p->gArc->reverseDirection(); + } + } + if(nextArc && !vexList[nextArc->eVexID].visited) + nextArc->visit(); + vexList[nextVex].visit(); + } + } + } } void ALGraph::Dijkstra(int strtID){ @@ -795,7 +847,7 @@ void AMLGraph::ResetDistance(){ } } -void AMLGraph::DFS(int strtID){ +void AMLGraph::DFS(int strtID, bool generateForest){ if(strtID == -1) return; vector awaitVexList; @@ -820,9 +872,36 @@ void AMLGraph::DFS(int strtID){ nextArc->visit(); outVexList[nextVex].visit(); } + if(generateForest){ + for(int i = 0; i < outVexList.size(); i++){ + if(outVexList[i].visited) continue; + awaitVexList.clear(); + awaitArcList.clear(); + awaitVexList.push_back(i); + while(awaitVexList.size() > 0){ + int nextVex = awaitVexList.back(); + AMLArc *nextArc = awaitArcList.size() > 0 ? awaitArcList.back() : nullptr; + awaitVexList.pop_back(); + if(nextArc) + awaitArcList.pop_back(); + for(AMLArc *p = outVexList[nextVex].firstArc; p != nullptr; p = p->outVexID == strtID ? p->nextOutArc : p->nextInArc){ + int endID = p->outVexID == nextVex ? p->inVexID : p->outVexID; + if(outVexList[endID].visited == false){ + awaitVexList.push_back(endID); + awaitArcList.push_back(p); + if(type == UDG && GetIdOf(p->gArc->edVex()) != endID) + p->gArc->reverseDirection(); + } + } + if(nextArc && !outVexList[nextVex].visited) + nextArc->visit(); + outVexList[nextVex].visit(); + } + } + } } -void AMLGraph::BFS(int strtID){ +void AMLGraph::BFS(int strtID, bool generateForest){ if(strtID == -1) return; vector awaitVexList; @@ -847,6 +926,33 @@ void AMLGraph::BFS(int strtID){ nextArc->visit(); outVexList[nextVex].visit(); } + if(generateForest){ + for(int i = 0; i < outVexList.size(); i++){ + if(outVexList[i].visited) continue; + awaitVexList.clear(); + awaitArcList.clear(); + awaitVexList.push_back(i); + while(awaitVexList.size() > 0){ + int nextVex = awaitVexList[0]; + AMLArc *nextArc = awaitArcList.size() > 0 ? awaitArcList[0] : nullptr; + awaitVexList.erase(awaitVexList.begin()); + if(nextArc) + awaitArcList.erase(awaitArcList.begin()); + for(AMLArc *p = outVexList[nextVex].firstArc; p != nullptr; p = p->outVexID == strtID ? p->nextOutArc : p->nextInArc){ + int endID = p->outVexID == nextVex ? p->inVexID : p->outVexID; + if(outVexList[endID].visited == false){ + awaitVexList.push_back(endID); + awaitArcList.push_back(p); + if(type == UDG && GetIdOf(p->gArc->edVex()) != endID) + p->gArc->reverseDirection(); + } + } + if(nextArc && !outVexList[nextVex].visited) + nextArc->visit(); + outVexList[nextVex].visit(); + } + } + } } void AMLGraph::Dijkstra(int strtID){ diff --git a/graph_implement.h b/graph_implement.h index e5cbc95..a342354 100644 --- a/graph_implement.h +++ b/graph_implement.h @@ -50,10 +50,10 @@ public: /* Other Function */ virtual void ClearVisit() = 0; virtual void ResetDistance() = 0; - virtual void DFS(int strtID) = 0; - virtual void DFS(MyGraphicsVexItem *strtVex) = 0; - virtual void BFS(int strtID) = 0; - virtual void BFS(MyGraphicsVexItem *strtVex) = 0; + virtual void DFS(int strtID, bool generateForest = false) = 0; + virtual void DFS(MyGraphicsVexItem *strtVex, bool generateForest = false) = 0; + virtual void BFS(int strtID, bool generateForest = false) = 0; + virtual void BFS(MyGraphicsVexItem *strtVex, bool generateForest = false) = 0; virtual void Dijkstra(int strtID) = 0; virtual void Dijkstra(MyGraphicsVexItem *strtVex) = 0; @@ -127,10 +127,10 @@ public: /* Other Function */ void ClearVisit(); void ResetDistance(); - void DFS(int strtID); - void DFS(MyGraphicsVexItem *strtVex){DFS(GetIdOf(strtVex));} - void BFS(int strtID); - void BFS(MyGraphicsVexItem *strtVex){BFS(GetIdOf(strtVex));} + void DFS(int strtID, bool generateForest = false); + void DFS(MyGraphicsVexItem *strtVex, bool generateForest = false){DFS(GetIdOf(strtVex), generateForest);} + void BFS(int strtID, bool generateForest = false); + void BFS(MyGraphicsVexItem *strtVex, bool generateForest = false){BFS(GetIdOf(strtVex), generateForest);} void Dijkstra(int strtID); void Dijkstra(MyGraphicsVexItem *strtVex){Dijkstra(GetIdOf(strtVex));} AMLGraph* ConvertToAML(); @@ -202,10 +202,10 @@ public: /* Other Function */ void ClearVisit(); void ResetDistance(); - void DFS(int strtID); - void DFS(MyGraphicsVexItem *strtVex){DFS(GetIdOf(strtVex));} - void BFS(int strtID); - void BFS(MyGraphicsVexItem *strtVex){BFS(GetIdOf(strtVex));} + void DFS(int strtID, bool generateForest = false); + void DFS(MyGraphicsVexItem *strtVex, bool generateForest = false){DFS(GetIdOf(strtVex), generateForest);} + void BFS(int strtID, bool generateForest = false); + void BFS(MyGraphicsVexItem *strtVex, bool generateForest = false){BFS(GetIdOf(strtVex), generateForest);} void Dijkstra(int strtID); void Dijkstra(MyGraphicsVexItem *strtVex){Dijkstra(GetIdOf(strtVex));} ALGraph* ConvertToAL(); diff --git a/mycanvas.cpp b/mycanvas.cpp index 7a6e6a3..e44d123 100644 --- a/mycanvas.cpp +++ b/mycanvas.cpp @@ -89,6 +89,14 @@ void MyCanvas::CreateSettings(int radius){ view->setType(id == 0 ? MyGraphicsView::DG : MyGraphicsView::UDG); type = id == 0 ? DG : UDG; }); + singleSelectGroup *dfsSetting = new singleSelectGroup("Traverse Mode", this); + selectionItem *setGenerateTree = new selectionItem("Tree", "Generate tree", this); + selectionItem *setGenerateForest = new selectionItem("Forest", "Generate forest", this); + dfsSetting->AddItem(setGenerateTree); + dfsSetting->AddItem(setGenerateForest); + connect(dfsSetting, &singleSelectGroup::selectedItemChange, this, [=](int id){ + generateForest = id == 1; + }); QWidget *whiteSpace = new QWidget(this); whiteSpace->setFixedHeight(30); horizontalValueAdjuster *aniSpeed = new horizontalValueAdjuster("Animation speed", 0.1, 20, 0.1, this); @@ -110,6 +118,7 @@ void MyCanvas::CreateSettings(int radius){ connect(delBtn, &textButton::clicked, this, [=](){emit setDel(this);}); settings->AddContent(delBtn); settings->AddContent(saveBtn); + settings->AddContent(dfsSetting); settings->AddContent(dirSetting); settings->AddContent(structureSetting); settings->AddContent(aniSpeed); @@ -353,19 +362,22 @@ void MyCanvas::Init(){ viewLog *newLog = new viewLog("[BFS] | --- BFS start ---"); newLog->setStyleSheet("color:#0078d4"); logDisplay->addWidget(newLog); - bfs(); + g->BFS(view->selectedVex(), generateForest); + view->hasVisitedItem = true; }); connect(startDfs, &textButton::clicked, this, [=](){ viewLog *newLog = new viewLog("[DFS] | --- DFS start ---"); newLog->setStyleSheet("color:#0078d4"); logDisplay->addWidget(newLog); - dfs(); + g->DFS(view->selectedVex(), generateForest); + view->hasVisitedItem = true; }); connect(startDij, &textButton::clicked, this, [=](){ viewLog *newLog = new viewLog("[Dij] | --- Dijkstra start ---"); newLog->setStyleSheet("color:#0078d4"); logDisplay->addWidget(newLog); - dijkstra(); + g->Dijkstra(view->selectedVex()); + view->hasVisitedItem = true; if(g->GetInfoOf(view->selectedVex())->strtVexInfo == nullptr){ dijStart->setValue("Run dijkstra first"); dijPrev->setValue("Run dijkstra first"); @@ -429,34 +441,3 @@ void MyCanvas::addVex(MyGraphicsVexItem *vex){ void MyCanvas::addArc(MyGraphicsLineItem *arc){ g->AddArc(arc); } - -void MyCanvas::dfs(){ - MyGraphicsVexItem *strtVex = view->selectedVex(); - if(strtVex != nullptr){ - g->DFS(strtVex); - view->hasVisitedItem = true; - } -} - -void MyCanvas::bfs(){ - MyGraphicsVexItem *strtVex = view->selectedVex(); - if(strtVex != nullptr){ - g->BFS(strtVex); - view->hasVisitedItem = true; - } -} - -void MyCanvas::dijkstra(){ - MyGraphicsVexItem *strtVex = view->selectedVex(); - if(strtVex){ - g->Dijkstra(strtVex); - view->hasVisitedItem = true; - } -} - -void MyCanvas::setWeight(int w){ - MyGraphicsLineItem *arc = view->selectedArc(); - if(arc){ - g->SetWeight(arc, w); - } -} diff --git a/mycanvas.h b/mycanvas.h index 82fca79..8377378 100644 --- a/mycanvas.h +++ b/mycanvas.h @@ -25,6 +25,7 @@ private: AbstractGraph *g; int structure_type; int type; + bool generateForest = false; void CreateSettings(int r); void Init(); @@ -48,13 +49,6 @@ signals: private slots: void addVex(MyGraphicsVexItem*); void addArc(MyGraphicsLineItem*); - //void delVex(MyGraphicsVexItem*); - //void delArc(MyGraphicsLineItem*); - void dfs(); - void bfs(); - void dijkstra(); - void setWeight(int w); - void setAniRate(int step){view->setAniRate(step / 100.0);} };