《算法笔记》读书记录DAY_50

本文介绍了有向无环图(DAG)的概念,并详细阐述了拓扑排序的算法过程,包括如何通过拓扑排序判断一个图是否为有向无环图。给出了使用邻接表实现拓扑排序的C++代码示例,以及如何优化队列以优先输出入度为0的最小编号顶点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

CHAPTER_10  提高篇(4)——图算法专题

10.6.1有向无环图

如果一个有向图的任意顶点都无法通过一些有向边回到自身,那么称这个有向图为有向无环图DAG)。如下给出几个DAG的例子:

10.6.2拓扑排序

拓扑排序是将有向无环图G的所有顶点排出一个线性序列,使得对图G中的任意两个顶点u和v,如果存在边u->v,那么在序列中u一定能在v的前面。这个序列又被称为拓扑序列

如下图,给出有向图(a),拓扑排序为acbfde。可以看出,这个序列完全符合拓扑排序的定义。

参照上图,拓扑排序的算法过程如下:

(1)定义一个队列Q,并把所有入度为0的结点加入队列。

(2)取队首结点输出,然后删去所有从它出发的边,并令这些边到达的顶点入度减1,如果某个结点的入度为0,则将其加入队列。

(3)反复进行(2)操作,直到队列为空。如果队列为空时入过队的结点个数恰好为N,说明拓扑排序成功,图G为有向无环图;否则,拓扑排序失败,图G中有环。

可以使用邻接表实现拓扑排序。由于需要记录结点的入度,因此需要额外建立一个数组inDegree[MAXV],并在程序一开始读入图时就记录好每个结点的入度。接下来就只需要按上面所说的步骤进行实现即可。代码如下:

vector<int> G[MAXV];
int n,m,inDegree[MAXV];

bool topologicalSort() {
	int num=0;                //记录加入拓扑序列的顶点数
	queue<int> q;
	for(int i=0;i<n;i++) {
		if(inDegree[i]==0) {
			q.push(i);        //将所有入度为0的结点入队 
		}
	}
	while(!q.empty()) {
		int u=q.front();      //取队首顶点
		//cout<<u;            必要时可以输出这个顶点
		q.pop();              //出队
		for(int i=0;i<G[u].size();i++) {
			int v=G[u][i];    //v为u的后继结点
			inDegree[v]--;    //顶点v的入度减1 
			if(inDegree[v]==0) {
				q.push(v);    //顶点v的入度减为0时则入队 
			} 
		}
		G[u].clear();         //清空u的出边,如无必要可以不写
		num++;                //拓扑序列里的顶点数+1 
	}
	if(num==n)
		return true;          //加入拓扑序列的顶点数为n则成功 
	else
		return false;         //反之拓扑排序失败 
}

拓扑排序的一个重要应用就是判断一个图是否是有向无环图,正如上面的代码,如果topologicalSort()函数返回true,则排序成功,给定的图是有向无环图;反之则给定的图中有环。

最后指出,如果要求多个入度为0的顶点中,选择最小编号的顶点优先输出,则把queue改成priority_queue即可。

<think>好的,我现在需要解释用户提供的代码片段`day_date_list.extend(day_datas)`。首先,我应该确认自己对这个语句的理解是否正确。`extend()`是Python中列表的一个方法,用于将一个可迭代对象的所有元素添加到列表末尾。这里的`day_date_list`应该是一个列表,而`day_datas`可能是另一个列表或可迭代对象。 接下来,我需要思考用户可能的疑问点。他们可能想知道`extend()`和`append()`的区别,或者这个操作的具体效果。例如,如果`day_datas`是一个列表,使用`extend()`会将它的元素逐个添加,而`append()`则会将其作为单个元素添加。我需要用例子来说明这一点,比如原来的列表是`[1,2,3]`,`extend([4,5])`会变成`[1,2,3,4,5]`,而`append([4,5])`则变成`[1,2,3,[4,5]]`。 然后,我需要考虑用户的使用场景。可能他们在处理日期数据,比如将多个日期的数据合并到一个列表中。例如,假设`day_date_list`存储了某几天的日期,而`day_datas`是另一批日期,使用`extend()`可以将两者合并。需要提醒用户确保`day_datas`确实是可迭代的,否则会抛出错误,比如如果`day_datas`是整数,就会报错。 另外,要注意`extend()`方法会直接修改原列表,而不是返回新列表。这和`+`操作符不同,后者会创建新列表。例如,`a = a + b`和`a.extend(b)`效果相同,但`extend()`更高效,尤其是处理大数据时。 可能用户在使用过程中遇到了问题,比如元素没有正确添加,或者类型错误。需要指出常见的错误,比如`day_datas`不是可迭代对象,或者误用了`append`导致结构变化。 最后,总结这个语句的作用,强调它用于合并列表元素,并提醒注意事项,比如可迭代性、原地修改等。确保解释清晰,结构合理,帮助用户理解并正确使用`extend()`方法。</think>我们来逐步解释代码`day_date_list.extend(day_datas)`的作用和原理: --- ### 1. **基本定义** - `day_date_list`:是一个Python列表(List)对象 - `day_datas`:需要被合并到`day_date_list`中的另一个可迭代对象(如列表、元组、集合等) --- ### 2. **`.extend()`方法的作用** - **功能**:将`day_datas`中的所有元素**逐个添加**到`day_date_list`的末尾 - **与`.append()`的区别**: - `.append(x)`:将整个`x`作为单个元素添加到列表 - `.extend(x)`:将`x`中的每个元素拆开后再逐个添加 #### 示例对比: ```python a = [1, 2, 3] b = [4, 5] # 使用 append a.append(b) # 结果: [1, 2, 3, [4, 5]] # 使用 extend a.extend(b) # 结果: [1, 2, 3, 4, 5] ``` --- ### 3. **典型使用场景** 假设你正在处理日期数据: ```python day_date_list = ["2023-10-01", "2023-10-02"] day_datas = ["2023-10-03", "2023-10-04"] day_date_list.extend(day_datas) # 结果: ["2023-10-01", "2023-10-02", "2023-10-03", "2023-10-04"] ``` --- ### 4. **注意事项** 1. **可迭代性要求**:`day_datas`必须是可迭代对象(如列表、元组),否则会抛出`TypeError` ```python # 错误示例(整数不可迭代) day_datas = 100 day_date_list.extend(day_datas) # TypeError ``` 2. **原地修改**:`.extend()`会直接修改原列表`day_date_list`,而不是返回新列表 3. **性能优势**:相比`+`操作符(如`new_list = a + b`),`.extend()`更高效,尤其适合合并大型列表 --- ### 5. **等价实现** 若不用`.extend()`,可以用循环模拟: ```python for item in day_datas: day_date_list.append(item) ``` --- ### 总结 `day_date_list.extend(day_datas)`的作用是:将`day_datas`中的所有元素逐个添加到`day_date_list`末尾,最终实现两个列表的**扁平化合并**。使用时需确保`day_datas`为可迭代对象。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值