本文主要收集整理了一下自己学习的思路,借鉴了一些优秀博主对其的理解。
1.冒泡排序(Bubble Sort)
思路:
假设我们从小到大排序:
它重复地走访要排序的元素列,依次比较两个相邻的元素,如果左边大于右边,就将左右数进行交换,这样,我们每次都能找到一个最大的值,并放到数组最右边。
代码:
public static void bubblingSort(int[] array){
int time = array.length-1;//初始化要交换的次数
int a = 0;//临时变量,用于交换
for(int i = 0;i<array.length-1;i++){
int count = 0;//变量用于记录交换次数
for(int j = 0;j<time;j++){
// 判断大小,大就交换
if(array[j]>array[j+1]){
a = array[j];
array[j] = array[j+1];
array[j+1] = a;
count++;
}
}
if(count==0){//如果一次循环中没完成一次交换,那么直接退出,无需再重复做无用循环
break;
}
time--;
}
for(int i = 0;i<array.length;i++){
System.out.print(array[i]+" ");
}
}
2.插入排序(InsertionSort)
思路:
如果:arr[index]>arr[index+1],就让arr[index+1]=arr[index] 然后和下一个比
这样一直比,直到arr[index]<arr[index+1],再插入即可;
代码:
public static void insertSort(int[] array){
for(int i = 1;i<array.length;i++){
int insertValue = array[i];//每次那一个值来插入
int index = i-1;//表示最后一个元素的下标
while(index>=0&&insertValue<array[index]){//当插入的值小于最后一个元素
array[index+1] = array[index];//将最后一个的值后移一位,为后续插入腾位置
index--;//最后一个比不过就退一个比,直至比到满足条件
}
// 退出循环就是满足条件
if(index+1 !=i) {//如果现在插入的位置就是它本来的位置,你那么就不用插入
array[index + 1] = insertValue;
}
}
// 打印结果
for(int i = 0;i<array.length;i++){
System.out.print(array[i]+" ");
}
}
3.希尔排序
思路:希尔排序就是缩小增量的插入排序
例:
初始增量第一趟 gap = length/2 = 4
第二趟,增量缩小为 2
第三趟,增量缩小为 1,得到最终排序结果
代码:
public static String shell2(int [] sort){
for( int len = sort.length/2;len>0;len/=2) {
// 这里是计算出每次要操作的次数
for(int i = len;i<sort.length;i++){
int j =i;
// 记录当前操作值
int temp = sort[j];
// 此时前一个数小于隔自己步数值的数
if(sort[j] <sort[j-len]){
while (j-len>=0&& temp<sort[j-len]){
sort[j] = sort[j-len];
j-=len;
}
sort[j] = temp;
}
}
}
return Arrays.toString(sort);
}
4.归并排序
思路:归并排序采用的是分治的思想
归并排序,先将待排序的数组不断拆分,直到拆分到区间里只剩下一个元素的时候。不能再拆分的时候。这个时候我们再想办法合并两个有序的数组,得到长度更长的有序数组。当前合并好的有序数组为下一轮得到更长的有序数组做好了准备。一层一层的合并回去,直到整个数组有序。
如何进行合并?
由于数组分到最后只有一个,那么相对于他的父数据,中轴左右是有序的。
就比如:
那么我们只需要将子数组的左右依次遍历,谁小就将其保存,这样遍历完子数组,整合起来的父数组就是有序的
代码:
/**
* 递归函数对nums[left...right]进行归并排序
* @param nums 原数组
* @param left 左边的索引
* @param right 右边记录索引位置
* @param temp
*/
private static void mergeSort2(int[] nums, int left, int right, int[] temp) {
if (left == right){//当拆分到数组当中只要一个值的时候,结束递归
return;
}
int mid = (left+right)/2; //找到下次要拆分的中间值
mergeSort2(nums,left,mid,temp);//记录树左边的
mergeSort2(nums,mid+1,right,temp);//记录树右边的
//合并两个区间
for (int i = left; i <= right; i++) {
temp[i] = nums[i];
//temp就是辅助列表,新列表的需要排序的值就是从辅助列表中拿到的
}
int i = left; //给辅助数组里面的值标点
int j = mid +1;
for (int k = left; k <= right ; k++) {//k 就为当前要插入的位置
if (i == mid + 1){//左边全满了
nums[k] = temp[j];
j++;
}else if (j == right+1){//右边全满了
nums[k] = temp[i];
i++;
}
else if (temp[i] <= temp[j]){
nums[k] = temp[i];
i++;
}else {
nums[k] = temp[j];
j++;
}
}
}
5.选择排序:
思路:依次找最小值
代码:
public static void selectSort(int[] array){
for(int i = 0;i<array.length-1;i++){
// 假定最小数
int index = i;
int min = array[i];
for(int j = i+1;j<array.length;j++){//找到最小值
if(min>array[j]){//如果假定最小值大于之后的一个数,重置最小数
min = array[j];
index = j;
}
}
if(index!=i){//判断现在交换完最后最小数是不是之前的那个最小数
array[index] = array[i];
array[i] = min;
}
}
6.快速排序
思路:
每次递归让其基准数左边全部小于基准数,其右边大于基准数。
这个博主写的快速排序通俗易懂。
https://blog.csdn.net/weixin_45970271/article/details/124460317
代码:
public static void sort(int[] arrays, int left, int right) {
if(left > right) {
return;
}
int l = left;
int r = right;
int pivot = arrays[left];
int temp = 0;
while(l < r) {
while(pivot <= arrays[r] && l < r) {
r--;
}
while(pivot >= arrays[l] && l < r) {
l++;
}
if(l <= r) {
temp = arrays[r];
arrays[r] = arrays[l];
arrays[l] = temp;
}
}
arrays[left] = arrays[l];
arrays[l] = pivot;
sort(arrays, left, l - 1);
sort(arrays, l + 1, right);
}