17.1 排序介绍
排序是将一群数据,依指定的顺序进行排列的过程。
排序(Sorting)是数据处理中一种很重要的运算,同时也是很常用的运算,一般数据处理工作25%的时间都在进行排序。简单地说,排序就是把一组记录(元素)按照某个域的值的递增(即由小到大)或递减(即由大到小)的次序重新排序的过程。
17.2 排序分类
1、内部排序:
指将需要处理的所有数据都加载到内部存储器中进行排序。
包括:交换式排序法、选择式排序法、插入式排序法。
2、外部排序法:
数据量过大,无法全部加载到内存中,需要借助外部存储进行排序。
包括:合并排序法、直接合并排序法。
17.3 内部排序
17.3.1 交换式排序法
交换式排序法属于内部排序法,是运用数据值比较后,依判断规则对数据位置进行交换,以达到排序的目的。
交换式排序法又分为两种:
1、冒泡排序法(Bubble sort)
2、快速排序法(Quick sort)
17.3.1.1 冒泡排序法
冒泡排序(Bubble Sorting)的基本思想是:通过对待排序序列从后向前(从下标较大的元素开始),依次比较相邻元素的排序码,或发现逆序则交换,使排序码较小的元素逐渐从后部向前部(从下标较大的单元移向下标较小的单元),就像水底下的气泡一样逐渐向上冒。
因为排序的过程中,个元素不断接近自己的位置,如果一趟比较下来没有进行过交换,就说明序列有序,因此要在排序过程中设置一个标志flag判断元素是否进行过交换,从而减少不必要的比较。
演示代码如下:
1 /**日期:2016-03-06 2 * 功能:冒泡排序法演示 3 */ 4 package test; 5 import java.util.*; 6 public class Demo1 { 7 8 public static void main(String[] args) { 9 // TODO Auto-generated method stub 10 11 int arr1[]={27,23,12,33,76,55}; 12 Bubble bubble=new Bubble(); 13 bubble.sort(arr1); 14 //打印排序后的结果 15 for(int i=0;i<arr1.length;i++) 16 { 17 System.out.print(arr1[i]+" "); 18 } 19 System.out.println(""); 20 21 22 int len=60000; 23 int arr[]=new int[len]; 24 for(int i=0;i<arr.length;i++) 25 { 26 //Math.random()可以生成0~1,不包括1,之间的数 27 arr[i]=(int)(Math.random()*10000); 28 } 29 30 Calendar cal=Calendar.getInstance(); 31 System.out.println("冒泡排序法排序前时间:"+cal.getTime()); 32 bubble.sort(arr); 33 cal=Calendar.getInstance(); //注意cal要重写一遍 34 System.out.println("冒泡排序法排序后时间:"+cal.getTime()); 35 36 } 37 38 } 39 40 //冒泡排序法 41 class Bubble 42 { 43 //排序方法,注意sort前为void,它与进行数值处理的函数不同,无返回值 44 public void sort(int arr[]) 45 { 46 //用于交换的临时变量 47 int temp=0; 48 //外层循环,决定一共走几趟 49 for(int i=0;i<(arr.length-1);i++) 50 { 51 //内存循环,开始逐个比较,如果发现前一个元素比后一个大,则两者交换 52 for(int j=0;j<(arr.length-1-i);j++) 53 { 54 //从小到大排序为">",反之,为"<" 55 if(arr[j]>arr[j+1]) 56 { 57 //换位 58 temp=arr[j]; 59 arr[j]=arr[j+1]; 60 arr[j+1]=temp; 61 } 62 } 63 } 64 } 65 }
运行结果如下:
1 12 23 27 33 55 76 2 冒泡排序法排序前时间:Sun Mar 06 22:41:30 CST 2016 3 冒泡排序法排序后时间:Sun Mar 06 22:41:35 CST 2016
17.3.1.1 快速排序法
快速排序法(Quicksort)是对冒泡排序的一种改进。由C.A.R Hoare在1962年提出。 它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
17.3.2 选择式排序法
选择式排序也属于内部排序法,是从欲排序的数组中,按指定的规则选出某一元素,经过和其他元素重整,再依原则交换后达到排序的目的。
选择式排序又可分为两种:
1、选择排序法(Selectiong Sort)
2、堆排序法(Heap Sort)
17.3.2.1 选择排序法
选择排序(select sorting)也是一种简单的排序方法。它的基本思想是:第一次从R[0]-R[n-1]中选择最小值,与R[0]交换;第二次从R[1]-R[n-1]中选择最小值,与R[1]交换;第三次从R[2]-R[n-1]中选择最小值,与R[2]交换......第i次从R[i-1]-R[n-1]中选择最小值,与R[i-1]交换......第n-1次从R[n-2]-R[n-1]中选择最小值,与R[n-2]交换。总共通过n-1次,得到一个按排序码从小到大排列的有序序列。
演示代码如下:
1 /**日期:2016-03-06 2 * 功能:选择排序法演示 3 */ 4 package test; 5 import java.util.*; 6 public class Demo2 { 7 8 public static void main(String[] args) { 9 // TODO Auto-generated method stub 10 11 int arr1[]={27,23,12,33,76,55}; 12 Select select=new Select(); 13 select.sort(arr1); 14 //打印排序后的结果 15 for(int i=0;i<arr1.length;i++) 16 { 17 System.out.print(arr1[i]+" "); 18 } 19 System.out.println(""); 20 21 22 int len=60000; 23 int arr[]=new int[len]; 24 for(int i=0;i<arr.length;i++) 25 { 26 //Math.random()可以生成0~1,不包括1,之间的数 27 arr[i]=(int)(Math.random()*10000); 28 } 29 30 Calendar cal=Calendar.getInstance(); 31 System.out.println("选择排序法排序前时间:"+cal.getTime()); 32 select.sort(arr); 33 cal=Calendar.getInstance(); //注意cal要重写一遍 34 System.out.println("选择排序法排序后时间:"+cal.getTime()); 35 } 36 37 } 38 39 //选择排序法 40 class Select 41 { 42 public void sort(int arr[]) 43 { 44 int temp=0; 45 for(int i=0;i<(arr.length-1);i++) 46 { 47 //找出arr[i]及之后的所有数中的最小值,首先假定最小值为arr[i] 48 int min=arr[i]; 49 int minIndex=i; 50 for(int j=i+1;j<(arr.length);j++) 51 { 52 //从小到大排序为">",反之,为"<" 53 if(min>arr[j]) 54 { 55 min=arr[j]; 56 minIndex=j; 57 } 58 } 59 //将最小值与arr[i]交换位置,如果自己就是最小值,自己与自己交换 60 temp=arr[i]; 61 arr[i]=arr[minIndex]; 62 arr[minIndex]=temp; 63 } 64 } 65 }
运行结果如下:
1 12 23 27 33 55 76 2 选择排序法排序前时间:Sun Mar 06 22:46:47 CST 2016 3 选择排序法排序后时间:Sun Mar 06 22:46:48 CST 2016
17.3.2.2 堆排序法
17.3.3 插入式排序法
插入式排序法属于内部排序法,是对于欲排序的元素以插入的方式找寻元素的适当位置,以达到排序的目的。
插入式排序法又可分为3种:
1、插入排序法(Insertion sort)
2、谢耳排序法(shell sort)
3、二叉树排序法(Binary-tree sort)
17.3.3.1 插入排序法
插入排序的基本思想是:把n个待排序的元素看成为一个有序表和一个无序表,开始时有序表中只包含一个元素,无序表中包含有n-1个元素,排序过程中每次从无序表中取出第一个元素,把它的排序码依次与有序表元素的排序码进行比较,将它加入到有序表中的适当位置,使之成为新的有序表。
例如 n=6,数组R的六个排序码分别为:17,3,25,14,20,9。它的直接插入排序的执行过程如图9所示。
演示代码如下:
1 /**日期:2016-03-06 2 * 功能:插入排序法演示 3 */ 4 package test; 5 6 import java.util.Calendar; 7 8 public class Demo3 { 9 10 public static void main(String[] args) { 11 // TODO Auto-generated method stub 12 13 int arr1[]={27,23,12,33,76,55}; 14 Insert Insert=new Insert(); 15 Insert.sort(arr1); 16 //打印排序后的结果 17 for(int i=0;i<arr1.length;i++) 18 { 19 System.out.print(arr1[i]+" "); 20 } 21 System.out.println(""); 22 23 24 int len=60000; 25 int arr[]=new int[len]; 26 for(int i=0;i<arr.length;i++) 27 { 28 //Math.random()可以生成0~1,不包括1,之间的数 29 arr[i]=(int)(Math.random()*10000); 30 } 31 32 Calendar cal=Calendar.getInstance(); 33 System.out.println("插入排序法排序前时间:"+cal.getTime()); 34 Insert.sort(arr); 35 cal=Calendar.getInstance(); //注意cal要重写一遍 36 System.out.println("插入排序法排序后时间:"+cal.getTime()); 37 } 38 39 } 40 41 //插入排序法 42 class Insert 43 { 44 public void sort(int arr[]) 45 { 46 for(int i=1;i<arr.length;i++) 47 { 48 //带插入的值 49 int insertVal=arr[i]; 50 //首先index指向待插入的值的前一位数 51 int index=i-1; 52 //从小到大排序为">",反之,为"<" 53 while(index>=0&&arr[index]>insertVal) 54 { 55 arr[index+1]=arr[index]; 56 index--; 57 } 58 arr[index+1]=insertVal; 59 } 60 } 61 }
运行结果如下:
1 12 23 27 33 55 76 2 插入排序法排序前时间:Sun Mar 06 22:48:09 CST 2016 3 插入排序法排序后时间:Sun Mar 06 22:48:10 CST 2016
17.3.3.2 谢耳排序法
17.3.3.3 二叉树排序法
17.4 外部排序
17.4.1 合并排序法
17.4.2 直接合并排序法
17.5 排序方法比较及总结
排序速度:冒泡排序法<选择排序法<插入排序法<快速排序法
面试常考:冒泡排序法、选择排序法、插入排序法
快速排序法:理解较困难,可记忆。