插入排序
插入排序(InsertionSort),一般也被称为直接插入排序。
对于少量元素的排序,它是一个有效的算法。插入排序是一种最简单的排序方法,它的基本思想是将一个记录插入到已经排好序的有序表中,从而一个新的、记录数增 1 的有序表
在其实现过程使用双层循环,外层循环对除了第一个元素之外的所有元素,内层循环对当前元素前面有序表进行待插入位置查找,并进行移动。
第一轮:从第二位置的 6 开始比较,比前面 7 小,交换位置。
第二轮:第三位置的 9 比前一位置的 7 大,无需交换位置。
第三轮:第四位置的 3 比前一位置的 9 小交换位置,依次往前比较。
第四轮:第五位置的 1 比前一位置的 9 小,交换位置,再依次往前比较。
public static void InsertSort(int[] arr) {
for (int i = 0; i < arr.length; i++) {
for (int j = i; j > 0; j--) {
if (arr[j] < arr[j - 1]) {
int tmp = arr[j];
arr[j] = arr[j - 1];
arr[j - 1] = tmp;
} else
break;
}
}
}
选择排序
选择排序(Selection Sort)是一种简单直观的排序算法。它的工作原理是这样的:
首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中
继续寻找最小(大)元素,然后放到已排序系列的末尾。依次类推,直到所有全是均排序完毕。选择排序主要优点与数据移动有关。如果某个元素位于正确的最终位置上,则它不会被移动。选择排序
每次交换一对元素,它们当中至少有一个将被移动到其他最终位置上,因此,对n个元素的表进行排序总共
进行至多n-1此交换。在所有的完全依靠交换去移动元素的排序方法中,选择排序属于非常好的一种。
从这个图来看,选择排序实际上把列表分成了左右的两部分,左边是已经排序好的部分,右边是没有排序的数列。第一次,13是最小,位置不用移动,第二次从13之外剩余数列中选择一个最小的数是27,然后把27拿出来,放到13的后面。依次类推,左边已经排序好的越来越多,右边未排序的越来越少,直到右边没有元素
public static void slectSort(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
int MinIndex = i;
for (int j = i + 1; j < arr.length; j++) {
if (arr[MinIndex] > arr[j]) {
MinIndex = j;
}
}
int tmp = arr[i];
arr[i] = arr[MinIndex];
arr[MinIndex] = tmp;
}
}
冒泡排序
冒泡排序(Bubble
Sort)是一种简单的排序算法。它重复地遍历要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。遍历数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢"浮"到数列的顶端。
冒泡排序的过程和图解分析
冒泡排序算法的运作如下:
1)比较相邻的元素,如果第一个比第二个大(升序),就交换他们两个位置。
2)对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完,最后的元素会是最大的数。
3)针对所有的元素重复以上步骤,除了最后一个。
4)持续每次对越来越少的元素重复上面步骤,直到没有任何一对数字需要比较。
下面这个图,表示第一个步骤和第二个步骤的过程。
上面一遍走下来之后,确保最大的数字93已经排到最末尾了,下次就排序93之前的数据就可以。依次,第二次走完一遍,数字77会放到93的前面,也就是整个数列倒数第二个位置。以此类推,每下一次要排序的数列都会缩短一个元素,需要交换的次数也越来越小,直到不需要交换位置,这个时候排序结束。
private static void BubbleSort(int[] arr) {
int tmp;
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j < arr.length - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
}
快速排序
快速排序(QuickSort),又称划分交换排序,通过一趟排序将要排序的数据分割成独立的两部分。其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按照此方法对两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
快速排序思想和图解
快速排序步骤为:
1.从数列中挑出一个元素,称为"基准"。
2.重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准大的摆放在基准的后面,相同的可以摆到任意一边。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
3.递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
递归的最底部情形,是数列的大小是0或者1,也就是永远都已经被排序好了。虽然一直递归下去,但是这个算法总会结束,因为在每次迭代中,它至少会把一个元素摆放到它最后面的位置去。
package com.anthony.sort;
import java.util.Arrays;
public class QuickSort {
public static void main(String[] args) {
int[] arr = {54, 26, 93, 17, 77, 31, 44, 55, 20};
System.out.println(Arrays.toString(arr));
quickSort(arr, 0, arr.length-1);
System.out.println(Arrays.toString(arr));
}
public static void quickSort(int[] arr, int first, int last) {
if (first >= last){
return ;
}
int mid_value = arr[first];
int low = first;
int high = last;
while ( low < high) {
// 基准值和high对应值比较,high左移
while ( low < high && arr[high] >= mid_value) {
// 说明high对应元素大于中间基准值,high需要往左移动
high -= 1;
}
// 退出循环,把high和low对应元素进行位置交换
int tmp = arr[low];
arr[low] = arr[high];
arr[high] = tmp;
// 基准值和low对应的值比较, low右移
while ( low < high && arr[low] < mid_value) {
low += 1;
}
// 退出循环,
int tmp1 = arr[high];
arr[high] = arr[low];
arr[low] = tmp1;
}
// 从循环退出时,low==high
arr[low] = mid_value;
// 对low左边列表执行快速排序,递归调用
quickSort(arr, first, low-1);
// 对low右边列表进行排序
quickSort(arr, low+1, last);
}
}