摘《李开复:算法的力量》
:
算法是计算机科学领域最重要的基石之一,但却受到了国内一些程序员的冷落。许多学生看到一些公司在招聘时要求的编程语言五花八门就产生了一种误解,认为学计算机就是学各种编程语言,或者认为,学习最新的语言、技术、标准就是最好的铺路方法。其实大家都被这些公司误导了。编程语言虽然该学,但是学习计算机算 法和理论更重要,因为计算机算法和理论更重要,因为计算机语言和开发平台日新月异,但万变不离其宗的是那些算法和理论,例如数据结构、算法、编译原理、计算机体系结构、关系型数据库原理等等
。
许多计算机科学家认为,排序算法是算法学习中最基本的问题。那么我们就从排序这类算法开始,去看看算法究竟是什么。
排序算法解决的是一类什么具体问题呢?
输入
:n
个数的序列
<a1,a2,a3,...,an>
输出
:
输入序列的一个重排
<a'1,a'2,a'3,...,a'n>,
使得
a'1<=a'2<=a'3<=...<=a'n
输入序列通常是一个
n
元数组,但也可能由其他形式来表示,如链表。
对于这个问题,我们可以很容易联想到日常生活中的许多例子。那么我们解决这个问题的第一个思路便可以从日常生活中获得。
插入排序,这是一个对少量元素进行排序的有效算法。其工作机理和很多人打牌时,整理手中牌时的做法差不多。在开始摸牌时,我们的左手是空的,牌面朝下的放在桌上。接着,一次从桌上摸起一张牌,并将它插入到左手一把牌中的正确位置上。为了找到这张牌合适的位置,要将它与手中已有的每一张牌从右向左地进行比较。无论在什么时候,左手中的牌都是排好序的,而这些牌原先都是桌上那副牌里最顶上的一些牌。
//
主方法
INSERTION-SORT(A)
//
从桌面上一次次取牌
for j ← 2 to length[A]
do
//
取一张牌到右手
key
key ← A[j]
//
眼睛注意的位置(将要比较的位置)
i ← j – 1
//
开始寻找合适的位置
while i > 0 and A[i] > key
do
//
微调左手中的已经排好顺序的牌
A[i + 1] ← A[i]
//
移动眼睛,转换比较的对象
i ← i – 1
//
将右手中的牌放在左手牌中合适的位置上
A[i + 1] ← key
大概的思路已经在脑子中形成了,剩下的是简单的工作:将思路转化为实实在在的代码。在这里我用
java
编写了一个静态方法。关于这个算法的具体证明过程详见《
Introduction to Algorithms
》
.
/** */
/**
*InsertionSort
*The time limit of this sort is O(n^2)
*<strong>O(n^2)</strong>
*
@param
element will be sorted
*在这段代码中使用了java的范型以及一个对象接口,详细情况可以参见java相关教材
*/
public
static
<
Type
extends
Comparable
>
void
insertionSort(Type element[])
...
{
for
(
int
j
=
1
;j
<
element.length;j
++
)
...
{
Type key
=
element[j];
int
i
=
j
-
1
;
while
( (i
>=
0
)
&&
(element[i].compareTo(key)
>
0
))
...
{
element[i
+
1
]
=
element[i];
i
--
;
}
element[i
+
1
]
=
key;
}
}
如同大家打牌一样,很多人熟能生巧整理手中的牌时又准又快,而有些人却费时费力。那么一个算法也是友好有坏,在这里我只给出相关的评价指数,至于具体规定可参见相关书籍。
这个算法的时间复杂度为
O(n^2)
,空间复杂度为
O(n).
关于“
O”
符号可以在微积分类书籍上找到更为详尽的解释。
科学技术不断进步,很多新的算法应运而生。在这里再介绍一种排序算法。它在时间复杂度上有了具大提高,空间上却付出了两倍的代价。
合并排序,一种利用了“分治策略”的排序方法。分治策略:将原问题划分成
n
个规模较小而结构简单与原问题相似的子问题;递归地解决这些子问题,然后再合并其结果,就得到原问题的解。排序算法就是借助了这种思想,本质是:从中间把数组分成元素个数尽量相等的两半,分别对他们进行排序,然后再合并两个有序表。整个问题最困难的地方便是合并两个有序表,在这里我们着重看看这个过程。
再举打牌这个例子
,
假设有两堆牌正
面朝上地放在桌上,每一堆都是已经排好顺序的,最小的牌在最上面。我们希望把这两堆牌合并成一个排好序的输出堆,面朝下地放在桌上。基本步骤包括在面朝上的两堆牌中,选取顶上两张牌中较小的一张,将其取出后面朝下地放入输出堆中。重复这个步骤,直到某一堆为空为止。
/** */
/**
*Merge used in the mergeSort
*<strong>O(n)</strong>
*
@param
element Type[] the elements to be merged
*
@param
p int the begin of the first elements
*
@param
q int the end of the first elements
*
@param
r int the end of the second elements
*/
private
static
<
Type
extends
Comparable
>
void
merge(Type element[],
int
p,
int
q,
int
r)
...
{
//
确定两堆牌的起始位置
int
nl
=
q
-
p
+
1
;
int
nr
=
r
-
q;
//
新建两个输入堆用于存放待组合牌
Type[] lElement,rElement;
lElement
=
(Type[])java.lang.reflect.Array.newInstance(element.getClass().getComponentType(),nl);
rElement
=
(Type[])java.lang.reflect.Array.newInstance(element.getClass().getComponentType(),nr);
//
做记录处理
for
(
int
i
=
0
;i
<
nl;i
++
)
...
{
lElement[i]
=
element[p
+
i];
}
for
(
int
i
=
0
;i
<
nr;i
++
)
...
{
rElement[i]
=
element[q
+
i
+
1
];
}
//
开始取牌
int
i
=
0
,j
=
0
;
int
k
=
p;
//
逐个比较,一直到一个堆为空
while
((i
<
nl)
&&
(j
<
nr))
...
{
if
(lElement[i].compareTo(rElement[j])
<=
0
)
...
{
element[k]
=
lElement[i];
i
++
;
}
else
...
{
element[k]
=
rElement[j];
j
++
;
}
k
++
;
}
//
处理某一堆中 剩下的牌
while
(i
<
nl)
...
{
element[k]
=
lElement[i];
i
++
;
k
++
;
}
while
(j
<
nr)
...
{
element[k]
=
rElement[j];
j
++
;
k
++
;
}
}
这个算法的时间复杂度为
O(n log2 n),
空间复杂度为
O(2n)
=
O(n).
至此两个算法的介绍结束,我们将这类算法扩大化,从中取出根本的东西。
分享到:
相关推荐
分治算法在很多领域都有广泛的应用,如排序(如快速排序)、计算几何、矩阵乘法等。在互联网行业中,分治算法同样发挥着重要作用,尤其是在大数据处理和复杂系统设计中,它能够帮助我们有效地管理和解决复杂的问题。...
一、A*搜索算法 一(续)、A*,Dijkstra,BFS 算法性能比较及A*算法的应用 二、Dijkstra 算法初探 二(续)、彻底理解Dijkstra 算法...十二、快速排序算法之所有版本的c/c++实现 十三、通过浙大上机复试试题学SPFA 算法
前言: 本人的原创作品经典算法研究系列,...十二(再续):快速排序算法之所有版本的c/c++实现 十三、通过浙大上机复试试题学SPFA 算法 十四、快速选择SELECT算法的深入分析与实现 十五、多项式乘法与快速傅里叶变换
在本文中,我们将深入探讨游戏开发中的一个关键算法——A*寻路算法,并结合提供的代码进行解析。A*算法是一种广泛应用的路径搜索方法,尤其在游戏场景中,它用于智能体(如游戏角色或NPC)寻找从起点到目标点的最短...
#### 十二、快速排序算法之所有版本的c/c++实现 快速排序是一种高效的排序算法,采用分治策略来递归地将数组分为较小的部分进行排序。本文提供了多种C/C++实现版本,涵盖了不同应用场景下的优化技巧。 #### 十三、...
快速排序的平均时间复杂度为O(nlogn),是最常用的排序算法之一。 ### 十三、通过浙大上机复试试题学SPFA算法 SPFA(Shortest Path Faster Algorithm)是一种改进的Bellman-Ford算法,用于解决含有负权边的图中的...
3. **RSA加密算法初探 - botg的专栏 - CSDNBlog.mht**:RSA是一种非对称加密算法,是现代网络安全的基础。这篇MHT文件可能详细解释了RSA的工作原理,包括公钥和私钥的生成、数字签名以及密钥交换过程。 4. **基于...
#### 数据结构与C#:初探专业转型之路 数据结构,作为计算机科学的核心组成部分,对于任何级别的程序员而言都至关重要。它不仅涉及到数据的组织方式,还包括对这些数据进行操作的算法。对于从新手过渡到中级程序员...
例如,讲解链表、树等数据结构时,教师可以使用图示方法,而在教授排序算法时,可以从具体问题出发,引导学生分析解决问题的过程,并总结出算法的思想。 在教学过程中,教师还应适当设疑,引导学生思考。提出问题时...
4. 算法设计:Python是学习算法的理想语言,如排序、搜索等经典算法。教师可以逐步引入这些算法,让学生通过编程实现,从而理解算法的工作原理和效率。 在教学方法上,可以采用以下策略: 1. 实践导向:通过编写...
此外,为了提高搜索引擎的性能和用户体验,还需要考虑索引更新策略、查询优化、结果排序算法以及用户体验设计等多个方面。例如,实时性要求搜索引擎能够快速响应新添加或更新的网页,而结果排序则直接影响到用户找到...
杨 培 -《非最优化算法初探》 张 辰 -《动态规划的特点及其应用》 张 力 -《类比思想在解题中的应用》 张一飞 -《冗繁削尽留清瘦——浅谈信息的充分利用》 ## 2001 高寒蕊 -《从圆桌问题谈数据结构的综合...
它通常包括线性结构、树形结构和图结构等基础数据结构的学习,以及查找、插入、删除、排序等算法的应用。然而,由于数据结构课程内容的抽象性和算法的高抽象度,学生往往难以理解,导致学习兴趣不高,学习效果不佳。...
项目中可能涵盖的算法包括但不限于排序算法(如冒泡排序、快速排序、归并排序等)、搜索算法(如二分查找、深度优先搜索、广度优先搜索等)、图算法(如Dijkstra算法、Floyd-Warshall算法等)以及动态规划问题。...
数据结构课程包含了许多理论和算法,例如线性表、栈、队列、数组、矩阵、树、二叉树、图、查找和排序算法等,这些内容往往难以为学生所理解。 2. 教学方法单一:传统教学方法主要是讲授理论知识,这导致学生难以将...
例如,可以采用任务教学法,这种方法要求教师在任务开始之前给学生布置一个具有现实意义的问题,如排序、图的最短路径等。通过分组讨论和互相交流,学生们将被引导去发现、提出、分析和解决问题,培养创造性思维。 ...
其次,构建基于大数据的工程造价评估模型是提高精准性的手段之一。灰色模型可用于预测和分析,通过累加优化确定影响造价的因素。通过对误差平方的最小化计算,可以匹配并确定参数,形成适用于大数据环境的工程造价...
在讲解数据结构中的内部排序算法时,教师可以启发学生思考算法的核心原理,引导他们想象和尝试算法的其他可能性。例如,在讲解折半插入排序时,可以通过更换查找过程中的系数,激发学生对算法改良的想象。之后,通过...
比如,在讲解汉诺塔算法时,可以通过游戏程序来让学生体验算法的关键步骤,从而更易于理解算法的实质,并激发学生用编程语言实现算法的兴趣。 对于不同基础和学习能力的学生,教师应实施分层次教学。具体方法包括将...