1. 插入排序
1.1 直接插入排序
1 public void sort(int[] arr) { 2 int tmp; 3 for(int i = 1; i < arr.length; i++) { 4 // 待插入数据 5 tmp = arr[i]; 6 int j; 7 for(j = i - 1; j >= 0; j--) { 8 // 判断是否大于tmp,大于则后移一位 9 if(arr[j] > tmp) { 10 arr[j+1] = arr[j]; 11 }else{ 12 break; 13 } 14 } 15 arr[j+1] = tmp; 16 System.out.println(i + ":" + Arrays.toString(arr)); 17 } 18 }
1.2 希尔排序(最小增量排序)
希尔排序严格来说是基于插入排序的思想,又被称为缩小增量排序。
1 public void sort(int[] arr) { 2 // i表示希尔排序中的第n/2+1个元素(或者n/4+1) 3 // j表示希尔排序中从0到n/2的元素(n/4) 4 // r表示希尔排序中n/2+1或者n/4+1的值 5 int i, j, r, tmp; 6 // 划组排序 7 for(r = arr.length / 2; r >= 1; r = r / 2) { 8 for(i = r; i < arr.length; i++) { 9 tmp = arr[i]; 10 j = i - r; 11 // 一轮排序 12 while(j >= 0 && tmp < arr[j]) { 13 arr[j+r] = arr[j]; 14 j -= r; 15 } 16 arr[j+r] = tmp; 17 } 18 System.out.println(i + ":" + Arrays.toString(arr)); 19 } 20 }
2. 交换排序
2.1 冒泡排序
原理:比较两个相邻的元素,将值大的元素交换至右端。
思路:依次比较相邻的两个数,将小数放在前面,大数放在后面。即在第一趟:首先比较第1个和第2个数,将小数放前,大数放后。然后比较第2个数和第3个数,将小数放前,大数放后,如此继续,直至比较最后两个数,将小数放前,大数放后。重复第一趟步骤,直至全部排序完成。
举例说明:要排序数组:int[] arr={6,3,8,2,9,1};
第一趟排序:
第一次排序:6和3比较,6大于3,交换位置: 3 6 8 2 9 1
第二次排序:6和8比较,6小于8,不交换位置:3 6 8 2 9 1
第三次排序:8和2比较,8大于2,交换位置: 3 6 2 8 9 1
第四次排序:8和9比较,8小于9,不交换位置:3 6 2 8 9 1
第五次排序:9和1比较:9大于1,交换位置: 3 6 2 8 1 9
第一趟总共进行了5次比较, 排序结果: 3 6 2 8 1 9
---------------------------------------------------------------------
第二趟排序:
第一次排序:3和6比较,3小于6,不交换位置:3 6 2 8 1 9
第二次排序:6和2比较,6大于2,交换位置: 3 2 6 8 1 9
第三次排序:6和8比较,6大于8,不交换位置:3 2 6 8 1 9
第四次排序:8和1比较,8大于1,交换位置: 3 2 6 1 8 9
第二趟总共进行了4次比较, 排序结果: 3 2 6 1 8 9
---------------------------------------------------------------------
第三趟排序:
第一次排序:3和2比较,3大于2,交换位置: 2 3 6 1 8 9
第二次排序:3和6比较,3小于6,不交换位置:2 3 6 1 8 9
第三次排序:6和1比较,6大于1,交换位置: 2 3 1 6 8 9
第二趟总共进行了3次比较, 排序结果: 2 3 1 6 8 9
---------------------------------------------------------------------
第四趟排序:
第一次排序:2和3比较,2小于3,不交换位置:2 3 1 6 8 9
第二次排序:3和1比较,3大于1,交换位置: 2 1 3 6 8 9
第二趟总共进行了2次比较, 排序结果: 2 1 3 6 8 9
---------------------------------------------------------------------
第五趟排序:
第一次排序:2和1比较,2大于1,交换位置: 1 2 3 6 8 9
第二趟总共进行了1次比较, 排序结果: 1 2 3 6 8 9
---------------------------------------------------------------------
最终结果:1 2 3 6 8 9
---------------------------------------------------------------------
由此可见:N个数字要排序完成,总共进行N-1趟排序,每i趟的排序次数为(N-i)次,所以可以用双重循环语句,外层控制循环多少趟,内层控制每一趟的循环次数,即
public static void BubbleSort(int[] arr) { int temp;//定义一个临时变量 for(int i=0;i<arr.length-1;i++){//冒泡趟数 for(int j=0;j<arr.length-i-1;j++){ if(arr[j+1]<arr[j]){ temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; } } } }
2.2 快速排序
单单看以上解释还是有些模糊,可以通过实例来理解它,下面通过一组数据来进行排序过程的解析:
原数组:{3,7,2,9,1,4,6,8,10,5}
期望结果:{1,2,3,4,5,6,7,8,9,10}
花了点时间撸了下面这张快速排序示意图:
Demo步骤解析:
1.一开始选定数组的最后一个元素5作为基准值,也就是最终排序结果应该是以5为界限划分为左右两边。
2.从左边开始,寻找比5大的值,然后与5进行调换(因为如果比5小的值本来就应该排在5前面,比5大的值调换之后就去到了5的后面),一路过来找到了7,将7与5调换,结束此次遍历。
3.从右边开始,由于7已经是上一轮排好序的便不再动它,从10开始,一路向左遍历,寻找比5小的值,然后与5进行调换(因为如果比5大的值本来就应该排在5后面,比5小的值调换之后就去到了5的后前面),一路过来找到了4,将4与5调换,结束此次遍历。
4.从左边开始,由于3和4都是前两轮已经排好序的便不再动它,从2开始,一路向右遍历,寻找比5大的值,然后与5进行调换(道理同步骤2),一路过来找到了9,将9与5调换,结束此次遍历。
5.从右边开始,由于排在9后面的那几个数字都是上几轮排好序的便不再动它,从1开始,一路向右遍历,寻找比5小的值,然后与5进行调换(道理同步骤3),一下子就找到了1,将1与5调换,结束此次遍历。
6.这个时候,发现5的左右两边都是排好序了的,所以结束此轮排序,5的左右两边抽出来各自进行下一轮的排序,规则同上,直到无法再拆分下去,即完成了整体的快速排序。
- /**
- * 快速排序
- * @author IT_ZJYANG
- */
- public class QuickSort {
- /**
- * 将数组的某一段元素进行划分,小的在左边,大的在右边
- * @param a
- * @param start
- * @param end
- * @return
- */
- public static int divide(int[] a, int start, int end){
- //每次都以最右边的元素作为基准值
- int base = a[end];
- //start一旦等于end,就说明左右两个指针合并到了同一位置,可以结束此轮循环。
- while(start < end){
- while(start < end && a[start] <= base)
- //从左边开始遍历,如果比基准值小,就继续向右走
- start++;
- //上面的while循环结束时,就说明当前的a[start]的值比基准值大,应与基准值进行交换
- if(start < end){
- //交换
- int temp = a[start];
- a[start] = a[end];
- a[end] = temp;
- //交换后,此时的那个被调换的值也同时调到了正确的位置(基准值右边),因此右边也要同时向前移动一位
- end--;
- }
- while(start < end && a[end] >= base)
- //从右边开始遍历,如果比基准值大,就继续向左走
- end--;
- //上面的while循环结束时,就说明当前的a[end]的值比基准值小,应与基准值进行交换
- if(start < end){
- //交换
- int temp = a[start];
- a[start] = a[end];
- a[end] = temp;
- //交换后,此时的那个被调换的值也同时调到了正确的位置(基准值左边),因此左边也要同时向后移动一位
- start++;
- }
- }
- //这里返回start或者end皆可,此时的start和end都为基准值所在的位置
- return end;
- }
- /**
- * 排序
- * @param a
- * @param start
- * @param end
- */
- public static void sort(int[] a, int start, int end){
- if(start > end){
- //如果只有一个元素,就不用再排下去了
- return;
- }
- else{
- //如果不止一个元素,继续划分两边递归排序下去
- int partition = divide(a, start, end);
- sort(a, start, partition-1);
- sort(a, partition+1, end);
- }
- }
- }