一步一步写算法(之图添加和删除)

原文:一步一步写算法(之图添加和删除)

【 声明:版权所有,欢迎转载,请勿用于商业用途。  联系信箱:feixiaoxing @163.com】

前面我们谈到的图的数据结构图的创建,今天我们就来说一说如何在图中添加和删除边。边的添加和删除并不复杂,但是关键有一点需要记住,那就是一定要在小函数的基础之上构建大函数,否则很容易出现错误。

一、边的创建

边的创建一般来说可以分为下面以下几个步骤:

1)判断当前图中是否有节点,如果没有,那么在pGraph->head处添加一条边即可

2)如果当前图中有节点,那么判断节点中有没有以start点开头的,如果没有创建一个顶点和边,并插入图的head处

3)在当前有节点start中,判断是否end的边已经存在。如果end边存在,返回出错;否则在pVectex->neighbour处添加一条边

4)添加的过程中注意点的个数和边的个数处理

STATUS insert_vectex_into_graph(GRAPH* pGraph, int start, int end, int weight)
{
	VECTEX* pVectex;
	LINE* pLine;

	if(NULL == pGraph)
		return FALSE;

	if(NULL == pGraph->head){
		pGraph->head = create_new_vectex_for_graph(start, end, weight);
		pGraph->head->number ++;
		pGraph->count ++;
		return TRUE;
	}

	pVectex = find_vectex_in_graph(pGraph->head, start);
	if(NULL == pVectex){
		pVectex = create_new_vectex_for_graph(start, end, weight);
		pVectex->next = pGraph->head;
		pGraph->head = pVectex;
		pGraph->head->number ++;
		pGraph->count ++;
		return TRUE;
	}

	pLine = find_line_in_graph(pVectex->neighbor, end);
	if(NULL != pLine)
		return FALSE;

	pLine = create_new_line(end, weight);
	pLine->next = pVectex->neighbor;
	pVectex->neighbor = pLine;
	pVectex->number ++;
	return TRUE;
}

二、边的删除

在进行边的删除之前,我们需要对链表子节点进行处理,构建delete小函数,这样可以在边删除函数中使用。

STATUS delete_old_vectex(VECTEX** ppVectex, int start)
{
	VECTEX* pVectex;
	VECTEX* prev;

	if(NULL == ppVectex || NULL == *ppVectex)
		return FALSE;

	pVectex = find_vectex_in_graph(*ppVectex, start);
	if(NULL == pVectex)
		return FALSE;

	if(pVectex == *ppVectex){
		*ppVectex = pVectex->next;
		free(pVectex);
		return TRUE;
	}

	prev = *ppVectex;
	while(pVectex != prev->next)
		prev = prev->next;

	prev->next = pVectex->next;
	free(pVectex);
	return TRUE;
}

STATUS delete_old_line(LINE** ppLine, int end)
{
	LINE* pLine;
	LINE* prev;

	if(NULL == ppLine || NULL == *ppLine)
		return FALSE;

	pLine = find_line_in_graph(*ppLine, end);
	if(NULL == pLine)
		return FALSE;

	if(pLine == *ppLine){
		*ppLine = pLine->next;
		free(pLine);
		return TRUE;
	}

	prev = *ppLine;
	while(pLine != prev->next)
		prev = prev->next;

	prev->next = pLine->next;
	free(pLine);
	return TRUE;
}

一般来说,边的删除和边的添加是可逆的,过程如下所示:

1)判断图中是否有节点存在,如果没有,返回出错

2)判断图中节点start是否存在,如果不存在,返回出错

3)判断节点start中是否end边存在,如果不存在,返回出错

4)删除对应的边

5)判断该节点的边计数number是否为0,如果为0,继续删除节点

6)删除过程中注意边和顶点的个数处理

STATUS delete_vectex_from_graph(GRAPH* pGraph, int start, int end, int weight)
{
	VECTEX* pVectex;
	LINE* pLine;
	STATUS result;

	if(NULL == pGraph || NULL == pGraph->head)
		return FALSE;

	pVectex = find_vectex_in_graph(pGraph->head, start);
	if(NULL == pVectex)
		return FALSE;

	pLine = find_line_in_graph(pVectex->neighbor, end);
	if(NULL != pLine)
		return FALSE;

	result = delete_old_line(&pVectex->neighbor, end);
	assert(TRUE == result);
	pVectex->number --;

	if(0 == pVectex->number)
		result = delete_old_vectex(&pGraph->head, start);

	assert(TRUE == result);
	pGraph->count --;
	return TRUE;
}

注意事项:

(1)注意写小函数,再复杂的功能都是有无数的小功能构建的,函数最好不要超过50行

(2)老规矩,代码务必要测试

时间: 2024-11-08 19:54:25

一步一步写算法(之图添加和删除)的相关文章

