`
张江兴
  • 浏览: 121414 次
  • 性别: Icon_minigender_1
  • 来自: 湖南
社区版块
存档分类
最新评论

小结常用排序方法(一)

阅读更多

做过几次各大IT公司的实习生招聘笔试题,发现数据结构还是很重要的,其中排序问题总是会出现在试题上,所以对几种常见的排序方法总结下。

 

其实排序可分为两大类:内部排序和外部排序

 

内部排序:指需排序的记录存放在计算机随机存储器中进行的排序过程,也就是小数量的数据排序,像冒泡排序,选择排序等就是内部排序;

 

外部排序:指需排序的记录数量很大,以致内存一次不能容纳全部记录,在排序过程中需对外存进行访问的排序过程;这种我暂时没怎么接触过,不多说了;

 

下面是几种常见的部内排序方法:

1.       直接插入排序

每次从无序表中抽出一个数插入到有序表中,使得表仍然有序,第一趟比较前两个数,然后把第二个数按大小插入到有序表中; 第二趟把第三个数据与前两个数从后向前扫描,把第三个数按大小插入到有序表中;依次进行下去,进行了(n-1)趟扫描以后就完成了整个排序过程,整个过程如下:

假设序列为49  38  65  97  76  13  27

【初始关键字】                ( 49 )  38  65  97  13  27

 

     i=2          (38)          ( 38  49 )  65  97  13  27

 

     i=3          (65)          ( 38  49  65 )  97  13  27

 

     i=4          (97)          ( 38  49  65  97 )  13  27

 

     i=5          (13)          ( 13  38  49  65  97 )  27

 

     i=5          (27)          ( 13  27  38  49  65  97 )  

                    

                    监视哨(保存当前待比较的数值)temp

Java代码实现:

int[]  text(int[] a ){

   for (int i = 1; i < a.length; i++) {

  int  temp = a[i];

  for (int j = i; j > 0 && temp < a[j-1]; j--) {

  a[j] = a[j - 1];

  }

  a[j] = temp;

}

return  a;

}

 

2.希尔排序

   又称缩小增量排序,其基本思想是:先将整个待排序的记录序列分割成若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行一次直接插入排序;

就是先取一个小于n(整个记录的长度)的整数t1作为第一个增量,把文件的全部记录分成t1个组。所有距离为t1的倍数的记录放在同一个组中。先在各组内进行直接插入排序;然后,取第二个增量t2<t1重复上述的分组和排序,直至所取的增量ti=1(ti<ti-l<…<t2<t1),即所有记录放在同一组中进行直接插入排序为止;

如果记录的量大且一组内的记录相隔距离远,那么就可以省去多次数据交换,这就是对直接插入排序的改进之处。示例如下:

假设序列为:49  38  65  97  76  13  27  49  55  04

增量可取: 5 3 1

【初始关键字】 49  38  65  97  76  13  27  49  55  04

 先分成5组:49  13 38  27  65  49  97  55  76  04          

 每一组进行直接插入排序后:13  27  49  55  04  49  38  65  97  76(第一趟排序结果)

 然后分成3组:13  55  38  76 27  04  65 49  49  97

每一组进行直接插入排序后:13  04  49  38  27  49  55  65  97  76(第二趟排序结果)

 再分成1组(对整个序列排序) 13  04  49  38  27  49  55  65  97  76

 进行直接插入排序后:04  13  27  38  49  49  55  65  76  97(第三趟排序结果)

Java代码实现:

int []  ShellSort(int[] a) {

  int  Temp; // 暂存变量

  int  DataLength; // 分割集合的间隔长度

  int  Pointer; // 进行处理的位置

DataLength = a.length / 2; // 初始集合间隔长度

  while (DataLength != 0) // 数列仍可进行分割

{ // 对各个集合进行处理

  for (int j = DataLength; j < a.length; j++) {

   Temp = a[j]; // 暂存Data[j]的值,待交换值时用

  Pointer = j - DataLength; // 计算进行处理的位置

// 进行集合内数值的比较与交换值

  while (Temp < a[Pointer] && Pointer >= 0 && Pointer < a.length) {

  a[Pointer + DataLength] = a[Pointer];

  // 计算下一个欲进行处理的位置

  Pointer = Pointer - DataLength;

  if (Pointer < 0 || Pointer >= Index)

  break;

  }

  // 与最后的数值交换

  a[Pointer + DataLength] = Temp;

  DataLength = DataLength / 2; // 计算下次分割的间隔长度

  }

return  a;

}

3.冒泡排序

   冒泡排序的过程很简单,首先将第一个数和第二个数进行比较,如果是逆序的,就将两个数交换,然后比较第二个数和第三个数,依次类推,直到第n-1个数和第n个数据进行比较完为止,然后进行延续二趟排序,对前n-1个数进行同类操作,直到没有数可比;

假设序列为:  49  38  65  97  76  13  27  49

第一趟排序:38  49  65  76  13  27  49  97

第二趟排序:38  49  65  13  27  49  76

第三趟排序:38  49  13  27  49  65

第四趟排序:38  13  27  49  49

第五趟排序:13  27  38  49

第六趟排序:13  27  38

从上面的排序过程可以看到:大的数一个个往下沉,小的数的就向上浮,跟这个排序方法的名字很贴切。

Java代码实现:

int  sort (int[]  a){

for(int j=1;j<=a.length;j++){

  for(int i=0;i<a.length-j;i++){

  if(a[i]>a[i+1]){

   int temp;

   temp = a[i];

   a[i] = a[i+1];

   a[i+1] = temp;

}  

  }

return  a;

}

为了提高效率,可以设置一个是否继续比较下去的标志,因为如果数列的排列顺序就是所要求的顺序,那就没必要一个个往下比了,比如:当一趟排序中没有发生数据交换,就可以提前终止。

 

4.快速排序

   快速排序是对冒泡排序的一种改进,通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列;

设要排序的数组是A[0]……A[N-1],首先任意选取一个数据(通常选用第一个数据)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。值得注意的是,快速排序不是一种稳定的排序算法,也就是说,多个相同的值的相对位置也许会在算法结束时产生变动。

一趟快速排序的算法是:

1)设置两个变量IJ,排序开始的时候:I=0J=N-1

2)以第一个数组元素作为关键数据,赋值给key,即 key=A[0]

3)从J开始向前搜索,即由后开始向前搜索(J=J-1),找到第一个小于key的值A[J],并与A[I]交换;

4)从I开始向后搜索,即由前开始向后搜索(I=I+1),找到第一个大于keyA[I],与A[J]交换;

5)重复第345步,直到 I=J (3,4步是在程序中没找到时候j=j-1i=i+1,直至找到为止。找到并交换的时候i j指针位置不变。另外当i=j这过程一定正好是i+j-完成的最后另循环结束)

过程可如下图表示:

                                  

上面是完成一趟排序的过程,整个排序过程可描述如下:

 

初始状态           49  38  65  97  76  13  27  49

 

一次划分之后          ( 27  38  13 )  49 76  97  65  49

 

分别进行快速排序     1327 38

                                    结束              结束      ( 49  65 )  76  ( 97 )

                                        49  ( 65 )  76                          结束

                                                 结束

  有序序列            ( 13  27  38  49  49  65  76  97 )

 

Java代码实现:

int[] sort(int[] data, int low, int high) {

  // 枢纽元,一般以第一个元素为基准进行划分

  int i = low;

  int j = high;

  if (low < high) {

  // 从数组两端交替地向中间扫描

  int pivotKey = data[low];

  // 进行扫描的指针i,j;i从左边开始,j从右边开始

  while (i < j) {

  while (i < j && a[j]>=pivotkey) {

  j--;

  }// end while

  if (i < j) {

  // 比枢纽元素小的移动到左边

  data[i] = data[j];

  i++;

  }// end if

  while (i < j && a[i]<=pivotkey) {

  i++;

  }// end while

  if (i < j) {

  // 比枢纽元素大的移动到右边

  data[j] = data[i];

  j--;

  }// end if

  }// end while

  // 枢纽元素移动到正确位置

  data[i] = pivotKey;

  // 前半个子表递归排序

  sort(data, low, i - 1);

  // 后半个子表递归排序

  sort(data, i + 1, high);

}// end if

return  a;

}// end sort

 

5.简单选择排序

   其基本思想是:在每一趟排序中将n-i+1(i=1,2,…,n-1)个记录中选取最小的记录和有序序列中第i个记录交换,个人觉得这种排序方法跟冒泡排序很像,比如从小到大排序,冒泡是将大的数一个一个往下沉,而简单选择排序是将小的数一个个往上冒;

Java代码实现:

 

int[] sort(int[] data) {

  int len = data.length;

  for (int i = 0; i < len; i++) {

  int position = i;

  for (int j = i + 1; j < len; j++) {

  if (data[position]>data[j])) {

  position = j;

  }

  }

  Int  temp = data[i];

  data[i] = data[position];

  data[position] = temp;

  }

}

 

分享到:
评论

相关推荐

    Java排序小结:常用的排序方法

    javaeye 收集的java排序小结,希望对大家有所帮组

    常见排序算法小结

    在高级语言的执行速度上,c是最快的,c++其次,而java和c#是最后的。Java和c#流行,主要的一个原因是可以跨平台。

    常用排序算法小结(附Java实现)

    NULL 博文链接:https://easense2009.iteye.com/blog/1568614

    PHP常用排序算法实例小结【基本排序,冒泡排序,快速排序,插入排序】

    主要介绍了PHP常用排序算法,结合实例形式总结分析了php常见的排序算法,包括基本排序、冒泡排序、快速排序、插入排序等,需要的朋友可以参考下

    Java数组常用排序算法实例小结

    主要介绍了Java数组常用排序算法,结合实例形式总结分析了java数组常用的4种排序算法,包括冒泡排序、数组递增排序、快速排序及选择排序,需要的朋友可以参考下

    JavaScript中各种引用类型的常用操作方法小结

    重排序方法: compare 升序: function compare(value1, value2){ if (value1&lt;value2&gt;value2){ return 1; } else{ return 0; } } var values = [0,1,5,10,15]; values.sort(compare); console.log(values); // ...

    SQL Server查询前N条记录的常用方法小结

    主要介绍了SQL Server查询前N条记录的常用方法,以实例形式分析总结了SQL Server查询数据库的三种常用技巧,具有一定参考借鉴价值,需要的朋友可以参考下

    Python程序设计:元组的常用操作.pptx

    菜单生成器 任务 菜单生成器 任务背景 运用元组相关知识,编写一个程序,要求输入菜品和它的价格,格式化打印该菜单。 本案例主要针对元组的基本使用的考察,元组是不可变序列,创建元组可以通过()创建,也...小结 谢

    Java常用算法手册源代码

    1.11 小结 第2章 数据结构 2.1 数据结构概述 2.1.1 什么是数据结构 2.1.2 数据结构中的基本概念 2.1.3 数据结构的内容 2.1.4 数据结构的分类 2.1.5 数据结构的几种存储方式 2.1.6 数据类型 2.1.7 常用的数据结构 ...

    C/C++常用算法手册.秦姣华(有详细书签).rar

    《C/C++常用算法手册》对每一个知识点都给出了相应的算法及应用示例。虽然这些例子都是以C语言来编写的,但是算法并不局限于C语言。如果读者采用其他编程语言,例如C++、C#、VB、Java等,根据其语法格式进行适当的...

    javascript数组对象常用api函数小结(连接,插入,删除,反转,排序等)

    本文实例讲述了javascript数组对象常用api函数。分享给大家供大家参考,具体如下: 1. concat() 连接两个或多个数组,并返回结果 var a = [1,2,3]; var b = a.concat(6,7); console.log(a); //[1,2,3] console.log...

    ORACLE 常用分析函数

    PLSQL开发笔记和小结;分析函数简述  ROW_NUMBER () OVER([partition_clause] order_by_clause) dense_rank在做排序时如果遇到列有重复值,则重复值所在行的序列值相同,而其后的序列值依旧递增,rank则是重复值...

    突破程序员基本功的16课.part2

    1.3 小结 第2课 对象与内存控制 2.1 实例变量和类变量 2.1.1 实例变量和类变量的属性 2.1.2 实例变量的初始化时机 2.1.3 类变量的初始化时机 2.2 父类构造器 2.2.1 隐式调用和显式调用 2.2.2 访问子类对象...

    Grails 技术精解与Web开发实践【源码+样章】----下载不扣分,回帖加1分,欢迎下载,童叟无欺

    1.6 本章小结 4 第一篇 入门篇 第2章 Hello Grails 6 2.1 Grails的安装 6 2.1.1 JDK的安装与配置 6 2.1.2 Grails的安装 7 2.2 创建Grails工程 8 2.3 Grails的MVC架构 11 2.4 Scaffold应用程序 14 2.5 开发工具的...

    最常用的12种设计模式小结

    可以通过实现多个Comparator接口来达到多种排序的目的. 2.装饰着模式(Decorator): 动态的给一个对象添加一些额外的职责. 比如java.io包. BufferedInputStream封装了FileInputStream, 它们都实现了InputStream接口, ...

    轻松学C#(图解版)

    1.4 小结 11 1.5 习题 12 第二篇 面向对象基础篇 第2章 类和对象 16 2.1 分析Hello World程序 16 2.2 语法规范 17 2.2.1 标识符 17 2.2.2 关键字 18 2.2.3 注释 19 2.3 定义类 20 2.4 实例化对象 20 2.5 小结 20 ...

    javaSE代码实例

    1.5 小结 11 第2章 基本数据类型——构建Java 大厦的基础 12 2.1 源代码注释 12 2.1.1 单行注释 12 2.1.2 区域注释 12 2.1.3 文档注释 13 2.2 基本数据类型 14 2.2.1 整型 15 2.2.2 浮点型 17 ...

Global site tag (gtag.js) - Google Analytics