算法:C语言实现
作者:Robert Sedgewick
作者网站:https://www.cs.princeton.edu/~rs/
第一部分 基础知识
第一章:引言
按照作者的说法,这本书主要研究基本算法,即使用的最为广泛的算法。
理解过程
- 实现并测试程序,包括程序变体
- 讨论程序在小规模例子上的操作
- 尝试在较大问题上使用
一般方法:由一个原型例子入手,探索这个例子的性能特征,改进算法。
1.1 算法
算法即解决特定问题的方法,这与具体的计算机无关,学习的要点在于解决问题的方法,而不是程序。
算法关注的是计算中设计的数据的组织方法,用这种方法建立的对象称为数据结构。
- 数据结构为算法的最终产物,研究数据结构来理解算法
- 算法的复杂度和数据结构的复杂度无关
- 算法研究的目的即节省空间和时间
开发大规模程序时,需要将问题分解为小问题,分解是为了算法更容易实现。
样本问题——连通性
给定整数对序列,每个整数表示某种类型对象,p-q表示”p连接到q“,连通关系可传递,p-q,q-r,则p-r。
要求
- 过滤集合中无关的程序对
这个图如何理解? - 左边为给定的表示对象的连接
- 中间为连通算法输出的表示新连接的对(就是过滤出来的无关的对)
- 右边是之前存在的连通关系的证明
比如2-9,这个就不需要过滤,因为之前给出的连接中可以表示为2-9是联系的,右边就是证明。
问题设计要求
- 记录足够多的数对信息的程序
- 判定一个新对是否连通
此任务称为连通性问题
连通性问题的实际意义
网络连接问题
- 整数可以表示大规模网络中的计算机
- 对表示网络中的连接
- 此程序可以确定是否需要建立已有的连接,还是建立新的连接。
应用:确定是否连通。
比如能否确定图中的两个黑点是否连通。
当我们得到新对,需要确定此对是否为一个新的连接,然后把看到的连接信息合并到已得到的连通关系中,使其可以检查后续要出现的连接。
- 用整数表示抽象集合中的元素
- 查照包含给定数据项的集合
- 用并集替换包含两个给定数据项的集合
问题已经被转换为定义表示集合的数据结构,并实现对这个数据结构的查找和合并。
1.3 合并-查找算法
- 实现问题的简单算法
- 存储输入对的方式
- 遍历输入对函数
- 检查对象连通性
由于实际使用中对的量会很大,则不能将数据全部放在内存中。所以将数据放到数组中。
程序1.1 连通问题的快速查找算法
#include <stdio.h>
#define N 10
int main()
{
int i, p, q, t, id[N];
for (i = 0; i < N; i++) // 给数组赋值
id[i] = i;
while (scanf("%d %d", &p, &q) == 2)
{
if (id[p] == id[q])
continue;
for (t = id[p], i = 0; i < N; i++)
if (id[i] == t)
id[i] = id[q];
printf("*********************************\n%d %d ", p, q);
for (int j = 0; j < 10; j++)
{
printf("%d ", id[j]);
}
printf("\n*********************************\n");
}
return 0;
}
此图为输出结果。
代码解释
只要数组中两个数的值相等则连通,比如第一次输入3和4,那么3位和4位就都成了4,则表示3-4。
- 程序先给数组赋值,然后我们输入连通对,如果id[p]和id[q]的值相等,那就说明p和q这两个位置的值相等,则p-q连通,所以直接continue,进行下一对输入。
- 如果不相等,则说明之前没有建立连通关系,那么这时就需要建立连通关系。
- 首先把id[p]的值给到中间变量t,然后遍历数组,如果id[i]的值为t,则把id[q]的值赋给id[i]。此时id[p]就和id[q]相等了。遍历数组是为了保存原来的连通关系,应为若之前有连通,则如果直接idp]=id[q]就会破坏之前的连通关系。
- 也可以解释为,若有之前的连通关系,则新的连通和之前的也是连通的,所以需要将之前所有的和t相等的值都赋值为id[q]。比如3-4,4-9,则3-9,所以3 4 9的值都是9。