排序的分类及部分实现
根据在排序过程中涉及的存储器不同,可将排序方法分为两大类:内部排序和外部排序。
内部排序是指待排序列完全存放在内存中所进行的排序过程,适合不太大的元素序列。
外部排序指的是大文件的排序,待排序的文件无法一次装入内存,将待排序的记录存储再外存储器上,需要在内存和外部存储器之间进行多次数据交换,已达到排序整个文件的目的。
根据有序序列长度增加所用策略不同,可将内部排序方法分为5类:交换排序、选择排序、插入排序、归并排序和基数排序。其中交换排序、插入排序和选择排序是一个逐步扩大记录的有序序列长度的过程。
交换排序是对无序区中记录的关键字两两进行比较,若逆序交换,直到关键字之间不存在逆序为止。冒泡排序和快速排序是交换排序中最典型的两个方法。
简单选择排序和堆排序是选择排序中最典型的两个方法。
直接插入排序和希尔排序是插入排序中最典型的两个方法。
归并排序是不断将两个或两个以上有序区合并成一个有序区,直到全部记录有序。
可分为稳定排序与不稳定排序两种:
稳定排序有冒泡排序、直接插入排序、归并排序、基数排序;
不稳定排序有选择排序、快速排序、希尔排序、堆排序
几种简单排序的Java实现
1、冒泡排序
1 public class BubblingSort 2 { 3 public static void main(String[] args) 4 { 5 int[] a = {6,5,3,2,0}; 6 sort(a); 7 } 8 9 /** 10 * 冒泡排序 11 * 复杂度最优为n 12 * 最差为n平方 13 */ 14 private static void sort(int[] a) 15 { 16 for(int i = 0; i < a.length; i ++) 17 { 18 boolean flag = true; //优化,设置标识 19 for(int j = i + 1; j < a.length; j ++) 20 { 21 if(a[i] < a[j]) //前后两个元素比较 22 { 23 int temp = a[i]; //交换 24 a[i] = a[j]; 25 a[j] = temp; 26 flag = false; //若有交换,标识设为false,表示数组还不是有序数组 27 } 28 } 29 if(flag) //若一轮比较之后,flag为true,即未进行过交换,证明数组已是有序,跳出循环 30 { 31 break; 32 } 33 } 34 for(int i = 0; i < a.length; i ++) 35 { 36 System.out.print(a[i] + " "); 37 } 38 } 39 }
2、插入排序
1 public class InsertSort 2 { 3 public static void main(String[] args) 4 { 5 int[] a = {2,5,6,0,3}; 6 sort(a); 7 } 8 9 /** 10 * 插入排序 11 * 复杂度最优为n 12 * 最差为n平方 13 */ 14 private static void sort(int[] a) 15 { 16 for(int i = 0; i < a.length - 1; i ++) 17 { 18 if(a[i] > a[i + 1]) //若当前值大于下一个值,进行插排('>'为正序,'<'为倒序) 19 { 20 int x = a[i + 1]; //先将下标为i+1的值存入临时变量x中 21 int j = i + 1; //设置一个将数组值后移的下标j,j为当前进行判断的后一位下标(j之前可看成一个有序数组) 22 /** 23 * 将j之前的有序数组后移,直到临时变量的值找到有序数组中合适的位置 24 */ 25 do 26 { 27 j --; 28 a[j + 1] = a[j]; 29 }while(j > 0 && x < a[j - 1]); 30 a[j] = x; //将临时变量x的值放入有序数组的合适位置 31 } 32 } 33 for(int i = 0; i < a.length; i ++) 34 { 35 System.out.print(a[i] + " "); 36 } 37 } 38 }
3、快速排序
1 public class QuickSort 2 { 3 public static void main(String[] args) 4 { 5 int[] a = {6,5,3,2,0}; 6 sort(a,0,a.length - 1); 7 for(int i = 0; i < a.length; i ++) 8 { 9 System.out.print(a[i] + " "); 10 } 11 } 12 13 private static void sort(int[] a, int left, int right) 14 { 15 if(left >= right) //如果左边的数组大于或等于就代表已经整理完成一个组了 16 { 17 return; 18 } 19 int i = left; 20 int j = right; 21 int key = a[left]; 22 while(i < j) //控制在当组内寻找一遍 23 { 24 /** 25 * 而寻找结束的条件就是: 26 * 1、找到一个小于或者大于key的数(大小取决于你想升序还是降序) 27 * 2、没有符合的i与j相遇 28 */ 29 while(i < j && key <= a[j]) 30 { 31 j --; //向前寻找 32 } 33 a[i] = a[j]; //找到一个这样的数后就把他赋给前面的被拿走的i的值(如果第一次循环且key是a[0],那么就是给key) 34 while(i < j && key >= a[i]) 35 { 36 i ++; 37 } 38 a[j] = a[i]; 39 a[i] = key; 40 } 41 sort(a,left,i -1); 42 sort(a,i + 1, right); 43 } 44 }
4、选择排序
1 public class SelectSort 2 { 3 public static void main(String[] args) 4 { 5 int[] a = {0,2,3,5,6}; 6 sort(a); 7 } 8 9 10 /** 11 * 选择排序 12 * 平均复杂度为n平方 13 */ 14 private static void sort(int[] a) 15 { 16 for(int i = 0; i < a.length - 1; i ++) 17 { 18 int k = i; //设置标识 19 for(int j = i + 1; j < a.length; j ++) 20 { 21 if(a[k] > a[j]) //将下标为i的元素与其后的元素比较 22 { 23 k = j; //k记录最小(大)值的下标 24 } 25 } 26 if(k != i) //若k不等于当前下标,进行交换 27 { 28 int temp = a[k]; 29 a[k] = a[i]; 30 a[i] = temp; 31 } 32 } 33 for(int i = 0; i < a.length; i ++) 34 { 35 System.out.print(a[i] + " "); 36 } 37 } 38 }