参考文献:https://blog.csdn.net/singgel/article/details/80335658
交换排序
1.冒泡排序:首先将第一个记录的键值和第二个键值进行比较,若为逆序,即R[1].key大于R[2].key,则将这两个记录交换,然后继续比较第二个和第三个记录的键值,依此类推,直到完成第n-1个记录和第n个记录的键值比较交换为止,上述过程称为第一趟起泡,其结果使键值最大的记录移到了第n个位置上,然后再进行第二趟起泡,即对前n-1个记录进行同样的操作,其结果是次大键值的记录安置在第n-1个位置上,重复上面的过程。当在一趟起泡过程中没有进行记录交换的操作时,整个排序过程终止。
public void bubbleSort(int[] arr) {
//一共比较的次数为数组的长度-1
for(int i=0;i<arr.length-1;i++) {
//依次比较相邻两个元素的大小
//注意此时比较的总长度 为原数组的长度减去比较过的次数再-1
for(int j=0;j<arr.length-i-1;j++) {
if(arr[j]>arr[j+1]) {
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
2.快速排序:对于给定的一组记录,选择一个基准元素,通常选择第一个元素或者最后一个元素,通过一趟扫描,将待排序列分成两部分,一部分比基准元素小, 一部分大于等于基准元素,此时基准元素在其排好序后的正确位置,然后再用同样的方法递归地排序划分的两部分,直到序列中的所有记录均有序为止。该方法增大了记录的比较和移动的距离,将关键字较大的记录从前面直接移动到后面,关键字较小的记录从后面直接移动到前面,从而减少了总的比较次数和移动次数。
这篇文章讲的很好:https://blog.csdn.net/weixin_37817685/article/details/79969349
public void quickSort(int[] arr, int left, int right) {
//先确保数组长度
if(left > right) {
return;
}
int i = left, j = right;
//基准位
int base = arr[left];
while(i<j) {
//先从后往前查找,循环每次进行j--
while(i<j && arr[j] >= base)
j--;
//然后从前往后查找,循环每次进行i++
while(i<j && arr[i] <= base)
i++;
//如果满足条件则交换
if(i<j) {
int temp = arr[j];
arr[j] = arr[i];
arr[i] = temp;
}
}
//最后将基准位与最后一个i或j相等位置的元素交换
arr[left] = arr[i];
arr[i] = base;
//递归调用左半数组
quickSort(arr, left, j-1);
//递归调用右半数组
quickSort(arr, j+1, right);
}
插入排序
3.直接插入排序:基本思想是依次将每个记录插入到一个已排好序的有序表中去,从而得到一个新的、记录数增加1的有序表。
public void insertionSort(int[] arr) {
for(int i=1;i<arr.length;i++) {
//将元素依次与之前所有的元素进行比较
for(int j=i;j>0;j--) {
if(arr[j]<arr[j-1]) {
int temp = arr[j-1];
arr[j-1] = arr[j];
arr[j] = temp;
}
}
}
}
4.希尔排序:先将要排序的一组数按某个增量d(n/2,n为要排序数的个数)分成若干组,每组中记录的下标相差d。对每组中全部元素进行直接插入排序,然后再用一个较小的增量(d/2)对它进行分组,在每组中再进行直接插入排序。当增量减到1时,进行直接插入排序后,排序完成。
public void shellSort(int[] arr) {
int i,j,temp;
//按照某一增量
for(int increment = arr.length / 2; increment > 0; increment /= 2) {
System.out.println("increment:" + increment);
//对每组相对应元素进行直接插入排序
for(i = increment; i < arr.length; i++) {
// System.out.println("i:" + i);
temp = arr[i];
for(j = i - increment; j >= 0; j -= increment) {
// System.out.println("j:" + j);
// System.out.println("temp:" + temp);
// System.out.println("data[" + j + "]:" + data[j]);
if(arr[j] > temp) {
arr[j + increment] = arr[j];
}
else {
break;
}
}
arr[j + increment] = temp;
}
for (i = 0; i < arr.length; i++)
System.out.print(arr[i] + " ");
}
}
选择排序
5.直接选择排序:基本思想是在第i次选择操作中,通过n-i次键值间比较,从n-i+1个记录中选出键值最小的记录,并和第i(1小于等于1小于等于n-1)个记录交换
public void selectionSort(int[] arr) {
//每次选择第i个元素和后面所有的元素进行比较,选择其中最小的元素插入到i位置
//注意最后一个元素不用进行比较,所以一共比较的次数为数组的长度-1
for(int i=0;i<arr.length-1;i++) {
int min_index = i;
//每次选择最小的元素插入到相应的i位置
for(int j=i+1;j<arr.length;j++) {
if(arr[min_index]>arr[j]) {
min_index = j;
}
}
if(min_index != i) {
int temp = arr[i];
arr[i] = arr[min_index];
arr[min_index] = temp;
}
}
}
归并排序
6.归并排序:将两个或两个以上的有序文件合并成为一个新的有序文件,归并排序是把一个有n个记录的无序文件看成是由n个长度为1的有序子文件组成的文件,然后进行两两归并,如此重复,直至最后形成包含n个归并,得到n/2个长度为2或者1的有序文件,再两两归并,如此重复,直至最后形成包含n个记录的有序文件位置。这种反复将两个有序文件归并成一个有序文件的排序方法称为二路归并排序。二路归并排序的核心操作是将一堆数组中前后相邻的两个有序序列归并为一个有序序列。
public class MergeSort {
public void mergeSort(int[] arr, int left, int right) {
//当分到只有一个元素的时候,退出递归程序
if(left >= right) {
return;
}
int mid = (left + right)/2;
mergeSort(arr,left,mid); //左边排序
mergeSort(arr,mid+1,right); //右边排序
merge(arr,left,mid,right); //将两个有序子数组合并
}
public void merge(int[] arr, int left, int mid, int right) {
//创建临时数组,长度为左右左部分有部分两个数组长度之和
int[] temp = new int[right-left+1];
int i = left; //左序列指针
int j = mid+1; //右序列指针
int t = 0; //临时指针
while(i<=mid&&j<=right) {
if(arr[i]<arr[j]) {
temp[t] = arr[i];
t++;
i++;
}
else {
temp[t] = arr[j];
t++;
j++;
}
}
//如果左边还有剩余,将左边剩余的归并
while(i<=mid) {
temp[t++] = arr[i++];
}
//如果右边
while(j<=right) {
temp[t++] = arr[j++];
}
//将临时数组更新到原数组
t = 0;
while(t<temp.length) {
arr[left++] = temp[t++];
}
}