排序算法
Posted gshao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了排序算法相关的知识,希望对你有一定的参考价值。
参考:https://blog.csdn.net/weixin_40205234/article/details/86699088
https://blog.csdn.net/adusts/article/details/80882649
从执行效率:冒泡排序<选择排序<插入排序<快速排序。
从稳点性: 快速排序,选择排序 不稳定; 冒泡排序,插入排序 稳定。
1. 冒泡排序
以升序为例,两个相邻的数比较大小,如果前面的数比后面的数大,那么交换位置。双重for循环,外层循环控制轮数,内层循环控制每轮比较的次数,每轮比较会将该轮最大数交换到最后面。
代码:
public class BubbleSort { public static void main(String[] args) { int[] arr = {3,44,38,5,47,15,36,26,27,2,46,4,19,50,48}; BubbleSort(arr); System.out.println(Arrays.toString(arr)); } public static void BubbleSort(int []arr) { //外层循环控制轮数 for(int i=1;i<=arr.length-1;i++) { //内层循环控制每轮比较的次数 for(int j=1;j<=arr.length-i;j++) { if(arr[j-1]>arr[j]) { //借助中间变量交换两个位置上的值 int temp = arr[j-1]; arr[j-1]= arr[j]; arr[j]=temp; } } } } }
动态演示:
2. 选择排序
以升序为例,在未排序序列中找到最小元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
代码:
public class SelectionSort { private void mian() { int[] arr = {3,44,38,5,47,15,36,26,27,2,46,4,19,50,48}; SelectionSort(arr); System.out.println(Arrays.toString(arr)); } private void SelectionSort(int[] arr) { for(int i =0;i<arr.length-1;i++) { int minIndex = i; for(int j=i;j<arr.length-1;j++) { if(arr[minIndex]>arr[j]) { minIndex = j; //记下目前找到的最小值所在的位置 } } //在内层循环结束,也就是找到本轮循环的最小的数以后,再进行交换 if (minIndex != i){ int temp = arr[i]; arr[i] = arr[minIndex]; arr[minIndex] = temp; } } } }
动态演示;
3. 插入排序
- 从第一个元素开始,该元素可以认为已经被排序;
- 取出下一个元素,在已经排序的元素序列中从后向前扫描;
- 如果该元素(已排序)大于新元素,将该元素移到下一位置;
- 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;
- 将新元素插入到该位置后;
- 重复步骤2~5。
代码:
public class InsertSort { public static void main(String[] args) { int[] arr = {3,44,38,5,47,15,36,26,27,2,46,4,19,50,48}; insertionSort(arr); System.out.println(Arrays.toString(arr)); } private static void insertionSort(int []arr){ for(int i=1; i<arr.length; i++){ int preIndex = i-1; int current = arr[i]; while(preIndex>=0 && arr[preIndex]>current){ arr[preIndex+1]=arr[preIndex]; preIndex--; } arr[preIndex+1]=current; } } }
动态演示:
4. 快速排序:
步骤为:
- 从数列中挑出一个元素,称为"基准"(pivot),
- 重新排序数列,所有比基准值小的元素摆放在基准前面,所有比基准值大的元素摆在基准后面(相同的数可以到任何一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
- 递归地(recursively)把小于基准值元素的子数列和大于基准值元素的子数列排序。
递归到最底部时,数列的大小是零或一,也就是已经排序好了。这个算法一定会结束,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。
代码:
public class QuickSort { public static void main(String[] args) { int[] arr = {3,44,38,5,47,15,36,26,27,2,46,4,19,50,48}; quickSort(arr,0,arr.length-1); System.out.println(Arrays.toString(arr)); } private static void quickSort(int[] arr, int low, int high) { if (low < high) { // 找寻基准数据的正确索引 int index = getIndex(arr, low, high); // 进行迭代对index之前和之后的数组进行相同的操作使整个数组变成有序 quickSort(arr, 0, index - 1); quickSort(arr, index + 1, high); } } private static int getIndex(int[] arr, int low, int high) { // 基准数据 int tmp = arr[low]; while (low < high) { // 当队尾的元素大于等于基准数据时,向前挪动high指针 while (low < high && arr[high] >= tmp) { high--; } // 如果队尾元素小于tmp了,需要将其赋值给low arr[low] = arr[high]; // 当队首元素小于等于tmp时,向前挪动low指针 while (low < high && arr[low] <= tmp) { low++; } // 当队首元素大于tmp时,需要将其赋值给high arr[high] = arr[low]; } // 跳出循环时low和high相等,此时的low或high就是tmp的正确索引位置 // 由原理部分可以很清楚的知道low位置的值并不是tmp,所以需要将tmp赋值给arr[low] arr[low] = tmp; return low; // 返回tmp的正确位置 } }
动态演示:
借用下啊哈算法的图:
i和j分别为左哨兵和右哨兵,这里枢纽元定为6,然后分别从左往右(i++)和右往左(j--)开始遍历
左哨兵查找比6大的元素,右哨兵查找比6小的元素
第一次交换结果
第二次交换结果
相遇后直接与枢纽元交换
然后再递归排序就行
以上是关于排序算法的主要内容,如果未能解决你的问题,请参考以下文章