一步一步写算法(之排序二叉树删除-2)

原文:一步一步写算法(之排序二叉树删除-2) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 2.4 删除节点的左右子树都存在,此时又会分成两种情形 1)左节点是当前左子树的最大节点,此时只需要用左节点代替根节点即可 /* * * 10 ======> 6 * / \ / * 6 15 5 15 * / * 5 */ 代码该怎么编写呢? STATUS delete_node_from_tree(TREE_NODE** ppTreeNode

一步一步写算法(之排序二叉树删除-3)

原文:一步一步写算法(之排序二叉树删除-3) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 3 普通节点的删除 3.1 删除的节点没有左子树,也没有右子树 测试用例1: 删除节点6 /* * * 10 ======> 10 * / \ * 6 15 15 * */ static void test8() { TREE_NODE* pTreeNode = NULL; assert(TRUE == insert_node_into_tree

一步一步写算法(之排序二叉树删除-1)

原文:一步一步写算法(之排序二叉树删除-1) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 相比较节点的添加,平衡二叉树的删除要复杂一些.因为在删除的过程中,你要考虑到不同的情况,针对每一种不同的情况,你要有针对性的反应和调整.所以在代码编写的过程中,我们可以一边写代码,一边写测试用例.编写测试用例不光可以验证我们编写的代码是否正确,还能不断提高我们开发代码的自信心.这样,即使我们在开发过程对代码进行修改或者优化也不会担心害怕.然而看起

一步一步写算法(之图结构)

原文:一步一步写算法(之图结构) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 图是数据结构里面的重要一章.通过图,我们可以判断两个点之间是不是具有连通性:通过图,我们还可以计算两个点之间的最小距离是多少:通过图,我们还可以根据不同的要求,寻找不同的合适路径.当然,有的时候为了计算的需要,我们还需要从图中抽象出最小生成树,这样在遍历计算的时候就不需要持续判断是不是遇到了循环节点.当然,这所有的一切都是从图的表示开始的. 1)矩阵表示 矩

一步一步写算法(之图创建)

原文:一步一步写算法(之图创建) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 前面我们讨论过图的基本结构是什么样的.它可以是矩阵类型的.数组类型的,当然也可以使指针类型的.当然,就我个人而言,比较习惯使用的结构还是链表指针类型的.本质上,一幅图就是由很多节点构成的,每一个节点上面有很多的分支,仅此而已.为此,我们又对原来的结构做了小的改变: typedef struct _LINE { int end; int weight; str

一步一步写算法(之图的保存)

原文:一步一步写算法(之图的保存) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 前面的几篇博客,我们对图进行基本定义,同时介绍了图的创建.图的添加和删除等.今天,我们聊一聊图是怎么在存储在外设中的.这些外接设备可以是各种类型的,比如说,可以是硬盘.sd卡.网络硬盘等等.本质上说,我们今天讨论的主题就是怎么把图的数据永久地保留在本地.并且,如果需要加载这些数据,也可以快速恢复图原来的面貌.对图数据结构已经记得不太清楚的朋友可以复习一下面

一步一步写算法(之哈希二叉树)

原文:一步一步写算法(之哈希二叉树) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 用过平衡二叉树的朋友都清楚,平衡二叉树的最大优点就是排序.不管是在数据插入的时候还是在数据删除的时候,我们都要考虑到数据的排序情况.但是和数据的添加.删除一样重要的,还有数据的查询.很不幸,平衡二叉树经常由于节点的添加和删除,数据的查询效率会变得非常低下.朋友们可以看看下面这样的一个极端场景,所有分支节点都只有一边存在数据: /* * 7 3 * / *

一步一步写算法(之 算法总结)

原文:一步一步写算法(之 算法总结) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 自10月初编写算法系列的博客以来,陆陆续续以来写了几十篇.按照计划,还有三个部分的内容没有介绍,主要是(Dijkstra算法.二叉平衡树.红黑树).这部分会在后面的博客补充完整.这里主要是做一个总结,有兴趣的朋友可以好好看看,欢迎大家提出宝贵意见. (1) 排序算法 快速排序 合并排序 堆排序 选择排序 基数排序 冒泡排序 插入排序 希尔排序 链表排序

一步一步写算法(之prim算法 上)

原文:一步一步写算法(之prim算法 上) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 前面我们讨论了图的创建.添加.删除和保存等问题.今天我们将继续讨论图的一些其他问题,比如说如何在图的环境下构建最小生成树.为什么要构建最小生成树呢?其实原理很简单.打个比方,现在某一个乡镇有n个村,那么这n个村肯定是联通的.现在我们打算在各个村之间搭建网线,实现村村通的工程.那么有什么办法可以实现村村互通,同时又使得最后的总距离最小呢?要达到这个目