The basic operator of the graph

这是我们计算机问题求解课程的一个课程设计,我们在期末复习的大环境下赶完了这份工,虽算不上一份满意的答卷,但毕竟完成度还是比较高。
下面我就关于我所做的部分做一下还原与总结。

题目

理解图论的基本概念,图的矩阵表示,图的连通性,图的遍历,以及求图的连通支方法。实现如下功能:

分工建议:

  1. 以结点对的形式输入一个无向简单图的边,建立该图的邻接矩阵,判断图是否连通。(1人)
  2. 并计算任意两个结点间的距离。(1 人)
  3. 对不连通的图输出其各个连通支。(1 人)
  4. 系统搭建(1 人)

过程与分析

我负责系统搭建(其实就是图形界面的建立),考虑到QT与c++的关系,自然选择以QT来进行图形界面的开发。

第一个坑(初学)

学习一样新的东西时,尽量选择相关说明文档或者相关书籍,而不是选择相关视频进行学习,因为视频实在太慢了。
QT可以直接进行ui的设计,拖动按钮、输入组件、显示组件等这些组件,但根据我的分析来看,至少有七八个界面,
所以不得不用代码来操作。(如果直接全部ui来了要我有何用==)
界面

第二个坑(组件设计)

关于这些组件的设置,要尽量定义少的组件,使整个代码才不那么乱。
当时采取简单的if-else来达到目的,如:

void Dialog::setNextBtn(QString text, int x, int y, int width, int hight, QString image)
{
nextBtn = new QPushButton(this);
nextBtn->setText(text);
nextBtn->setGeometry(QRect(x, y, width, hight));
nextBtn->setStyleSheet(image);
if(text == tr("下一步"))
connect(nextBtn, &QPushButton::clicked, this, &Dialog::next_clicked);
else if(text == tr("上一步"))
connect(nextBtn, &QPushButton::clicked, this, &Dialog::last_clicked);
else if(text == tr("bfs显示"))
connect(nextBtn, &QPushButton::clicked, this, &Dialog::bfsOutput_clicked);
else if(text == tr("dfs显示"))
connect(nextBtn, &QPushButton::clicked, this, &Dialog::dfsOutput_clicked);
else if(text == tr("显示距离"))
connect(nextBtn, &QPushButton::clicked, this, &Dialog::floydOutput_clicked);
}

现在回头看,发觉用switch语句可读性与效率都应该更高些。

第三个坑(输出)

有了输出组件,当然应该还需要准确的输出与标准化显示。
我采取流和字符串来同时进行操作,以达到准确输出,如:

//矩阵形式输出图
void adjacencyWGraph::outputWithAdjacency(string &s)const
{
stringstream ss;
string temp;
s += " ";
for (int i = 0; i < n; i++) {
for(int k = 0; k < maxLength+2-1; k++){
s += " ";
}

ss.clear();
ss << vertex[i];
ss >> temp;
s += temp;
}
s += "\r";
for (int i = 1; i <= n; i++) {
ss.clear();
ss << vertex[i - 1];
ss >> temp;
s += temp;
for(int k = 0; k < maxLength+2-1; k++){
s += " ";
}
for (int j = 1; j <= n; j++) {
if (a[i][j] != INT_MAX) {
ss.clear();
ss << a[i][j];
ss >> temp;
s += temp;
for(int k = 0; k < maxLength+2-(int)temp.length(); k++){
s += " ";
}
}
else {
s += "∞";
for(int k = 0; k < maxLength; k++){
s += " ";
}
}
}
s += "\r";
}
//cout<<s<<endl;
}

其中maxLength是我为了达到尽量的标准化输出而来获取到的输入当中的最大字符串的长度(或是权值的字符串形式的长度)。
函数如下:

//获取输入的字符串的最大长度,以保持输出的整齐
void adjacencyWGraph::getMaxLength()
{
stringstream ss;
this->maxLength = 2;
string temp;
int length;
for(int i=0;i<n;i++){
temp = vertex[i];
length = temp.length();
if(length>maxLength){
maxLength = length;
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (a[i][j] != INT_MAX) {
ss.clear();
ss << a[i][j];
ss >> temp;
length = temp.length();
if(length>maxLength){
maxLength = length;
}
}
}
}
}

第四个坑(异常)

我们考虑到了需要抛出异常这个功能,在这里就是当输入非法时,提示用户输入错误,并告述他正确的输入格式让他重新输入。
由于时间因素,我并没有完成这个功能,而是给了一个格式说明的界面以及输入的默认提示文字来提示用户正确输入。

第五个坑(QTextBrowser)

这是一个天坑,在我万般百度、谷歌的情况下依旧未被解决的问题。
就是当输入图的顶点过多时(大概超过15个)时,矩阵形式输出在界面上是没法看的,过量的顶点字符会排到第二行,
(当时连滑条都做出来了,还是没有滑动的按钮==),不过值得欣慰的是,复制粘贴到文本文档里面并不会换行,格式还是对的。

第六个坑(布局)

只有主菜单界面是栅格布局。

第七个坑(画图)

最开始是想用QT的2D绘图功能来输出的,最后,当然不了了之了==

效果图

主界面

主菜单界面

手动输入界面

手动输入界面

全图效果

全图效果

源码链接