- 浏览: 539953 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
GGGGeek:
看完了博主的博文,如果没猜错的话应该是浙大吧?很多优秀的人因为 ...
转《D君的故事》 以时刻警示自己 -
游牧民族:
楼主写的不错,学习了,最近对爬虫比较感兴趣,也写了些爬虫相关的 ...
通用爬虫框架及heritrix爬虫介绍 -
jimmee:
jerome_s 写道ice 你怎么看? 粗略的看了一下ice ...
MessagePack, Protocol Buffers和Thrift序列化框架原理和比较说明 -
jerome_s:
ice 你怎么看?
MessagePack, Protocol Buffers和Thrift序列化框架原理和比较说明 -
jimmee:
nk_tocean 写道照着做了,但是不行啊,还是乱码.先确认 ...
hive编写udf处理非utf-8数据
一般来说,排序算法有10种,今天先说4种,并给出基本的代码。如有错误,欢迎大家指正。如果大家比较忙,忙着去泡妞的话,可以直接跳到最后看我的小结部分。
为了便于后面的讨论和理解,这里先做一个约定,就是把你要排序的元素假想为大小不一的一些球,这些球都放在一个容器里。排序的过程是把这些球拿出来按照一个指定的顺序的摆放(这里指定的顺序我们先定为升序,倒序是一回事)。同时预先定义两个方法,假定我们要比较的元素是整型数字,其实要改成通用的类型,也是很容易的一件事。
1. 选择排序
顾名思义,不断地把容器中最小的球选择出来,依次摆放在前面已经拿出来的球后面。直至容器中没有球为止。大家看一下代码:
现在来分析一下分析一下这个算法的性能,排序要完成,第一次选出最小的数,需要N-1比较,第二次需要N-2,…,一直到1;那么总共的比较是(N-1)+(N-2)+(N-3)+…+1=N(N-1)/2,时间复杂度O(n^2);交换次数为N-1次,这是显而易见的。
2.插入排序
插入排序,我们从容器拿球出来时,并不要求拿最大的还是最小,依次拿出来就可以了。拿出来以后,放到已经拿出来的球中的适当位置,大家想想在排队时,要把个子矮的人调整到适当的位置,都是和他前面的比较,如果比他前面的人矮,就插入到前面去,直到他前面的人都比他个子矮,这样最后就可以形成一个有序的队伍。下面是代码:
现在来分析一下插入排序,通过内部循环大家可以看到,比较的次数和移动的次数是一样的。在最坏情况下,插入第i个数时,需要比较i-1和移动i-1次,因此最坏情况下,需要N(N-1)/2次比较和移动,平均情况是N(N-1)/4次比较和移动。
3.冒泡程序
冒泡,大家想想,水里气泡是不是从底向上组件冒到上面的。我们对容器里的小球采用冒泡排序的话,我们也是不断地把最小的球浮到上面来。最后形成一个有序的小球队列。还是先看代码
其实上面的程序还可以进一步改进,如果第i趟时,没有发生交换,就说明已经排好序了。和前面的分析一样,第i趟冒泡排序需要N-i次比较和交换。总的来说,平均和最坏情况下都需要N^2/2次比较和交换操作(理论证明有点复杂,但是牛人已经证明过了)。
4.希尔排序
希尔排序本质上就是插入排序,大家有没有注意到,如果在一个数组里,最小的一个元素在最后一个位置,插入排序时,我们是不是需要移动N-1次才能放到具体的位置?于是,shell这个人就想,我们是不是可以以一定的步长把数组里的元素分成几个序列?分别对这些子序列使用希尔排序,最后步长减小为1时再使用插入排序搞定。Ok,这就是希尔排序了。当然了,希尔排序的难点就是步长的选择,到底多少合适呢?说实话,算法大牛们到现在为止都没有证明出哪一个步长序列是最好的。我这里就是用广泛采用的步长序列吧,1,4,13,40,121…(其实就是3x+1形成的序列),这个步长下,时间复杂度是O(N^(3/2));代码如下:
小结:选择排序,插入排序和冒泡排序都是O(n^2)的,希尔排序低于O(n^2)。实际应用过程中,对于数据量较小时(一般来说,小于1w),一般可以使用选择排序,插入排序和冒泡排序,中等数据量(小于100w)可以采用希尔排序,可以取得较好的效果。即使对于小数据量,还可以进一步分析,选择排序是不管输入数据的形态怎样(也就是说,不管输入的数据是随机的,还是几乎有序的,还是倒序的),时间复杂度都是O(N^2),然而如果数据几乎是有序的时候,采用插入排序和冒泡排序都可以在线性时间内完成排序。那么选择排序有没有作为首选的时候呢?答案是肯定的,如果我们要排序的文件比较大时,移动文件耗费的时间占据了很多时间,这个时候,比较操作是微不足道的,根据前面我们的分析,选择排序需要的移动(即交换)次数是最少的,这时选择排序当然是我们的首选了。
接下来,我准备说一下快速排序,归并排序和堆排序。
为了便于后面的讨论和理解,这里先做一个约定,就是把你要排序的元素假想为大小不一的一些球,这些球都放在一个容器里。排序的过程是把这些球拿出来按照一个指定的顺序的摆放(这里指定的顺序我们先定为升序,倒序是一回事)。同时预先定义两个方法,假定我们要比较的元素是整型数字,其实要改成通用的类型,也是很容易的一件事。
public static boolean less(int a,int b){ return a<b; }
public static void exch(int [] arr,int i,int j){ int temp=arr[i]; arr[i]=arr[j]; arr[j]=temp; /** 这里给大家说一个不需要临时变量就交换两个数的技巧,异或就可以了。如下: arr[i]=arr[i]^arr[j]; arr[j]=arr[i]^arr[j]; arr[i]=arr[i]^arr[j]; **/ }
1. 选择排序
顾名思义,不断地把容器中最小的球选择出来,依次摆放在前面已经拿出来的球后面。直至容器中没有球为止。大家看一下代码:
/** ** arr 要排序的数组 ** start 排序数组的开始位置 ** end 排序数组的结束位置 **/ public static void sort(int [ ] arr,int start,int end){ int i,j,min; for(i=start;i<end-1;i++){ min=i; for(j=start+1;j<=end;j++){ if(less(arr[j],arr[min]) min=j; } exch(arr,i,min); } }
现在来分析一下分析一下这个算法的性能,排序要完成,第一次选出最小的数,需要N-1比较,第二次需要N-2,…,一直到1;那么总共的比较是(N-1)+(N-2)+(N-3)+…+1=N(N-1)/2,时间复杂度O(n^2);交换次数为N-1次,这是显而易见的。
2.插入排序
插入排序,我们从容器拿球出来时,并不要求拿最大的还是最小,依次拿出来就可以了。拿出来以后,放到已经拿出来的球中的适当位置,大家想想在排队时,要把个子矮的人调整到适当的位置,都是和他前面的比较,如果比他前面的人矮,就插入到前面去,直到他前面的人都比他个子矮,这样最后就可以形成一个有序的队伍。下面是代码:
public static void sort(int [ ] arr,int start,int end){ int i,j,temp; /** 这里是找出元素中最小的一个,避免后面插入时要判断是否已经到达数组 第一个位置。 **/ for(i=end;i>start;i--) if(less(arr[i],arr[i-1])) exch(arr,i,i-1); for(i=start+2;i<=end;i++){ temp=arr[i]; j=i; /** 注意,这里在处理插入时,采用赋值操作的实现当然要比交换操作快。 **/ while(less(temp,arr[j-1]){ arr[j]=arr[j-1]; j--; } arr[j]=temp; } }
现在来分析一下插入排序,通过内部循环大家可以看到,比较的次数和移动的次数是一样的。在最坏情况下,插入第i个数时,需要比较i-1和移动i-1次,因此最坏情况下,需要N(N-1)/2次比较和移动,平均情况是N(N-1)/4次比较和移动。
3.冒泡程序
冒泡,大家想想,水里气泡是不是从底向上组件冒到上面的。我们对容器里的小球采用冒泡排序的话,我们也是不断地把最小的球浮到上面来。最后形成一个有序的小球队列。还是先看代码
public static void sort(int [ ] arr,int start,int end){ int i,j; //最多只需要N-1趟就可以排好序了,因为一次把一个小的球浮上来。 for(i=start;i<end;i++){ for(j=end;j>i;j--){ if(less(arr[j],arr[j-1])) exch(arr,j,j-1); } } }
其实上面的程序还可以进一步改进,如果第i趟时,没有发生交换,就说明已经排好序了。和前面的分析一样,第i趟冒泡排序需要N-i次比较和交换。总的来说,平均和最坏情况下都需要N^2/2次比较和交换操作(理论证明有点复杂,但是牛人已经证明过了)。
4.希尔排序
希尔排序本质上就是插入排序,大家有没有注意到,如果在一个数组里,最小的一个元素在最后一个位置,插入排序时,我们是不是需要移动N-1次才能放到具体的位置?于是,shell这个人就想,我们是不是可以以一定的步长把数组里的元素分成几个序列?分别对这些子序列使用希尔排序,最后步长减小为1时再使用插入排序搞定。Ok,这就是希尔排序了。当然了,希尔排序的难点就是步长的选择,到底多少合适呢?说实话,算法大牛们到现在为止都没有证明出哪一个步长序列是最好的。我这里就是用广泛采用的步长序列吧,1,4,13,40,121…(其实就是3x+1形成的序列),这个步长下,时间复杂度是O(N^(3/2));代码如下:
public static void sort(int [ ] arr,int start,int end){ int i,j,temp,h; //计算步长 for(h=1;h<=(end-start)/9;h=3*h+1); //开始以不同步长进行插入排序 for(;h>0;h/=3){ //注意,这里后面i++,而不是i+=h for(i=start+h;i<=end;i++){ j=i;temp=arr[i]; while(j>=start+h&&less(temp,arr[j-h]){ arr[j]=arr[j-h]; j-=h; } arr[j]=temp; } } }
小结:选择排序,插入排序和冒泡排序都是O(n^2)的,希尔排序低于O(n^2)。实际应用过程中,对于数据量较小时(一般来说,小于1w),一般可以使用选择排序,插入排序和冒泡排序,中等数据量(小于100w)可以采用希尔排序,可以取得较好的效果。即使对于小数据量,还可以进一步分析,选择排序是不管输入数据的形态怎样(也就是说,不管输入的数据是随机的,还是几乎有序的,还是倒序的),时间复杂度都是O(N^2),然而如果数据几乎是有序的时候,采用插入排序和冒泡排序都可以在线性时间内完成排序。那么选择排序有没有作为首选的时候呢?答案是肯定的,如果我们要排序的文件比较大时,移动文件耗费的时间占据了很多时间,这个时候,比较操作是微不足道的,根据前面我们的分析,选择排序需要的移动(即交换)次数是最少的,这时选择排序当然是我们的首选了。
接下来,我准备说一下快速排序,归并排序和堆排序。
发表评论
-
moses安装记录
2016-12-11 11:00 01. moses的安装说明地址(注意,一定要安装好相应的bo ... -
翻译算法
2016-12-09 07:50 0翻译的概率T=argsMaxP(T|S)=P(T)P(S|T ... -
JPEG 简易文档 V2.15【转载】
2016-04-10 16:35 635JPEG 简易文档 V2.15 ------------- ... -
Java 并发之 ConcurrentSkipListMap 简述
2015-09-20 20:24 1125JCIP 提到了在 Java 6 中引入了两个新的并发集合类 ... -
最简单的平衡树(红-黑树)的实现
2015-09-04 08:04 1190在二叉搜索树(BST)的基础上,要实现一颗平衡树,可以使用 ... -
lucene索引创建的理解思路
2014-06-29 23:12 1485虽然lucene4很早就出来,但是这里仍然以lucene3. ... -
lucene的拼写检查的实现原理
2014-06-08 18:19 13151. 建索引时, 使用ngram的方式创建索引 Sp ... -
字符串相似算法-(3) NGram Distance
2014-06-08 17:54 4902就是N-Gram version of edit dista ... -
字符串相似算法-(2) Levenshtein distance
2014-06-08 16:32 2231编辑距离概念描述: ... -
字符串相似算法-(1) Jaro-Winkler Distance
2014-06-08 12:05 6759Jaro-Winkler Distance 算法 ... -
Lucene的数字范围搜索 (Numeric Range Query)原理
2014-04-05 16:08 135540. 全文索引的核心就是倒排索引. 1. 若 ... -
UDT协议-基于UDP的可靠数据传输协议的实现分析(7)-流量和拥塞控制
2014-04-02 20:53 4143流量控制 对于一个带宽1Gbps, RTT为100ms的网络 ... -
UDT协议-基于UDP的可靠数据传输协议的实现分析(6)-链接的建立和关闭
2014-04-01 22:47 20491. 模式有client/server mode(客户端, ... -
协议-基于UDP的可靠数据传输协议的实现分析(5)-可靠性怎么保证
2014-03-31 23:08 3782发送方的处理:1) 包发送确认后,由于还没有收到确认,先缓存 ... -
UDT协议-基于UDP的可靠数据传输协议的实现分析(4)-发送和接收的算法
2014-03-30 10:09 71530. 计时器udt有四种计时器: ACK, NAK, E ... -
UDT协议-基于UDP的可靠数据传输协议的实现分析(3)-包结构说明
2014-03-29 17:24 3202udt的包结构1. 数据包,基本结构如下: 0 ... -
UDT协议-基于UDP的可靠数据传输协议的实现分析(2)-为什么要用udt
2014-03-28 08:00 37630. AIMD算法的简单回顾 (1) 慢开始 ... -
UDT协议-基于UDP的可靠数据传输协议的实现分析(1)-准备工作
2014-03-27 12:52 38191. 协议实现方案: Yunhong Gu提出的rfc的草 ... -
mapreduce的一些算法设计,优化等(2)
2014-01-28 15:50 14721. 反序(order inversion ... -
mapreduce的一些算法设计,优化等(1)
2014-01-27 17:15 2076本系列是根据书籍《Da ...
相关推荐
冒泡排序法是一种简单的排序算法,通过不断地比较相邻的元素,直到没有元素再需要交换为止。其实现步骤如下: * 首先,从数组的第一个元素开始,比较相邻的元素,如果它们的顺序错误,则交换它们。 * 继续比较直到...
7种排序算法程序汇总 冒泡排序 选择排序 插入排序 希排序尔 快速排序 二叉排序树 堆排序
带哨兵的直接排序法是一种基于直接插入法的排序算法。它的基本思想是将待排序的序列分成两个部分:已经排序的部分和未排序的部分。然后,对未排序的部分使用哨兵元素进行插入排序,将其插入到已经排序的部分中。 带...
在计算机科学领域中,排序算法是一种基本的算法,它可以将数据按照一定的顺序排列,以便更好地存储、检索和处理数据。排序算法的速度和效率对程序的性能有着至关重要的影响。 1.冒泡排序算法 冒泡排序算法是一种...
桶式排序法桶式排序法桶式排序法桶式排序法
描述中的程序实现了快速排序法,可能是用一种编程语言如C++、Java或Python编写的,用于对一维数组进行排序。这种程序的实现一般包括上述的三个主要步骤,并可能包含优化措施,例如处理小数组时改用插入排序,或者...
冒泡排序是一种简单直观的排序算法,它重复地遍历待排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。遍历数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的...
在编程领域,排序算法是计算机科学中的核心概念,特别是在数据结构和算法分析中。Java作为广泛应用的编程语言,提供了丰富的工具和技术来实现各种排序算法。本文将深入探讨标题"常用排序算法java演示"中涉及的知识点...
时间复杂度用于衡量排序算法的效率,通常以大O表示法来表示。文档中提到了几种不同排序算法的时间复杂度: - **O(n²)**:插入排序、冒泡排序和选择排序的时间复杂度均为O(n²),这意味着随着数据量的增加,这些...
该程序包含7大排序算法: # sort.bubbleSort() #冒泡排序 # sort.shellSort() #希尔排序 # sort.insertionSort() #插入排序 # sort.Selectionsort1() #选择排序 # sort.heapSort() #堆排序 # sort.countSort() ...
在计算机科学中,排序算法是数据结构领域的重要组成部分,它涉及到如何有效地重新排列一组数据,使其按照特定的顺序排列。本资源提供了三种经典的排序算法的C语言实现:堆排序、直接插入排序和快速排序。 首先,让...
归并排序(Merge Sort)是一种基于分治策略的高效排序算法,由计算机科学家John W. Backus于1945年提出。它的工作原理可以分为三个主要步骤:分解、解决和合并。 1. 分解:将原始数据序列分成两个相等(或接近相等...
希尔排序是一种基于插入排序的算法,通过将待排序的数组元素按某个增量分组,然后对每组使用直接插入排序算法排序。随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止...
在计算机科学中,排序算法是将一组数据按照一定的顺序排列的过程。排序算法的性能直接影响到数据处理和分析的效率。本课程设计中,我们将对八种内部排序算法的性能进行分析和比较。 1. 直接插入排序(Insertion ...
在计算机科学领域,排序算法是数据处理中的核心部分,它涉及到如何有效地重新排列一组数据,使其按照特定的顺序排列。本资源"总结了各种排序算法,并用C++代码实现,并有演示",提供了丰富的学习材料,包括不同类型...
排序算法是计算机科学中最基础和重要的算法之一,用于将一组数据按照特定的顺序进行排列。本文将对几种常见的内部排序算法和外部排序算法进行详细总结。 首先,排序的基本定义是:给定一个包含n个记录的序列,其...
合并排序是一种基于分治策略的排序算法,它将大问题分解为小问题来解决。首先将数组分为两个相等或近乎相等的部分,然后对每一部分递归地进行排序,最后将结果合并。这种算法的时间复杂度为O(n log n),稳定性好,...
选择堆积排序法是一种高效的排序算法,适用于大规模的数据结构。该算法使用堆积结构来存储数据,并对堆积结构进行排序。选择堆积排序法的时间复杂度为O(nlogn),因此非常适合大规模数据的排序。 在软件技术基础中,...
在IT领域,排序算法是计算机科学中的基础但至关重要的概念,尤其在数据处理和算法设计中扮演着核心角色。本文将深入探讨标题中提到的几种基于比较的排序算法:选择排序、插入排序、归并排序、快速排序、堆排序、冒泡...
常用排序算法总结常用排序算法总结常用排序算法总结常用排序算法总结常用排序算法总结常用排序算法总结常用排序算法总结常用排序算法总结常用排序算法总结常用排序算法总结