《算法:C语言实现》_第一部分_用快速合并算法实现解决连通性问题

上一篇文章讲到,快速查找算法只适合开销不大的连通性问题上,现在对此进行改进。
每次合并遍历全部数组效率太低,能不能不要每次遍历数组全部值,优化为每次只遍历数组的部分值,复杂度因此就会降低。

快速合并的补算法
它与快速查找算法都基于同一个数据结构——通过对象名引用数组元素,但数组元素表达的含义不同,具有更复杂的抽象结构。
这里运用到了树结构,在连通性的关系中,

p->k & q->k = p->q

可将k是为根节点,p和q是为子节点,p和q有共同的根结点k,故p和q连通。
数据结构
1.有一个节点数组id[N],其中的id[i]就表示存放i的父节点。
2.i的根结点是id[id[…id[]i]…]],不断向上找父节点的父节点……直到找到根结点。(这里根结点指向的是自身)
3.在一个没有环的结构中,每个对象指向同一集合中的另一个对象。要确定两个对象是否在同一个集合当中,只需要跟随每个对象的指针,直到达到指向自身的一个对象(只有根结点才会指向自身,所以这里说的是直到找到根结点)。
4.当且仅当这个过程使两个对象到达同一个对象时,这两个对象在同一个集合中。
5.如果两者不在同一个集合中,最终一定到达不同对象(这两个不同的对象是两个不同的根结点,分别都指向的是自身)。
6.当我们在进行合并操作时,只需将一个对象链接到另一个对象。因此命名为快速合并。

快速合并算法的树形表示
在这里插入图片描述图中描述的结构就是树,是基本的组合结构。

对于合并和查找操作,图中的树是有用的。它们可以快速建立。
性质
1.当且仅当两个对象在输入中是连通时,这两个对象在树中连通。
2.沿着树向上可以很快找到包含每个对象的树的根。
3.每棵树只有一个对象指向自己——根结点。
快速合并算法示例(不是太快的查找)
在这里插入图片描述快速查找和快速合并的区别
1.快速查找在查找树根时,只需要一个链接就可以达到树根,快速合并则可能需要经过几个链接才能达到树根。
2.快速查找对N个对象执行M次合并操作,程序至少需要MN条指令。快速合并则不需要遍历整个数组,即少于MN条指令。
代码实现
替换快速查找算法中while循环体里的内容。

for(i = p; i != id[i]; i = id[i]);//向上找到p的树根
for(i = q;i != id[q];i = id[q]);//向上找到q的树根
if(i == j) continue;//如果p和q的树根相同则进行下一次while循环
id[i] = j;//不同则将id[q]赋值给id[i],表示连通,实现合并操作。
printf("%d %d",p,q);

快速合并算法相对于快速查找算法来说,是一种改进,但有其自身的局限性。
我们不能保证每种情况下,它都会比快速查找算法快。

快速合并次数
对于M>N,快速合并算法求解N个对象,M个对的连通问题,需要执行MN/2条指令。
一种极端情况
假设输入的连通对,是1-2,2-3,3-4,……的次序。N-1个这样的连通对输入之后,可得到N个对象在同一个集合之中。且用快速合并算法生成的树是一条直线。第N个对象指向第N-1个对象,第N-1个对象指向第N-2个对象,以此类推。
如果此时通过第N个对象来查找树根,则需要遍历前N-1个对象。
因此前N个连通对遍历的对象数量就是
(0+1+2+……+(N-1))/N = (N-1)/2。

算法C语言实现 (第1-4部分)基础知识、数据结构、排序及搜索(原书第3版) 本书是Sedgewick彻底修订和重写的C算法系列的第一本。全书分为四部分,共16章。第一部分“基础知识”(第1—2章)介绍基本算法分析原理。第二部分数据结构”(第3~5章)讲解算法分析中必须掌握的数据结构知识,主要包括基本数据结构、抽象数据结构、递归和树。第三部分“排序”(第6~11章)按章节顺序分别讨论基本排序方法(如选择排序、插入排序、冒泡排序、希尔排序等)、快速排序方法、归并和归并排序方法、优先队列与堆排序方法、基数排序方法以及特殊用途的排序方法,并比较了各种排序方法的性能特征。第四部分“搜索”(第12~16章)在进一步讲解符号表、树等抽象数据类型的基础上,重点讨论散列方法、基数搜索以及外部搜索方法。 书中提供了用C语言描述的完整算法源程序,并且配有丰富的插图和练习。作者用简洁的实现将理论和实践成功地结合了起来,这些实现均可在真实应用上测试,使得本书自问世以来备受程序员的欢迎。 本书可作为高等院校计算机相关专业算法数据结构课程的教材和补充读物,也可供自学之用。 目录 出版者的话 译者序 前言 第一部分 基础知识  第1章 引言   1.1 算法   1.2 典型问题——连通性   1.3 合并一查找算法   1.4 展望   1.5 主题概述  第2章 算法分析的原理   2.1 实现和经验分析   2.2 算法分析   2.3 函数的增长   2.4 大O符号   2.5 基本递归方程   2.6 算法分析示例   2.7 保证、预测及局限性 第二部分 数据结构  第3章 基本数据结构   3.1 构建组件   3.2 数组   3.3 链表   3.4 链表的基本处理操作   3.5 链表的内存分配   3.6 字符串   3.7 复合数据结构  第4章 抽象数据类型   4.1 抽象对象和对象集   4.2 下推栈ADT   4.3 栈ADT客户示例   4.4 栈ADT的实现   4.5 创建一个新ADT   4.6 FIFO队列和广义队列   4.7 复制和索引项   4.8 一级ADT   4.9 基于应用的ADT示例   4.10 展望  第5章 递归与树   5.1 递归算法   5.2 分治法   5.3 动态规划   5.4 树   5.5 树的数学性质   5.6 树的遍历   5.7 递归二叉树算法   5.8 图的遍历   5.9 综述 第三部分 排序  第6章 基本排序方法   6.1 游戏规则   6.2 选择排序   6.3 插入排序   6.4 冒泡排序   6.5 基本排序方法的性能特征   6.6 希尔排序   6.7 对其他类型的数据进行排序   6.8 索引和指针排序   6.9 链表排序   6.10 关键字索引统计  第7章 快速排序   7.1 基本算法   7.2 快速排序算法的性能特征   7.3 栈大小   7.4 小的子文件   7.5 三者取中划分   7.6 重复关键字   7.7 字符串和向量   ……  第8章 归并与归并排序  第9章 优先队列和堆排序  第10章 基数排序  第11章 特殊用途的排序方法 第四部分 搜索  第12章 符号表和二叉搜索树  第13章 平衡树  第14章 散列  第15章 基数搜索  第16章 外部搜索
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值