问题描述 :
目的:使用C++模板设计并逐步完善图的邻接表抽象数据类型(ADT)。
内容:(1)请参照图的邻接矩阵模板类原型,设计并逐步完善图的邻接表ADT。(由于该环境目前仅支持单文件的编译,故将所有内容都集中在一个源文件内。在实际的设计中,推荐将抽象类及对应的派生类分别放在单独的头文件中。)
(2)设计并实现一个算法,在已存在的图中查找指定元素值的结点,如查找成功,则删除之(包括与之相关的边);否则,返回。图的存储结构采用邻接表。将其加入到ADT中。
注意:DG(有向图), DN(有向网), UDG(无向图), UDN(无向网)
参考函数原型:
//往G中删除一个顶点
template<class TypeOfVer, class TypeOfEdge>
bool adjlist_graph<TypeOfVer, TypeOfEdge>::DeleteVer(const int u);
输入说明 :
建图的输入数据格式参见建图的算法说明。
第一行:图的类型
第二行:结点数
第三行:结点集
第四行:边数
第五行:边集
第六行:待删除的顶点的位序
输出说明 :
第一行:图的类型
第三行:删除前的顶点数
第四行:删除前的边数
第五行:删除前的邻接表
空行
第六行:删除后的顶点集
第七行:删除后的顶点数
第八行:删除后的边数
第九行:删除后的邻接表
输入范例 :
DG
6
A B C D E F
8
0 1
0 2
0 3
1 4
2 4
3 5
4 1
5 1
1
输出范例 :
DG
A B C D E F
6
8
A->3->2->1
B->4
C->4
D->5
E->1
F->1
A C D E F
5
4
A->2->1
C->3
D->4
E
F
思路分析
- 整理旧的图形结构,在整体移动到新的邻接表中,不如在将旧的邻接表中的结点移动到新的邻接表中,在移动的过程中对其进行更改。
- 新建一个新的顶点表,将原来的顶点表除了需要被删除的顶点全部复制过去
- 遍历新的顶点表的边表,如果其索引大于待删除目标节点的索引,就减一
- 如果是目标结点:就删除该结点
- 如果比目标节点小,那就不用删除
实现伪码
/*
描述:在G中删除一个顶点
*/
bool DeleteVer(const int u) {
//注意分类,有向图和无向图
//判定输入的位序是否合理
if(u<0 ||u >= Vers) return false;
//在位序合理的情况下,进行判定
//申请新的内存
verNode *verListTemp = new verNode[Vers-1];
edgeNode *temp = NULL,*temp2 = NULL;
int m = 0;//用来指向新的生成的邻接表
//指定位序之前的结点只需要修改的边表,不需要修改自身的位序
for(int i = 0; i < Vers; i ++) {
//遍历的每一个结点
//判定当前的结点是否为需要删除的目标节点的索引
if(i == u) {
//遍历改边表对应的边数量,总的边数减去该边数
if(GraphKnd == "DG" || GraphKnd == "DN") {
temp = verList[i].getHead();
while(temp) {
Edge --;
temp = temp->next;
}
}
continue;
} else {
//在不是要删除的目标结点的情况下,将结点复制到新生成的目标节点中
verListTemp[m] = verList[i];
verList[i].setHead(NULL);
//开始遍历当前的边表
//判定第一个结点是不是的要删除的结点
temp = verListTemp[m].getHead();
if(temp->getData() == u) {
verListTemp[m].setHead(temp->next);
Edge --;
delete temp;
} else {
//开始有头结点的单链表的遍历
while(temp) {
//查看当前节点的位序是否比目标结点的位序大
if(temp->getData() > u) {
temp->SetData(temp->getData() - 1);
}
//如果当前结点的下一个子节点是目标节点,就删除下一个结点
if(temp->next && temp->next->getData() == u) {
Edge --;
temp2 = temp->next;
temp->next = temp2->next;
delete temp2;
}
temp = temp->next;
}
}
m ++;
}
}
Vers --;
delete[] verList;
verList = verListTemp;
}
事故现场
两次提交
-
有点疑惑,有向图和无向图的删除顶点不都一个意思吗?都是删除定点表,然后删除各个顶点的边表。这里直接看样例的
-
问题:
-
无向图的边数是有两个顶点进行标识,删除一个顶点可以通过删除与之相邻接的顶点的边表进行删除,达到减去对应的边数的目的
-
但是有向图的顶点是通过一个顶点进行标识的,一个边只有一个顶点进行标识,删除顶点要删除该顶点对应的边表的边,同时删除边表要减去对应的边
第三次提交
- 这验证了我的猜想
第四次提交
分析总结
- 这道题我觉得一点都不简单,我做了好久,不过也有一点经验了。基本上都是建立在已有的基础上,在已有的基础上根据题目要求对其进行修改。
- 基本思路是遍历,根据遍历的当前节点的情况,采取不同的措施
- 有一个措施是删除,链表删除结点,采用的是无头结点链表删除结点
- 然后进行整合就行了