Ⅰ 冒泡排序法和快速排序比较的算法
打你屁股,这么简单的问题都不认真研究一下。
冒泡排序是最慢的排序,时间复杂度是 O(n^2)。
快速排序是最快的排序。关于快速排序,我推荐你看看《代码之美》第二章:我编写过的最漂亮的代码。作者所说的最漂亮,就是指效率最高的。
--------------------------------摘自《代码之美》---------------
当我撰写关于分治(divide-and-conquer)算法的论文时,我发现C.A.R. Hoare的Quicksort算法(“Quicksort”,Computer Journal 5)无疑是各种Quicksort算法的鼻祖。这是一种解决基本问题的漂亮算法,可以用优雅的代码实现。我很喜欢这个算法,但我总是无法弄明白算法中最内层的循环。我曾经花两天的时间来调试一个使用了这个循环的复杂程序,并且几年以来,当我需要完成类似的任务时,我会很小心地复制这段代码。虽然这段代码能够解决我所遇到的问题,但我却并没有真正地理解它。
我后来从Nico Lomuto那里学到了一种优雅的划分(partitioning)模式,并且最终编写出了我能够理解,甚至能够证明的Quicksort算法。William Strunk Jr.针对英语所提出的“良好的写作风格即为简练”这条经验同样适用于代码的编写,因此我遵循了他的建议,“省略不必要的字词”(来自《The Elements of Style》一书)。我最终将大约40行左右的代码缩减为十几行的代码。因此,如果要回答“你曾编写过的最漂亮代码是什么?”这个问题,那么我的答案就是:在我编写的《Programming Pearls, Second Edition》(Addison-Wesley)一书中给出的Quichsort算法。在示例2-1中给出了用C语言编写的Quicksort函数。我们在接下来的章节中将进一步地研究和改善这个函数。
【示例】 2-1 Quicksort函数
void quicksort(int l, int u)
{ int i, m;
if (l >= u) return; 10
swap(l, randint(l, u));
m = l;
for (i = l+1; i <= u; i++)
if (x[i] < x[l])
swap(++m, i);
swap(l, m);
quicksort(l, m-1);
quicksort(m+1, u);
}
如果函数的调用形式是quicksort(0, n-1),那么这段代码将对一个全局数组x[n]进行排序。函数的两个参数分别是将要进行排序的子数组的下标:l是较低的下标,而u是较高的下标。函数调用swap(i,j)将会交换x[i]与x[j]这两个元素。第一次交换操作将会按照均匀分布的方式在l和u之间随机地选择一个划分元素。
在《Programming Pearls》一书中包含了对Quicksort算法的详细推导以及正确性证明。在本章的剩余内容中,我将假设读者熟悉在《Programming Pearls》中所给出的Quicksort算法以及在大多数初级算法教科书中所给出的Quicksort算法。
如果你把问题改为“在你编写那些广为应用的代码中,哪一段代码是最漂亮的?”我的答案还是Quicksort算法。在我和M. D. McIlroy一起编写的一篇文章("Engineering a sort function," Software-Practice and Experience, Vol. 23, No. 11)中指出了在原来Unix qsort函数中的一个严重的性能问题。随后,我们开始用C语言编写一个新排序函数库,并且考虑了许多不同的算法,包括合并排序(Merge Sort)和堆排序(Heap Sort)等算法。在比较了Quicksort的几种实现方案后,我们着手创建自己的Quicksort算法。在这篇文章中描述了我们如何设计出一个比这个算法的其他实现要更为清晰,速度更快以及更为健壮的新函数——部分原因是由于这个函数的代码更为短小。Gordon Bell的名言被证明是正确的:“在计算机系统中,那些最廉价,速度最快以及最为可靠的组件是不存在的。”现在,这个函数已经被使用了10多年的时间,并且没有出现任何故障。
考虑到通过缩减代码量所得到的好处,我最后以第三种方式来问自己在本章之初提出的问题。“你没有编写过的最漂亮代码是什么?”。我如何使用非常少的代码来实现大量的功能?答案还是和Quicksort有关,特别是对这个算法的性能分析。我将在下一节给出详细介绍。
2.2 事倍功半
Quicksort是一种优雅的算法,这一点有助于对这个算法进行细致的分析。大约在1980年左右,我与Tony Hoare曾经讨论过Quicksort算法的历史。他告诉我,当他最初开发出Quicksort时,他认为这种算法太简单了,不值得发表,而且直到能够分析出这种算法的预期运行时间之后,他才写出了经典的“Quicksoft”论文。
我们很容易看出,在最坏的情况下,Quicksort可能需要n2的时间来对数组元素进行排序。而在最优的情况下,它将选择中值作为划分元素,因此只需nlgn次的比较就可以完成对数组的排序。那么,对于n个不同值的随机数组来说,这个算法平均将进行多少次比较?
Hoare对于这个问题的分析非常漂亮,但不幸的是,其中所使用的数学知识超出了大多数程序员的理解范围。当我为本科生讲授Quicksort算法时,许多学生即使在费了很大的努力之后,还是无法理解其中的证明过程,这令我非常沮丧。下面,我们将从Hoare的程序开
11
始讨论,并且最后将给出一个与他的证明很接近的分析。
我们的任务是对示例2-1中的Quicksort代码进行修改,以分析在对元素值均不相同的数组进行排序时平均需要进行多少次比较。我们还将努力通过最短的代码、最短运行时间以及最小存储空间来得到最深的理解。
为了确定平均比较的次数,我们首先对程序进行修改以统计次数。因此,在内部循环进行比较之前,我们将增加变量comps的值(参见示例2-2)。
【示例2-2】 修改Quicksort的内部循环以统计比较次数。
for (i = l+1; i <= u; i++) {
comps++;
if (x[i] < x[l])
swap(++m, i);
}
如果用一个值n来运行程序,我们将会看到在程序的运行过程中总共进行了多少次比较。如果重复用n来运行程序,并且用统计的方法来分析结果,我们将得到Quicksort在对n个元素进行排序时平均使用了1.4 nlgn次的比较。
在理解程序的行为上,这是一种不错的方法。通过十三行的代码和一些实验可以反应出许多问题。这里,我们引用作家Blaise Pascal和T. S. Eliot的话,“如果我有更多的时间,那么我给你写的信就会更短。”现在,我们有充足的时间,因此就让我们来对代码进行修改,并且努力编写出更短(同时更好)的程序。
我们要做的事情就是提高这个算法的速度,并且尽量增加统计的精确度以及对程序的理解。由于内部循环总是会执行u-l次比较,因此我们可以通过在循环外部增加一个简单的操作来统计比较次数,这就可以使程序运行得更快一些。在示例2-3的Quicksort算法中给出了这个修改。
【示例2-3】 Quicksort的内部循环,将递增操作移到循环的外部
comps += u-l;
for (i = l+1; i <= u; i++)
if (x[i] < x[l])
swap(++m, i);
这个程序会对一个数组进行排序,同时统计比较的次数。不过,如果我们的目标只是统计比较的次数,那么就不需要对数组进行实际地排序。在示例2-4中去掉了对元素进行排序的“实际操作”,而只是保留了程序中各种函数调用的“框架”。
【示例2-4】将Quicksort算法的框架缩减为只进行统计
void quickcount(int l, int u)
{ int m;
if (l >= u) return;
m = randint(l, u);
comps += u-l;
quickcount(l, m-1);
quickcount(m+1, u);
}
12
这个程序能够实现我们的需求,因为Quichsort在选择划分元素时采用的是“随机”方式,并且我们假设所有的元素都是不相等的。现在,这个新程序的运行时间与n成正比,并且相对于示例2-3需要的存储空间与n成正比来说,现在所需的存储空间缩减为递归堆栈的大小,即存储空间的平均大小与lgn成正比。
虽然在实际的程序中,数组的下标(l和u)是非常重要的,但在这个框架版本中并不重要。因此,我们可以用一个表示子数组大小的整数(n)来替代这两个下标(参见示例2-5)
【示例2-5】 在Quicksort代码框架中使用一个表示子数组大小的参数
void qc(int n)
{ int m;
if (n <= 1) return;
m = randint(1, n);
comps += n-1;
qc(m-1);
qc(n-m);
}
现在,我们可以很自然地把这个过程整理为一个统计比较次数的函数,这个函数将返回在随机Quicksort算法中的比较次数。在示例2-6中给出了这个函数。
【示例2-6】 将Quicksort框架实现为一个函数
int cc(int n)
{ int m;
if (n <= 1) return 0;
m = randint(1, n);
return n-1 + cc(m-1) + cc(n-m);
}
在示例2-4、示例2-5和示例2-6中解决的都是相同的基本问题,并且所需的都是相同的运行时间和存储空间。在后面的每个示例都对这些函数的形式进行了改进,从而比这些函数更为清晰和简洁。
在定义发明家的矛盾(inventor's paradox)(How To Solve It, Princeton University Press)时,George Póllya指出“计划越宏大,成功的可能性就越大。”现在,我们就来研究在分析Quicksort时的矛盾。到目前为止,我们遇到的问题是,“当Quicksort对大小为n的数组进行一次排序时,需要进行多少次比较?”我们现在将对这个问题进行扩展,“对于大小为n的随机数组来说,Quichsort算法平均需要进行多少次的比较?”我们通过对示例2-6进行扩展以引出示例2-7。
【示例2-7】 伪码:Quicksort的平均比较次数
float c(int n)
if (n <= 1) return 0
sum = 0
for (m = 1; m <= n; m++)
sum += n-1 + c(m-1) + c(n-m)
return sum/n
如果在输入的数组中最多只有一个元素,那么Quichsort将不会进行比较,如示例2-6
13
中所示。对于更大的n,这段代码将考虑每个划分值m(从第一个元素到最后一个,每个都是等可能的)并且确定在这个元素的位置上进行划分的运行开销。然后,这段代码将统计这些开销的总和(这样就递归地解决了一个大小为m-1的问题和一个大小为n-m的问题),然后将总和除以n得到平均值并返回这个结果。
如果我们能够计算这个数值,那么将使我们实验的功能更加强大。我们现在无需对一个n值运行多次来估计平均值,而只需一个简单的实验便可以得到真实的平均值。不幸的是,实现这个功能是要付出代价的:这个程序的运行时间正比于3n(如果是自行参考(self-referential)的,那么用本章中给出的技术来分析运行时间将是一个很有趣的练习)。
示例2-7中的代码需要一定的时间开销,因为它重复计算了中间结果。当在程序中出现这种情况时,我们通常会使用动态编程来存储中间结果,从而避免重复计算。因此,我们将定义一个表t[N+1],其中在t[n]中存储c[n],并且按照升序来计算它的值。我们将用N来表示n的最大值,也就是进行排序的数组的大小。在示例2-8中给出了修改后的代码。
【示例2-8】 在Quicksort中使用动态编程来计算
t[0] = 0
for (n = 1; n <= N; n++)
sum = 0
for (i = 1; i <= n; i++)
sum += n-1 + t[i-1] + t[n-i]
t[n] = sum/n
这个程序只对示例2-7进行了细微的修改,即用t[n]来替换c(n)。它的运行时间将正比于N2,并且所需的存储空间正比于N。这个程序的优点之一就是:在程序执行结束时,数组t中将包含数组中从元素0到元素N的真实平均值(而不是样本均值的估计)。我们可以对这些值进行分析,从而生成在Quichsort算法中统计比较次数的计算公式。
我们现在来对程序做进一步的简化。第一步就是把n-1移到循环的外面,如示例2-9所示。
【示例2-9】 在Quicksort中把代码移到循环外面来计算
t[0] = 0
for (n = 1; n <= N; n++)
sum = 0
for (i = 1; i <= n; i++)
sum += t[i-1] + t[n-i]
t[n] = n-1 + sum/n
现在将利用对称性来对循环做进一步的调整。例如,当n为4时,内部循环计算总和为:
t[0]+t[3] + t[1]+t[2] + t[2]+t[1] + t[3]+t[0]
在上面这些组对中,第一个元素增加而第二个元素减少。因此,我们可以把总和改写为:
2 * (t[0] + t[1] + t[2] + t[3])
我们可以利用这种对称性来得到示例2-10中的Quicksort。
【示例2-10】 在Quichsort中利用了对称性来计算
t[0] = 0
14
for (n = 1; n <= N; n++)
sum = 0
for (i = 0; i < n; i++)
sum += 2 * t[i]
t[n] = n-1 + sum/n
然而,在这段代码的运行时间中同样存在着浪费,因为它重复地计算了相同的总和。此时,我们不是把前面所有的元素加在一起,而是在循环外部初始化总和并且加上下一个元素,如示例2-11所示。
【示例2-11】 在Quicksort中删除了内部循环来计算
sum = 0; t[0] = 0
for (n = 1; n <= N; n++)
sum += 2*t[n-1]
t[n] = n-1 + sum/n
这个小程序确实很有用。程序的运行时间与N成正比,对于每个从1到N的整数,程序将生成一张Quicksort的估计运行时间表。
我们可以很容易地把示例2-11用表格来实现,其中的值可以立即用于进一步的分析。在2-1给出了最初的结果行。
表2-1 示例2-11中实现的表格输出
N Sum t[n]
0 0 0
1 0 0
2 0 1
3 2 2.667
4 7.333 4.833
5 17 7.4
6 31.8 10.3
7 52.4 13.486
8 79.371 16.921
这张表中的第一行数字是用代码中的三个常量来进行初始化的。下一行(输出的第三行)的数值是通过以下公式来计算的:
A3 = A2+1 B3 = B2 + 2*C2 C3 = A2-1 + B3/A3
把这些(相应的)公式记录下来就使得这张表格变得完整了。这张表格是“我曾经编写的最漂亮代码”的很好的证据,即使用少量的代码完成大量的工作。
但是,如果我们不需要所有的值,那么情况将会是什么样?如果我们更希望通过这种来方式分析一部分数值(例如,在20到232之间所有2的指数值)呢?虽然在示例2-11中构建了完整的表格t,但它只需要使用表格中的最新值。因此,我们可以用变量t的定长空间来替代table t[]的线性空间,如示例2-12所示。
【示例2-12】 Quicksoft 计算——最终版本
sum = 0; t = 0
15
for (n = 1; n <= N; n++)
sum += 2*t
t = n-1 + sum/n
然后,我们可以插入一行代码来测试n的适应性,并且在必要时输出这些结果。
这个程序是我们漫长学习旅途的终点。通过本章所采用的方式,我们可以证明Alan Perlis的经验是正确的:“简单性并不是在复杂性之前,而是在复杂性之后” ("Epigrams on Programming," Sigplan Notices, Vol. 17, Issue 9)。
Ⅱ C语言怎么对英文字母排序
根本就是.现代的英文字母就是拉丁字母
古代没有拼音,就使用反切,就是用两个认识会念的字,取第一个的声母,取第二个的韵母,拼合起来就行了.
古代,中国的回族兄弟不学汉字,学习阿拉伯语,但他们用阿拉伯文的字母来拼写口语(汉语),所以这是中国最早的拼音。
元朝,蒙古统治者用改变了的藏文的字母来拼写汉语等语言,叫八思巴字。虽然不是专门拼写汉语的,但是,也算汉语拼音的一种吧。
明朝,西方传教士用拉丁字母拼写汉语,是中国最早的拉丁字拼音。
清末明初,出现了用简单的古字表现汉语语音的拼音方式。民国年间,政府制定了“注音字母”,就是这个系统的集中表现。现在台湾依然使用。但是,同时也出现了拉丁字的拼音运动,而且,跟左翼人士的政治运动结合很密切。
共和国成立后,立即由政府制定了“汉语拼音方案”,就是现在使用的这一套方案。联合国也承认的。
**《现代汉语拼音方案》的出笼 **
1949年中华人民共和国成立后,就马上着手研制拼音方案。1949年10月成立了民间团体“中国文字改革协会”,协会设立“拼音方案研究委员会”,讨论拼音方案采用什么字母的问题。
在1951年,毛泽东就指出:“文字必须改革,必须走世界文字共同的拼音方向”。但是,究竟采用什么形式的拼音方案,他本人也是经过了反复斟酌的。毛泽东到苏联访问时,他曾经问斯大林,中国的文字改革应当怎么办;斯大林说,中国是一个大国,可以有自己的字母。毛泽东回到北京之后,指示中国文字改革研究委员会制订民族形式的拼音方案。同时,上海的新文字研究会停止推广北方拉丁化新文字,等待新方案的产生。
1955年10月15日,全国文字改革会议在北京举行。叶籁士在发言中说:“从1952年到1954年这个期间,中国文字改革研究委员会主要进行汉字笔画式拼音方案的研究工作,经过了三年的摸索,曾经拟定几种草案,都放在《汉语拼音方案草案初稿》(汉字笔画式)里头”。这次会议上印发给代表们六种拼音方案的草案,有四种是汉字笔画式的,一种是拉丁字母式的,一种是斯拉夫字母式的。会议之后,当时的中国文字改革委员会主任吴玉章向毛泽东报告,他说,民族形式方案搞了三年,难以得到大家都满意的设计,不如采用拉丁字母。毛泽东同意采用拉丁字母,并在中央开会通过。
在中国制定拼音方案的时候,苏联已经不再搞拉丁化,改为搞斯拉夫化,把所有的拉丁化民族文字一律改成了斯拉夫字母。蒙古人民共和国也把蒙古字母改成了斯拉夫字母。50年代,中国向苏联一边倒,有人主张采用斯拉夫字母,跟苏联在文字上结盟。苏联派到中国的语言学家谢尔久琴柯也提出使用斯拉夫字母的建议。据说,苏联的一位副总理来中国访问时,曾经向陈毅副总理说,希望中苏两国都采用相同的字母。陈毅副总理回答说,中国文化必须跟东亚和东南亚联系,东亚和东南亚都习惯用拉丁字母。这样,中国才没有采用斯拉夫字母。如果我国当时采用了斯拉夫字母,我们今天使用计算机将会遇到更多的困难。中国政府当时在字母选择上的决策,是非常正确的。
1956年1月20日,毛泽东在知识分子问题会议上,发表了赞成拉丁字母的讲话。他说,“吴玉章同志的发言讲的很好。关于文字改革的意见,我很赞成。在将来采用拉丁字母,你们赞成不赞成呀?我看,在广大群众里头,问题不大;在知识分子里头,有些问题。中国怎么能用外国字母呢?但是,看起来还是采用这种外国字母比较好。吴玉章同志在这方面说得很有理由。因为这种字母很少,只有二十几个,向一面写,简单明了。我们汉字在这方面实在比不上。比不上就比不上,不要以为汉字那么好。有几位教授跟我说,汉字是‘世界万国’最好的一种文字,改革不得。假使拉丁字母是中国人发明的,大概就没有问题了。问题就出在外国人发明,中国人学习。但是,外国人发明中国人学习的事情是早已有之的。例如阿拉伯数字,我们不是久已通用了吗?拉丁字母出在罗马那个地方,为世界大多数国家所采用。我们用一下,是否就大有卖国的嫌疑呢?我看不见得。凡是外国好的东西,对我们有用的东西,我们就是要学,就是要统统拿过来,并且加以消化,变成自己的东西。我们中国历史上,汉朝就是这么做的,唐朝也是这么做的。汉朝和唐朝,都是我国历史上很有名很强盛的朝代。他们不怕吸收外国的东西,有好的东西就欢迎。只要态度和方法正确,学习外国的好东西,对自己是大有好处的。”(转引自郑林曦《论语说文》)。
此期间,群众中也创制了不少的文字方案,寄到中国文字改革委员会。根据统计资料,从1950年到1955年8月31日全国文字改革工作会议为止,寄来的方案有655个,从1955年8月31日到1958年2月汉语拼音方案公布为止,寄来的方案有1000多个,从1958年2月到1980年文化大革命结束为止,寄来的方案有1667个。群众设计的各种各样的文字方案总共有3300多个。这种创制造文字方案的积极性,在中国文化的发展历史上是空前的。这充分说明了语言规划的社会性。
1955年2月,中国文字改革委员会设立了“拼音方案委员会”,开始设计汉语拼音方案,提出了《汉语拼音方案(草案)》。1956年2月12日,中国文字改革委员会发表《汉语拼音方案(草案)》,公开征求意见。这个草案共有31个字母,其中有5个新字母(无点的i;长脚的n;带尾的z,c,s),以便实现“一字一音”,不用变读和双字母。草案发表后在全国范围内引起热烈的讨论,甚至海外华侨和留学生也提出了自己的意见。
1955年10月,国务院成立“汉语拼音方案审定委员会”,经过一年的工作,于1957年10月提出《修正草案》,11月1日由国务院全体会议第60次会议作为新的《汉语拼音方案(草案)》通过,提请全国人民代表大会审议,1958年2月11日,第一届全国人民代表大会第五次会议正式批准《汉语拼音方案》。1958年秋季开始,《汉语拼音方案》作为小学生必修的课程进入全国小学的课堂。《汉语拼音方案》是拼写规范化普通话的一套拼音字母和拼写方式,是中华人民共和国的法定拼音方案。这个方案吸取了以往各种拉丁字母式拼音方案,特别是国语罗马字和拉丁化新文字拼音方案的优点,它是我国三百多年拼音字母运动的结晶,是六十年来中国人民创造拼音方案经验的总结,比任何历史上一个拉丁字母式的拼音方案都更加完善和成熟。
《汉语拼音方案》有如下特点:
①只用国际通用的26个字母,不增加新字母;
②尽量不用附加符号(只用了两个附加符号);
③尽量不用变读;
④采用y,w和隔音符号“'”来隔音;
⑤采用四个双字母zh, ch, sh, ng;
⑥采用四个声调符号来表示阴平、阳平、上声、去声四个调类;
⑦采用拉丁字母通用的字母表顺序,并确定了汉语拼音字母的名称。
周恩来在《当前文字改革的任务》的报告中说:“现在公布的汉语拼音方案,是在过去的直音、反切以及各种拼音方案的基础上发展出来的。从采用拉丁字母来说,它的历史渊源远则可以一直追溯到350多年以前,近则可以说是总结了60年来我国人民创制汉语拼音方案的经验。这个方案,比起历史上存在过的以及目前还在沿用的各种拉丁字母的拼音方案来,确实更加完善。”
《汉语拼音方案》自制订以来,得到迅速的推广和应用。主要有如下方面。
①用于给汉字注音:从1958年秋季开始,全国小学的语文课本采用汉语拼音给汉字注音,接着,中学教科书、字典、词典以及通俗读物、扫盲课本也采用汉语拼音注音。《人民日报》等用汉语拼音字母给难字注音。1958年10月,中央工商行政管理局和中国文字改革委员会联合发出通知,要求各种商标图样和商品包装上加注汉语拼音字母。邮电局名、铁路站名、气象站名、城市街道名也都使用汉语拼音标注。1982年6月19日国家标准局发布了国家标准《中文书刊名称汉语拼写法》,规定国内出版的中文书刊在封面、或首页、或封底、或版权页上加注汉语拼音书名、刊名。
②用于教学普通话:《汉语拼音方案》公布后,陆续出版了利用汉语拼音编写的普通话教材、读物、字表、字典、词典,促进了普通话的推广和普及。在对外汉语教学中,《汉语拼音方案》已经成为外国人学习汉语进行全面训练的不可缺少的工具。
③用于字典、词典的注音、排序,书刊的索引。75卷的《中国大网络全书》采用汉语拼音排序,正文的每一个条目都注上了汉语拼音。
④作为我国少数民族创制和改革文字的共同基础。我国已经有壮族、苗族、侗族、哈尼族、僳僳族、佤族、黎族、纳西族、土族等少数民族采用汉语拼音字母相一致的字母形式。
⑤用于不便使用或不能使用汉字的领域:《汉语拼音方案》为盲文的点字和聋哑人的手语的制定提供了依据。汉语拼音还可用于手旗通讯、灯光通信中,用同汉语拼音字母对应的手旗讯号或灯光符号来传递信息。在电子计算机输入汉字方面,拼音输入法是一种最为普及的输入方法。
1977年,联合国地名标准化会议决定采用《汉语拼音方案》作为拼写中国地名的国际标准。1978年9月,国务院转发了《关于改用汉语拼音方案作为我国人名地名罗马字母拼写法的统一规范的报告》。1982年8月1日,国际标准化组织(ISO)文献工作技术委员会决议采用汉语拼音作为世界文献工作中拼写中国专有词语的国际标准,标准号:ISO7098-1982。《汉语拼音方案》已经从中国标准发展成为国际标准。
汉语拼音目前还是拼写汉字的辅助工具.
Ⅲ 关于网络英语新词的论文
总括来说,世界上语言可分为两大类。一类是目前已经没有人使用的,已不通行的,或已被废弃了的,称为“死”语言(dead language);另一类是目前仍然通行的称为“活”语言(living language)。希伯莱语、古拉丁语等属于前者;而汉、英、日、西、法、德、俄等语言俱属于后者,而且是其中最通行的几种。
“活”的语言有一个很重要的共通点,就是它们都随着时代的发展而变化。英语上这样,其他的语言也是如此。不过,由于英语在世界上的通行度和通行范围都胜于其他各种语言,所以其变化尤烈。
英语的变化主要表现于语法和词汇两方面,并籍这两种变化推动发展,构成现代英语的基础。近二十年来语言学理论最重大的进展之一是出现了“转换——生成语法”(Transformational-generative Grammar),这种语言学理论的诞生使英语进一步科学化。与此同时,大量新词汇的涌现使英语的表达力加强了,形式丰富了,因而使英语更趋生活化。
新词汇的产生
新词汇到底是怎样产生的?
当人们发现新事物,遇到新问题,总结了新经验,发展了新思想的时候,便需要新字和新词来表达,这是因为旧有的、沿袭使用的表达方法已经不适合或不敷应用了。另一方面,由于以英语作母语及第二语言的国家遍及全球各洲,而各地的风 土人情、生活习惯和社会环境大有区别,这就必然会出现不同的表达形式和用语,而这些语汇中不少会被逐渐吸收进经典的英语辞典中,成为语言的一部分。
在目前日益进步的社会里,科学和技术是新词汇的主要供应者,每当某一门科学发展到一个新阶段的时候,就有相当大一批新词涌现。在这些新词当中,很多是该等科学的专用词汇,鲜为外行人所知晓,只有专科字典及词典才有收栽;但是,其中也有不少常被应用和引用,结果成了一般人所喜闻乐道的用语。
例如,当美国太空人成功地登陆用于月球时,英语中出现了moonwalk(月球漫步),lunar rove(月球车),moonrock(月球标本车)等一系列有关的用词。由于近年发射了不少人造卫星绕月运行,故此就很必要地创出了apolune(远月点)和perilune(近月点)二词。太空船与太空站在空间会合对接,使docking增添了一个新含义(靠泊),同义的还有linkup。发射太空船被视为人类科学发展的象征,故很受注意。因此,不少与太空船有关的用词已被广泛使用,如CM(command mole:指令舱,指挥舱),splashdown (溅落),space sickness(宇航病),space age (太空时代)等。在谈到探索deep space(深空间,远空间)和其他太空现象时,quasar(类星射电源),pulsar(脉冲星),neutron srar (中子星)及神秘的black hole (太空黑洞)等已是耳熟能详的用语。
近二十年来,遗传学的迅速发展创造了许多使人耳目一新的词汇,如genetic code(遗传密码),codon(密码子),DNA(脱氧核糖核酸),transfa RNA(传输核糖核酸),messenger RNA(信使核糖核酸),transcription(信使核糖核酸的形成)等。这些新词流行日广,连到一般的书刊报道都有应用,故此早已广大读者所接受。
近年来发展迅猛的大了电脑工业带来的新词汇也着实不少。常听常用的包括FORTRAM(公式翻译程序语言),COBOL(面向商业的通用语言),ALGOL(算法语言),BASIC(初学者的通用符号指令码),absolute address(绝对地址),data bank(资料库,数据库),floppy dise(柔性塑料磁盘)pushdown(下推存储器)等等。旧有词如keyboard,terminal,memorym bit等也分别加添了新用法。
医学的飞跃发展同样带来了大批新词,包括了医学上的技术性用语及新制成的药品名称,新发现的病菌、病毒等。其中如hotoscanning(光扫描),open heart surgery(开心手术),picornabirus(换心人),microcirculation(微血管循环)等都是近期出现的。一些用词如the pill(口服避孕丸),test-tube baby(试管婴儿),transsexual operation(变性生术)等已成日常用语。
核物理学发展的结果,好象要把人们带进微观世界。kron(K介子),muon(μ介子),pion(π介子)等陆续发现,lepton(轻子),baryon(重子)的分别,当然还有引起轰动的quark(夸克)。假设上由各种antimatter(反物质)如antiproton(反质子),antineutrino(反中微子),antiquark(反夸克)等组成的antiworld(反物质世界)也备受重视。
数学和其他学科也在不停地发展。在通俗的教研、科普读物中,不难发现以下的名词术语:NOT("非"逻辑算子),parametric equation(变数方程),近年中小学推行的newmath(新数),artificial intelligence(人工智能),magmetocardiogram(磁性心动扫描记图),IC (集成电路),piscicide (鱼类灭绝),hot mooner (热月学家),Sealab(海底实验室),radiosterilization(放射性消毒)等。新的学科也在不断形成,例如bionics(仿生学),cryosurgery(冷冻手术),macrometereology(大气象学),ocean engineering(海洋工程学),phytochemistry(植物化学),biotelemetry(生物遥测学),astrionics(太空电子学)等数十种新的学科在发展和壮大。
军备竞争激烈,武器日新月异,自然也产生了不少新词汇。ABM(antiballistic missile:反弹道导弹),MIRV(multiple independently-targetedreentry vehicle:多弹头分导重返大气层运载工具),the Bomb(核威慑),helilift(使用直升机运输),Green Berets("绿色贝雷帽"特种部队),grunt(步兵,beam weapons(死光武器)等,几乎成了家喻户晓的用语。
交通工具的改进,也使人有瞠目结舌之感。天空上充斥着SST(supersonic transport:超音速运输机),airbus(空中巴士),air-taxi(空中的士);英法合制的Concorde(协调式飞机)在航空史上当然也占着重要地位。HST(hyper-sonic transport:特超音速飞机)的诞生,使飞机工业有了新发展。一些富裕的有闲人士经常乘搭喷气式飞机到各地旅游集会,成了一个特殊的阶层,称为jetset。喷气式飞机的乘客有时也会患上这样或那样的不适症状,统称为jetsyndrome。在水面和陆地上,新型的交通工具接连出现,包括ACV (air-cushion vehicle:气垫式运载工具),ATV(all-terrain vehicle:全地形车),hovercraft(气垫船),freight-liner(货柜火车),bullet train(子弹车),aerotrain(悬浮火车)等。
除了科学和技术之外,动荡的政局、日趋变革的社会环境和世界性的文化及各方面的交流,也是英文新字的来源。例如自六十年代初期“-in 运动”的兴起、转化和发展,使这个“家族”膨胀得使人吃惊。从第一代的sit-in(静坐示威)到第二代的teach-in (宣讲会),以至第三代的be-in(颓废派的社交集会),一共出现了数十个-in的用词,其演变之速,实令人咋舌。
近年来,世界政坛风云变幻。西欧诸国为加强团结,发展贸易,组织了EEC(European Economic Community:欧洲经济共同体)。中东和南美、非洲的石油输出国也组织了OPEC(Organization of Petroleum Exporting Countries:石油输出国组织)。在美国爆发了水门事件之后,Watergate一字被广泛应用以指任何的政治丑闻在政府内部,主张用武力解决争端的一派人被称为hawk(鹰派),主张和平手段的称为dove(鸽派),而dawk是介乎鹰派),主张和平手段的称为dove(鸽派),而dawk是介乎鹰派与鸽派的消极反战者。其他的政治用词如establishment(政府),atomic club(原子俱乐部),advance man(先行人员,助选人员),pilitical animal(政治动物)等亦常见用于报刊之上。
世界性的经济危机,通货膨胀和工商业的发展也是新词的重要来源之一。ASP(American Selling Price美国售价),slumpflation(萧条膨胀),added-value tax(增值税),Eurodollar(欧洲美元),petrodollar(石油美元),revenue sharing(国库分享)等都是近期产物。
社会的变革在过去两个年代中造成了很大的影响,不少基本意识形态受到了冲击。女权运动的爆发产生了像Women'sLib(妇解运动),chairperson(主席),malechauvinist(大男子主义者),girlcott(抵制)等新用词,但也促成了Men's Lib(男子解放运动)的诞生。六十年代末期美国黑人运动Black Power(黑色权力)爆发后,不少表示"…运动"的用语即仿此而出现,计有:Brown Power(褐色权力),Flower Power(花癫派权力),student power(学生权力),Red Power(红色权力)等,更有人戏谑地创出green power一语,意指“金钱魔力”(因美元背面是绿色的)。
道德观念的转变造成了generation gap(代沟),而gap字的用途又在此基础上多样化,以致产生了credibility gap(信誉沟),culture gap(文化沟),communication gap(通信隔阂)等新词。西方青年的思想与旧习俗社会的脱离,迫使他们要寻找发泄的途径。于是Mary Jane(大麻),LSD(迷幻药),upper(兴奋剂),soft drug(软毒品),hard drug(硬毒品),headshop(迷幻商店),commune(嬉皮士公社),psychedelphia(迷幻村)等词又应运而生。一代一代的颓废派亦相继出现:hippie(嬉皮士),flower children(花癫派),Gentle People(温和人),street people(街头颓废派),teenybopper(少年颓废派),等等。
人们对环境污染的注视在近年特别显著,这可见诸环境学家的倡议设立EarthDay(地球清洁日)和Eargh Week(地球清洁周)。"污染"这一用词无日不见出现于报章杂志之中,较新的词汇包括environmental pollution(环境污染) ,heat/thermal pollution(热污染), internal pollution(体内污染),visual pollution(视觉污染),antipollutionist(反污染者),environmentalist(环境问题专家),dystrophication(河湖污染)等。
在教育和语言研究方面,也因教学方法和教学用具的改革而出现了一系列的新词,如schoolbook(教科书式的),pass-fail(取否法),CAI(computer-assisted instruction(电脑辅助教学),audiovisuals(视听教材),coedism(男女同校教育),preppie(预科学生),open classroom(开放教室),polyversity(多元大学),megaversity(超级大学),generative grammar(生成语法),kernel sentencd(核心句)和Chomskian(乔姆斯基理论的)等。
娱乐和体育亦是较大的新词汇供应者。电台和电视台的audience rating(视听率),call-in(电话节目),sitcom(长寿单元喜剧),soup opera(肥皂剧),prime time(黄金时间),imstant replay(即时重播),VTR(磁带录像),VCR(盒式录像)等都是人所共知的用语了。多姿多采的新体育运动也丰富了英语的词汇。近期新兴的玩意包括skate-boarding(滑板运动),skydive(缓张伞跳伞)。land/sand yacht(沙滩艇,陆地风帆),hang glider(飞行风筝)是较高级的玩物。一些组合词如cyclo -cross(自行车越野赛),roller hockey(滚轴冰球),demolition derby(撞车大赛)等也因新型运动的兴起而相继出现。体育家们还发明了slimnastics(减肥体操),isometrics(静力锻练)等健美身体、增强力量的方法,当然还有流行海外的中国kung fu(功夫)和日本的aikido(合气道)等。
很多的新词汇实际上已经进入人们的日常生活和每个家庭之中。现在,很多家庭里都有VCD(盒式录像机);而原来称为television set的电视机现被谑称为television set 的电视机现被谑称作box, gogglebox, idiot box, idiot'slantern。microwave oven(微波电锔炉),autotimer(自动开关器)等是科技的新产物。videophone/picturephone(电视电话)亦在大量生产中。音响领域中的新词也有quadraphony(四声道),sensurrornd(杜比系统)等。七十年代最后一年才出产的Polarvision System(宝丽视系统)现已流行世界。较早期出现的telex(用户电报)更是大公司和商行必设的通讯系统,当然还有IDDD(International DirectDistance Dialling:国际直通长途电话)。过去几年生产了一种拉盖即开的罐装饮品,这种引起浪费和制造废品的用完即丢的容器也有新名称:thrwaway 或diposable 。
为了加强表达的力量,不少新的日用词汇被创造出来了。这一类的用词近年来大行其道,若不弄懂实难秘英、美、人士交谈。举例而言,精神病医院的新名称是funny farm,而fat farm却是减肥中心;在停车场向违例停泊的车辆派告票的女警察被称为meter maid(老虎机女郎),用油特多的"大食车"是gas eater。容易到手、尤其是以不正当手段得来的金钱叫做quick buck等等。
事实上,新词汇产生的原因及其来源非常广泛,可以说是由世界上各式各样的变化促成的,故此无法尽量罗列。总而言之,大量新词的涌现说明了社会在变化,英语在变化。
新词汇的构成
根据研究和统计的结果,在六十年代和七十年代中,共出现了一万多新的英文词汇。然而,这个数目所包括的仅是已经确立并被广泛使用的字和词,一些被大多数人接纳、太专门化或罕用的词语尚不算在内。按这一万多的新词汇所做的研究,其构成法可以分为四大类。
<1>创新法—— 即创造出一个全新的英文字。据研究结果显示,用这一种方法创出的新字新词所占比例较小,因为到目前为止,英语已经有了相当雄厚而根基巩固的“班底”,新词汇可由旧字和原有的词根变化出来。用创新法构成的新词汇包括。
(a)少量的社会科学及自然科学用词,如:periapsis(近拱点),cladistics(遗传分类学),penetralium(核心组织),ekistics(城市与区域计划学),isomorphism(同构),quark(夸克);
(b)已通用的新产品的商标名(代表或用来指同一类产品)和已被用作普通名词的专有名称,如:lasercomp(激光电脑排版机),dolby system(杜比系统),miniteller(微型出纳机),Rent-a-Train出租列车).polarvision system(宝丽视系统——即影即有电影系统),sealab(海底实验室),watergate(政治丑闻),Frisbee(玩具飞碟);
(c)人名和地名等专有名词衍变出的普通词类,如:Hitchcockian(希治阁式的,悬疑的),Chandler wobble(钱德勒振荡),cocacolonization(美国化),a-go-go(阿哥哥舞厅),Mcluhanesque(麦克卢汉式的,电子化的);
(d)经常被使用的字首缩略词(acronym)和普通的缩写语(abbtreviation),如:STLT(Strategic Arms Limitation Talks:限制战略武器会谈),COBOL(Coommon business Oriented Language:面向商业的通用语言),BADGE(Base Air Defense Ground Environment:地域半自动防空警备体系),ACV(air-cushion vehicle:气垫式运载工具),EEC(European Economic Community:欧洲经济共同体,欧洲共同市场),comsat(communication satellite:通讯卫星);
(e)新的习语,包括以前未被收入正式词典中的俚语(slang)和口语(colloquialism),如:posh(非常时髦的),bonkers(疯狂的),easy meat(易辨的事),like a lead balloon(毫无作用),can of worms(一团糟),merchant of death(死亡贩子),go for broke(尽最大努力),carry the can(面对责备,负起责任),selllike T shirts(货如轮转)。
用这一种方法创成的新字新词中,还包括了一种把长字缩短而保持原义的新形式,如deli(delicatessen:熟食店),mod(modern:时髦的,摩登的),nat(mationalist:民族主义者),neut(neutron bomb:中子弹),divi(dividend:红利),disco (discotheque:迪斯科,唱片夜总会)等。这种新形式与原字同样流行,有睦甚而超过。
一部分商标名被接纳为普通用词后,用法、含意和词类属性上亦起了变化。如telex原为名词(用户电报,电报用户直通电路),现可作动词用,表示"以用户电报通知";xerox原为名词(乾式影印,静电影印),现可作动词;STP原为汽油附加剂,现指幻觉剂;Tom it一词中,表示"逆来顺受"。
<2>结合法——在旧有用词的基础上,加上前缀、后缀或其他构词成分构成新词,或使两个旧有用词或旧有用词的部分结合起来成为新词,或使两个构词成分结合成新词。利用这种方法构成的新词汇所占比例较大,词义亦较易理解推出。例如:microelectronics(micro+electronies:微电子学),antididnapping(anti +kidnapping:防绑架的),autocue(auto+cue:自动提示器),electrofishing (electro+fishing:电力捕鱼),photobotany(photo+botany:光植物学),ecationese(ecation+ese:教育界术语),Pekingology(Peking+o+logy:北京学,北京问题研究),Dullesian(Dulles+ian:杜勒斯式的),robotesque(robot+esque:机械人似的);
Housrmanship(house+manship:英议员的雄辩),Americandom(American+dom::美国人的世界),cryptosecurity(crypto+security:秘密安全部的),paint-in(paint+in:油漆示威),pedestrianization(pedestrian+ization:人行道化),peacenik(peace+nik:反战运动分子);
diet pill(减肥丸),easy meat(易辨的事;易得的东西),Great Society(大社会),hard science(硬科学,自然科学),landmark(陆标),cardcarrying(典型的),carbecue(烤车架),boatel(汽艇旅馆),chunnel(水底列车隧道);
electrophobia(electro+phobia:电气恐怖症),bionics(bio+onics:仿生学),quarkonics(quark+onics:夸克学)。
有一部分前缀、后缀及构词成分是特别多产或特别活跃的,其中包括anti-,auto,bio,electro-,Euro-,extra-,geo-,hyper-,-ian,immuno-,in-,-in,inter-,intra-,-logy,macro-,micro-,mini-,multi-,-nik,non-,prar-,-phobia-,photo-,poly-,psycho-等,此等构词成分在构成新词的过程中起着相当积极的作用.
<3>添义法---使旧词添上新释义.近年来,不少沿用的旧词增添了新的含义.这一类形旧义新的字为数不少,碰上和使用时宜加注意,例如:
Happening:旧用法指一次事件,新用法指“哈普宁艺术”(一种目的使观众意外、惊奇和投入的舞台或其它形式的演出等。
这一部分的新词还包括了一些过去只能作为某一种词类使用,现在却可作别一词类运用的旧字。如H-bomb过去是名词(氢弹),现在可作动词,表示“用氢弹袭击”;lookingglass过去是名词,指“镜子”,现在可作形容词用,表示“颠倒的”,“乱七八糟的”等意。又如soul一字既加添了新意,指“黑人文化”,更可作形容词,泛指“黑人的”,如soul music(黑人音乐,灵乐),soul food(黑人食物)等。
一个值得注意的构词形式是back-formation,即所谓“逆序造词”或“倒反构词”。这是把一个现存的词的真正后缀或貌似后缀的部分脱落而形成该词的另一种词类。例如先有 free association(自由发言,自由联想),才有freeassociate;one-up(胜人一筹的,占上风的)和 one-upman胜...一筹,占...的上风)是从one-upmanship 一词倒反构成的。laser(激光)本是一字首缩略词,但是由于像是从lase变出来的名词,故英、美人士又创出lase这个动词,表示“放射激光”,“使受激光照射”。
<4>外借法---借用或吸收外来语。这种方法由来已久,英语中不少字和词其实是从外国借来使用,最后成了英语中不可缺少的部分。这些外来语很多保留原来的样貌,有些拉丁化拼音拼写成英语,亦有些被改头换面或按义译成英语的。例如:
discothèque <法>:唱片夜总会
autostrada <意>:高速公路
autopista <西>:高速公路
mao tai <中>:茅台酒
sushi <日>:寿司
westpolitik <德>:(东欧国家的)西方政策
samizdat <俄>:地下出版(物)
favela <葡>:贫民窟,木屋区
haman <阿拉伯语>:海玛姆(伊朗公众浴堂)
又如black humor (黑幽默)原为法语humour noir,英美人士借用后按义改成正式英语;同样地,found object (拾得艺术品)来自法语objet trouve。kirin来自日语kylin,后者又源于汉语ch’i lin(麒麟的旧拼写法)。
(本文是作者为《10000英文新字字典》写的导言)
Ⅳ 用C++交换排序
所谓交换,就是根据序列中两个记录值的比较结果来对换这两个记录在序列中的位置。交换排序的特点是:将键值较大的记录向序列的尾部移动,键值较小的记录向序列的前部移动。常见的交换排序有冒泡排序(Bubble Sort),鸡尾酒排序(Cocktail Sort),奇偶排序(OddEven Sort),地精排序(Gnome Sort),快速排序(Quick Sort),臭皮匠排序(Stooge Sort),梳排序(Comb Sort),Bogo排序(Bogo sort)。下面介绍前六种:
(一)冒泡排序
最差时间复杂度:O(n^2)
最优时间复杂度:O(n)
平均时间复杂度:O(n^2)
最差空间复杂度:总共O(n),需要辅助空间O(1)
稳定性:稳定
冒泡排序(Bubble Sort),它重复地走访过要排序的数列,一次比较两个元素如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。
冒泡排序算法的运作如下:
1.比较相邻的元素。如果第一个比第二个大,就交换他们两个。
2.对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
3.针对所有的元素重复以上的步骤,除了最后一个。
4.持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
实现代码:
[cpp] view plain
void BubbleSort(int *a, int len)
{
for (int i=0; i<len; i++)
{
for (int j=len-1; j>i; j--)
{
if (a[j]<a[j-1])
swap(a[j], a[j-1]);
}
}
}
(二)鸡尾酒排序
最差时间复杂度:O(n^2)
最优时间复杂度:O(n)
平均时间复杂度:O(n^2)
稳定性:稳定
鸡尾酒排序(Cocktail sort),是冒泡排序的一种变形。它与冒泡排序的不同之处在于排序时是以双向在序列中进行排序。数组中的数字本是无规律的排放,先对数组从左到右进行冒泡排序(升序),把最大值放到最右端,然后对数组从右到左进行冒泡排序(降序),把最小的数字放到最左端。然后再以此类推,以此改变冒泡的方向,并不断缩小未排序元素的范围。直到在一趟双向冒泡后没有发生交换,排序结束。
实现代码:
[cpp] view plain
void CocktailSort(int* a, int len)
{
int bottom = 0;
int top = len-1;
bool swapped = true;
while (swapped)
{
swapped = false;
for (int i=bottom; i<top; i++)
{
if (a[i]>a[i+1])
{
swap(a[i], a[i+1]);
swapped = true;
}
}
top = top-1;
for (int i=top; i>bottom; i--)
{
if (a[i]<a[i-1])
{
swap(a[i], a[i-1]);
swapped = true;
}
}
bottom = bottom+1;
}
}
(三)奇偶排序
最差时间复杂度:O(n^2)
稳定性:稳定
奇偶排序(OddEven Sort),是一种相对简单的排序算法,最初发明用于有本地互联的并行计算。此算法通过比较数组中相邻的(奇-偶)位置数字对,如果该奇偶对是错误的顺序(第一个大于第二个),则交换。下一步重复该操作,但针对所有的(偶-奇)位置数字对。如此交替下去,直到不发生交换,则排序结束。
在并行计算排序中,使用该算法,每个处理器对应处理一个值,并仅有与左右邻居的本地互连。所有处理器可同时与邻居进行比较、交换操作,交替以奇-偶、偶-奇的顺序。该算法由Habermann在1972年最初发表并展现了在并行处理上的效率。但在单处理器串行运行此算法,类似冒泡排序,较为简单但效率并不特别高。
实现代码:
[cpp] view plain
void OddEvenSort(int *a, int len)
{
bool swapped = true;
while (swapped)
{
swapped = false;
for (int i=0; i<len-1; i=i+2)
{
if (a[i]>a[i+1])
{
swap(a[i], a[i+1]);
swapped = true;
}
}
for (int i=1; i<len-1; i=i+2)
{
if (a[i]>a[i+1])
{
swap(a[i], a[i+1]);
swapped = true;
}
}
}
}
(四)地精排序
最差时间复杂度:O(n^2)
最优时间复杂度:O(n)
平均时间复杂度:O(n^2)
稳定性:稳定
地精排序(Gnome Sort),被Dick Grune称为最简单的排序算法。整个算法只有一层循环,默认情况下前进冒泡,一旦遇到冒泡的情况发生就往回冒,直到把这个数字放好,然后继续前进,前进到数组最后一个数结束。此排序算法虽然代码极短,但效率不高。
实现代码:
[cpp] view plain
void GnomeSort(int *a, int len)
{
int i=0;
while (i<len)
{
if (i==0 || a[i-1]<=a[i]){
i++;
}
else {
swap(a[i], a[i-1]);
i--;
}
}
}
(五)快速排序
最差时间复杂度:O(n^2)
最优时间复杂度:O(nlogn)
平均时间复杂度:O(nlogn)
稳定性:不稳定
快速排序(Quick Sort),使用分治法策略来把一个串行分为两个子串行,左边子串的值总小于右边的子串。此算法的三个步骤:
1.分解:将数组A[l...r]划分成两个(可能空)子数组A[l...p-1]和A[p+1...r],使得A[l...p-1]中的每个元素都小于等于A(p),而且,小于等于A[p+1...r]中的元素。下标p也在这个划分过程中计算。
2.解决:通过递归调用快速排序,对数组A[l...p-1]和A[p+1...r]排序。
3.合并:因为两个子数组时就地排序,将它们的合并并不需要操作,整个数组A[l..r]已经排序。
实现代码(其他实现方法见“三种快速排序算法的实现”):
[cpp] view plain
int partition(int* a, int left, int right)
{
int x = a[right];
int i = left-1, j = right;
for (;;)
{
while(a[++i] < x) { }
while(a[--j] > x) { if(j==left) break;}
if(i < j)
swap(a[i], a[j]);
else break;
}
swap(a[i],a[right]);
return i;
}
void quickSort(int* a, int left, int right)
{
if (left<right)
{
int p = partition(a, left, right);
quickSort(a, left, p-1);
quickSort(a, p+1, right);
}
}
(六)臭皮匠排序
最差时间复杂度:O(n^2.7)
臭皮匠排序(Stooge Sort),是一种低效的排序算法,在《算法导论》第二版第7章的思考题中被提到,是由Howard Fine等教授提出的所谓“漂亮的”排序算法。将数列平分为三个子串,依次递归排序前两个子串、后两个子串、前两个子串,最后确保整个数列有序。此算法在最坏情况下的递归式为T(n) = 3T(2n/3) + 1。由主定理很容易知道它的算法复杂性为:T(n) = O(n^log(3/2, 3))。很显然log(3/2, 3))>2,也就是说这个算法比插入排序的O(n^2)性能还差。
实现代码:
[cpp] view plain
void StoogeSort(int *a, int i, int j)
{
if(a[i]>a[j])
swap(a[i], a[j]);
if((i+1)>=j)
return;
int k = (j-i+1)/3;
StoogeSort(a, i, j-k);
StoogeSort(a, i+k, j);
StoogeSort(a, i, j-k);
}
Ⅳ 排序算法是怎样的
一、背景介绍
在计算机科学与数学中,排序算法(Sorting algorithm)是一种能将一串资料依照特定排序方式进行排列的一种算法。
最常用到的排序方式是数字顺序以及字典顺序。
有效的排序算法在一些算法(例如搜寻算法与合并算法)中是重要的, 如此这些算法才能得到正确解答。
排序算法也用在处理文字资料以及产生人类可读的输出结果。
基本上,排序算法的输出必须遵守下列两个原则:
1、输出结果为递增序列(递增是针对所需的排序顺序而言);
2、输出结果是原输入的一种排列、或是重组;
虽然排序算法是一个简单的问题,但是从计算机科学发展以来,在此问题上已经有大量的研究。 更多的新算法仍在不断的被发明。
二、知识剖析
查找和排序算法是算法的入门知识,其经典思想可以用于很多算法当中。因为其实现代码较短,应用较常见。 所以在面试中经常会问到排序算法及其相关的问题。但万变不离其宗,只要熟悉了思想,灵活运用也不是难事。
一般在面试中最常考的是快速排序和冒泡排序,并且经常有面试官要求现场写出这两种排序的代码。对这两种排序的代码一定要信手拈来才行。除此之外,还有插入排序、冒泡排序、堆排序、基数排序、桶排序等。
三、常见的几种算法:
冒泡算法、选择排序、插入排序、希尔排序、归并排序、快速排序
算法的特点:
1、有限性:一个算法必须保证执行有限步之后结束。
2、确切性: 一个算法的每一步骤必须有确切的定义。
3、输入:一个算法有零个或多个输入,以刻画运算对象的初始情况,所谓零个输入是指算法本身给定了初始条件。
4、输出:一个算法有一个或多个输出。没有输出的算法毫无意义。
5、可行性:算法中执行的任何计算步骤都是可以被分解为基本的可执行的操作步,即每个计算步都可以在有限时间内完成(也称之为有效性)。
Ⅵ 计算机专业学算法的都学些什么算法,有什么书可以看的学的话需要些什么基础的
计算机算法非常多的
A*搜寻算法
俗称A星算法。这是一种在图形平面上,有多个节点的路径,求出最低通过成本的算法。常用于游戏中的NPC的移动计算,或线上游戏的BOT的移动计算上。该算法像Dijkstra算法一样,可以找到一条最短路径;也像BFS一样,进行启发式的搜索。
Beam Search
束搜索(beam search)方法是解决优化问题的一种启发式方法,它是在分枝定界方法基础上发展起来的,它使用启发式方法估计k个最好的路径,仅从这k个路径出发向下搜索,即每一层只有满意的结点会被保留,其它的结点则被永久抛弃,从而比分枝定界法能大大节省运行时间。束搜索于20 世纪70年代中期首先被应用于人工智能领域,1976 年Lowerre在其称为HARPY的语音识别系统中第一次使用了束搜索方法。他的目标是并行地搜索几个潜在的最优决策路径以减少回溯,并快速地获得一个解。
二分取中查找算法
一种在有序数组中查找某一特定元素的搜索算法。搜索过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。这种搜索算法每一次比较都使搜索范围缩小一半。
Branch and bound
分支定界(branch and bound)算法是一种在问题的解空间树上搜索问题的解的方法。但与回溯算法不同,分支定界算法采用广度优先或最小耗费优先的方法搜索解空间树,并且,在分支定界算法中,每一个活结点只有一次机会成为扩展结点。
数据压缩
数据压缩是通过减少计算机中所存储数据或者通信传播中数据的冗余度,达到增大数据密度,最终使数据的存储空间减少的技术。数据压缩在文件存储和分布式系统领域有着十分广泛的应用。数据压缩也代表着尺寸媒介容量的增大和网络带宽的扩展。
Diffie–Hellman密钥协商
Diffie–Hellman key exchange,简称“D–H”,是一种安全协议。它可以让双方在完全没有对方任何预先信息的条件下通过不安全信道建立起一个密钥。这个密钥可以在后续的通讯中作为对称密钥来加密通讯内容。
Dijkstra’s 算法
迪科斯彻算法(Dijkstra)是由荷兰计算机科学家艾兹格·迪科斯彻(Edsger Wybe Dijkstra)发明的。算法解决的是有向图中单个源点到其他顶点的最短路径问题。举例来说,如果图中的顶点表示城市,而边上的权重表示著城市间开车行经的距离,迪科斯彻算法可以用来找到两个城市之间的最短路径。
动态规划
动态规划是一种在数学和计算机科学中使用的,用于求解包含重叠子问题的最优化问题的方法。其基本思想是,将原问题分解为相似的子问题,在求解的过程中通过子问题的解求出原问题的解。动态规划的思想是多种算法的基础,被广泛应用于计算机科学和工程领域。比较著名的应用实例有:求解最短路径问题,背包问题,项目管理,网络流优化等。这里也有一篇文章说得比较详细。
欧几里得算法
在数学中,辗转相除法,又称欧几里得算法,是求最大公约数的算法。辗转相除法首次出现于欧几里得的《几何原本》(第VII卷,命题i和ii)中,而在中国则可以追溯至东汉出现的《九章算术》。
最大期望(EM)算法
在统计计算中,最大期望(EM)算法是在概率(probabilistic)模型中寻找参数最大似然估计的算法,其中概率模型依赖于无法观测的隐藏变量(Latent Variable)。最大期望经常用在机器学习和计算机视觉的数据聚类(Data Clustering)领域。最大期望算法经过两个步骤交替进行计算,第一步是计算期望(E),利用对隐藏变量的现有估计值,计算其最大似然估计值;第二步是最大化(M),最大化在 E 步上求得的最大似然值来计算参数的值。M 步上找到的参数估计值被用于下一个 E 步计算中,这个过程不断交替进行。
快速傅里叶变换(FFT)
快速傅里叶变换(Fast Fourier Transform,FFT),是离散傅里叶变换的快速算法,也可用于计算离散傅里叶变换的逆变换。快速傅里叶变换有广泛的应用,如数字信号处理、计算大整数乘法、求解偏微分方程等等。
哈希函数
HashFunction是一种从任何一种数据中创建小的数字“指纹”的方法。该函数将数据打乱混合,重新创建一个叫做散列值的指纹。散列值通常用来代表一个短的随机字母和数字组成的字符串。好的散列函数在输入域中很少出现散列冲突。在散列表和数据处理中,不抑制冲突来区别数据,会使得数据库记录更难找到。
堆排序
Heapsort是指利用堆积树(堆)这种数据结构所设计的一种排序算法。堆积树是一个近似完全二叉树的结构,并同时满足堆积属性:即子结点的键值或索引总是小于(或者大于)它的父结点。
归并排序
Merge sort是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。
RANSAC 算法
RANSAC 是”RANdom SAmpleConsensus”的缩写。该算法是用于从一组观测数据中估计数学模型参数的迭代方法,由Fischler and Bolles在1981提出,它是一种非确定性算法,因为它只能以一定的概率得到合理的结果,随着迭代次数的增加,这种概率是增加的。该算法的基本假设是观测数据集中存在”inliers”(那些对模型参数估计起到支持作用的点)和”outliers”(不符合模型的点),并且这组观测数据受到噪声影响。RANSAC 假设给定一组”inliers”数据就能够得到最优的符合这组点的模型。
RSA加密演算法
这是一个公钥加密算法,也是世界上第一个适合用来做签名的算法。今天的RSA已经专利失效,其被广泛地用于电子商务加密,大家都相信,只要密钥足够长,这个算法就会是安全的。
并查集Union-find
并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。常常在使用中以森林来表示。
Viterbi algorithm
寻找最可能的隐藏状态序列(Finding most probable sequence of hidden states)。