排序算法在很多的领域都受到相当地重视,下面为由 Java 实现的三种简单排序,他们的平均时间复杂度都为 O(N^2) ,并不是十分迅速的算法。但由于这些算法有利于我们理解在此基础上的更加复杂的算法,加之在某些情况下这些算法比复杂的算法更加有效,所以掌握这些基本的算法还是十分有必要的,该文章中所有排序示例均为升序排序。
首先,我们定义两个辅助函数来帮助我们完成算法,他们分别是用于比较两元素大小的
Compare(double a,double b) 方法
int Compare(double a,double b) { if(a>b) return 1; else if(a == b) return 0; else return -1; }
其次是用于交换所需排序数组中两元素的值的Swap(double[] a, int i,int j) 方法
void Swap(double[] a,int i,int j) { double temp; temp = a[i]; a[i] = a[j]; a[j] = temp; }
1.冒泡排序:
冒泡排序的思想是将序列中的第1个元素与第2个元素进行比较,如果前者大于后者,则交换两元素位置,否者不交换;再将第2个元素与第三个元素比较,依次类推,知道第n-1个元素与第n个元素进行过比较(或交换)。经过第一趟排序,使得元素序
列中最大的元素被安排在第n个位置上,然后再通过同样的方法将第2大的元素排列到第n-1的位置上,一次类推,直到将最小的元素排列到第一个位置上。图式如下:
示例代码如下:
public static void BubblerSort(double[] a) { for(int i=0;i<a.length-1;i++) for(int j=i+1;j<a.length;j++) { if(Compare(a[i],a[j])==1)//如果第i个元素大于第i+1个元素则交换位置 Swap(a,i,j); } }
排序可视化:
时间复杂度分析:
冒泡排序的外层for循环的循环次数为n-1,内层for循环的循环次数为i,可知比较次数:
n*(n-1)/2 = O(n^2)
所以冒泡排序的最好、最坏和平均情况下的时间复杂度都为O(n^2).
2.直接插入排序:
直接插入排序的思想是将第一个元素看成是一个有序子序列,然后在从第二个记录起逐个插入到这个有序子序列中并形成新的有序子序列直至整个序列都变成有序序列。一般的,在第i步上,将a[i]插入到由a[0]到a[i-1]构成的有序子序列中。图示如下:
示例代码如下:
public static void StraightInsertSort(double[] a) { int temp; for(int i=0;i<a.length;i++) { temp = i; for(int j=i;j>=0;j--) { if(Compare(a[temp],a[j])==-1) { Swap(a,temp,j); temp--; } } } }
排序可视化:
时间复杂度分析:
在最好的情况下,即元素按照升序有序排列的情况下,此时每个内层for循环刚已进入就退出,只比较一次而不移动,易知总的比较次数为n-1,可知时间复杂度为O(n).
而在最坏的情况下,即元素逆序排列的情况下,第1循环1次,第2循环2次,以此类推,总循环次数为:
n*(n-1)/2 = O(n^2)
而在排序的一般情况下,所需排列的元素是随机的,即每个元素出现的概率是相同的,易知直接插入排序的时间复杂度为O(n^2).
3.简单选择排序:
简单选择排序的思想是从未排序的序列中选择最小的元素,接着是次小的,以此类推,需检索整个未检索部分,但只需一次交换就将待排序元素放到正确位置上。一般的,第i趟是从a[i]到a[n-1]中选择第i小元素并将此元素放到a[i]处。图示如下:
示例代码如下:
public static void SimpleSelectSort(double[] a) { int min; for(int i=0;i<a.length-1;i++) { min = i; for(int j=i+1;j<a.length;j++) { if(Compare(a[min],a[j])==1) min = j; } Swap(a,i,min); } }
排序可视化:
时间复杂度分析:
简单选择排序的外层for循环共循环n-1次,内层for循环共循环n-1-i次,易知时间复杂度为O(n^2).
4.完整代码:
////////////////////////////////////////////////////////////////// // // // // // 0.该类中所有排序结果均为升序排序; // // 1.类中所有排序方法均由 public static 修饰,可直接调用 ; // // // // // ////////////////////////////////////////////////////////////////// public class Sort { /* * 三种简单排序,平均时间复杂度均为 O(n^2); */ /* * 冒泡排序 */ public static void BubblerSort(double[] a) { for(int i=0;i<a.length-1;i++) for(int j=i+1;j<a.length;j++) { if(Compare(a[i],a[j])==1) Swap(a,i,j); } } /* * 选择排序 */ public static void SimpleSelectSort(double[] a) { int min; for(int i=0;i<a.length-1;i++) { min = i; for(int j=i+1;j<a.length;j++) { if(Compare(a[min],a[j])==1) min = j; } Swap(a,i,min); } } /* * 插入排序 */ public static void StraightInsertSort(double[] a) { int temp; for(int i=0;i<a.length;i++) { temp = i; for(int j=i;j>=0;j--) { if(Compare(a[temp],a[j])==-1) { Swap(a,temp,j); temp--; } } } } /* * 用于比较的方法 */ static int Compare(double a,double b) { if(a>b) return 1; else if(a == b) return 0; else return -1; } /* * 用于交换两数字的方法 */ static void Swap(double[] a,int i,int j) { double temp; temp = a[i]; a[i] = a[j]; a[j] = temp; } }文中排序可视化图片摘自博客:http://blog.csdn.net/paxhujing/article/details/51593973 点击打开链接