算法学习笔记——排序(冒泡、选择、快速、插入、希尔、归并、基数(桶排序)) 2020/2/19-2020/2/25

一、冒泡排序

(1)代码

//冒泡排序算法,封装成一个方法
 public static void bubbleSort(int[] arr) {
  // 冒泡排序 的时间复杂度 O(n^2), 自己写出
  int temp = 0; // 临时变量
  boolean flag = false; // 标识变量,表示是否进行过交换
  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]) {
     flag = true;
     temp = arr[j];
     arr[j] = arr[j + 1];
     arr[j + 1] = temp;
    }
   }
   if (!flag) { // 在一趟排序中,一次交换都没有发生过
    break;
   } else {
    flag = false; // 重置flag!!!, 进行下次判断
   }
  }
 }
主方法调用
public static void main(String[] args) {
  int arr[] = {3, 9, -1, 10, 20};
  System.out.println("排序前");
     System.out.println(Arrays.toString(arr));
     BubbleSort(arr);
  System.out.println("排序后");
     System.out.println(Arrays.toString(arr));
 }
控制台结果

在这里插入图片描述

(2)说明

在这里插入图片描述
在这里插入图片描述

二、选择排序

(1)代码部分

封装选择排序方法

public static void selectSort(int[] arr) {
  //在推导的过程,我们发现了规律,因此,可以使用for来解决
  //选择排序时间复杂度是 O(n^2)
  for (int i = 0; i < arr.length - 1; i++) {
   int minIndex = i;
   int min = arr[i];
   for (int j = i + 1; j < arr.length; j++) {
    if (min > arr[j]) { // 说明假定的最小值,并不是最小
     min = arr[j]; // 重置min
     minIndex = j; // 重置minIndex
    }
   }
   // 将最小值,放在arr[0], 即交换
   if (minIndex != i) {
    arr[minIndex] = arr[i];
    arr[i] = min;
   }
  }

主方法调用

int [] arr = {101, 34, 119, 1, -1, 90, 123};
System.out.println("排序前");
System.out.println(Arrays.toString(arr));
selectSort(arr);
System.out.println("排序后");
System.out.println(Arrays.toString(arr));

控制台输出
在这里插入图片描述

(2)说明

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

三、快速排序

(1)代码实现

快速排序方法

public static void quickSort(int[] arr,int left, int right) {
  int l = left; //左下标
  int r = right; //右下标
  //pivot 中轴值
  int pivot = arr[(left + right) / 2];
  int temp = 0; //临时变量,作为交换时使用
  //while循环的目的是让比pivot 值小放到左边
  //比pivot 值大放到右边
  while( l < r) { 
   //在pivot的左边一直找,找到大于等于pivot值,才退出
   while( arr[l] < pivot) {
    l += 1;
   }
   //在pivot的右边一直找,找到小于等于pivot值,才退出
   while(arr[r] > pivot) {
    r -= 1;
   }
   //如果l >= r说明pivot 的左右两的值,已经按照左边全部是
   //小于等于pivot值,右边全部是大于等于pivot值
   if( l >= r) {
    break;
   }
   //交换
   temp = arr[l];
   arr[l] = arr[r];
   arr[r] = temp;
   
   //如果交换完后,发现这个arr[l] == pivot值 相等 r--, 前移
   if(arr[l] == pivot) {
    r -= 1;
   }
   //如果交换完后,发现这个arr[r] == pivot值 相等 l++, 后移
   if(arr[r] == pivot) {
    l += 1;
   }
  }
  // 如果 l == r, 必须l++, r--, 否则为出现栈溢出
  if (l == r) {
   l += 1;
   r -= 1;
  }
  //向左递归
  if(left < r) {
   quickSort(arr, left, r);
  }
  //向右递归
  if(right > l) {
   quickSort(arr, l, right);
  }

主方法调用

public static void main(String[] args) {
  
  int[] arr = {-9,78,0,23,-567,70, -1,900, 4561};
  System.out.println("排序前");
  System.out.println(Arrays.toString(arr));
  quickSort(arr, 0,arr.length-1);
  System.out.println("插入排序后");
  System.out.println(Arrays.toString(arr));
 }

控制台输出

在这里插入图片描述

(2)说明

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

四、插入排序

(1)代码实现

public static void insertSort(int[] arr) {
  int insertVal = 0;
  int insertIndex = 0;
  //使用for循环来把代码简化
  for(int i = 1; i < arr.length; i++) {
   //定义待插入的数
   insertVal = arr[i];
   insertIndex = i - 1; // 即arr[1]的前面这个数的下标
 
   // 给insertVal 找到插入的位置
   // 说明
   // 1. insertIndex >= 0 保证在给insertVal 找插入位置,不越界
   // 2. insertVal < arr[insertIndex] 待插入的数,还没有找到插入位置
   // 3. 就需要将 arr[insertIndex] 后移
   while (insertIndex >= 0 && insertVal < arr[insertIndex]) {
    arr[insertIndex + 1] = arr[insertIndex];// arr[insertIndex]
    insertIndex--;
   }
   // 当退出while循环时,说明插入的位置找到, insertIndex + 1
   //这里我们判断是否需要赋值
   if(insertIndex + 1 != i) {
    arr[insertIndex + 1] = insertVal;
   }
  }

主方法调用

public static void main(String[] args) {

  int[] arr = {101, 34, 119, 1, -1, 89}; 
  System.out.println("插入排序前");
  System.out.println(Arrays.toString(arr));
  InsertSort(arr);
  System.out.println("插入排序后");
  System.out.println(Arrays.toString(arr));
 }

控制台输出
在这里插入图片描述

(2)说明

在这里插入图片描述
在这里插入图片描述

五、希尔排序

(1)代码实现

希尔排序移位式方法

//对交换式的希尔排序进行优化->移位法
 public static void shellSort2(int[] arr) {
  // 增量gap, 并逐步的缩小增量
  for (int gap = arr.length / 2; gap > 0; gap /= 2) {
   // 从第gap个元素,逐个对其所在的组进行直接插入排序
   for (int i = gap; i < arr.length; i++) {
    int j = i;
    int temp = arr[j];
    if (arr[j] < arr[j - gap]) {
     while (j - gap >= 0 && temp < arr[j - gap]) {
      //移动
      arr[j] = arr[j-gap];
      j -= gap;
     }
     //当退出while后,就给temp找到插入的位置
     arr[j] = temp;
    }
   }
  }
 }

主方法调用

public static void main(String[] args) {
  int[] arr = {101, 34, 119, 1, -1, 89}; 
  System.out.println("插入排序前");
  System.out.println(Arrays.toString(arr));
  shellSort(arr);
  System.out.println("插入排序后");
  System.out.println(Arrays.toString(arr));
 }

控制台输出
在这里插入图片描述

(2)说明

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

六、归并排序

(1)代码实现

合并方法

//合并的方法
 /**
  * 
  * @param arr 排序的原始数组
  * @param left 左边有序序列的初始索引
  * @param mid 中间索引
  * @param right 右边索引
  * @param temp 做中转的数组
  */
 public static void merge(int[] arr, int left, int mid, int right, int[] temp) {
  
  int i = left; // 初始化i, 左边有序序列的初始索引
  int j = mid + 1; //初始化j, 右边有序序列的初始索引
  int t = 0; // 指向temp数组的当前索引
  
  //(一)
  //先把左右两边(有序)的数据按照规则填充到temp数组
  //直到左右两边的有序序列,有一边处理完毕为止 
  while (i <= mid && j <= right) {//继续
   //如果左边的有序序列的当前元素,小于等于右边有序序列的当前元素
   //即将左边的当前元素,填充到 temp数组 
   //然后 t++, i++
   if(arr[i] <= arr[j]) {
    temp[t] = arr[i];
    t += 1;
    i += 1;
   } else { //反之,将右边有序序列的当前元素,填充到temp数组
    temp[t] = arr[j];
    t += 1;
    j += 1;
   }
  }
  //(二)
  //把有剩余数据的一边的数据依次全部填充到temp
  while( i <= mid) { //左边的有序序列还有剩余的元素,就全部填充到temp
   temp[t] = arr[i];
   t += 1;
   i += 1; 
  }
  
  while( j <= right) { //右边的有序序列还有剩余的元素,就全部填充到temp
   temp[t] = arr[j];
   t += 1;
   j += 1; 
  }  
  //(三)
  //将temp数组的元素拷贝到arr
  //注意,并不是每次都拷贝所有
  t = 0;
  int tempLeft = left; // 
  //第一次合并 tempLeft = 0 , right = 1 //  tempLeft = 2  right = 3 // tL=0 ri=3
  //最后一次 tempLeft = 0  right = 7
  while(tempLeft <= right) { 
   arr[tempLeft] = temp[t];
   t += 1;
   tempLeft += 1;
  }
 }

分+合方法

//分+合方法
 public static void mergeSort(int[] arr, int left, int right, int[] temp) {
  if(left < right) {
   int mid = (left + right) / 2; //中间索引
   //向左递归进行分解
   mergeSort(arr, left, mid, temp);
   //向右递归进行分解
   mergeSort(arr, mid + 1, right, temp);
   //合并
   merge(arr, left, mid, right, temp); 
  }
 }

主方法调用

public static void main(String[] args) {
  int arr[] = { 8, 4, 5, 7, 1, 3, 6, 2 };
  int temp[] = new int[arr.length];
  System.out.println("归并排序前=" + Arrays.toString(arr));
  mergeSort(arr, 0, arr.length - 1, temp);
  System.out.println("归并排序后=" + Arrays.toString(arr));
 }

控制台输出
在这里插入图片描述

(2)说明

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

七、基数排序(桶排序)

(1)代码实现

方法

//基数排序方法
 public static void radixSort(int[] arr) {  
  //根据前面的推导过程,我们可以得到最终的基数排序代码
  //1. 得到数组中最大的数的位数
  int max = arr[0]; //假设第一数就是最大数
  for(int i = 1; i < arr.length; i++) {
   if (arr[i] > max) {
    max = arr[i];
   }
  }
  //得到最大数是几位数
  int maxLength = (max + "").length();
  //定义一个二维数组,表示10个桶, 每个桶就是一个一维数组
  //说明
  //1. 二维数组包含10个一维数组
  //2. 为了防止在放入数的时候,数据溢出,则每个一维数组(桶),大小定为arr.length
  //3. 名明确,基数排序是使用空间换时间的经典算法
  int[][] bucket = new int[10][arr.length];
  //为了记录每个桶中,实际存放了多少个数据,我们定义一个一维数组来记录各个桶的每次放入的数据个数
  //可以这里理解
  //比如:bucketElementCounts[0] , 记录的就是  bucket[0] 桶的放入数据个数
  int[] bucketElementCounts = new int[10];
  //这里我们使用循环将代码处理
  for(int i = 0 , n = 1; i < maxLength; i++, n *= 10) {
   //(针对每个元素的对应位进行排序处理), 第一次是个位,第二次是十位,第三次是百位..
   for(int j = 0; j < arr.length; j++) {
    //取出每个元素的对应位的值
    int digitOfElement = arr[j] / n % 10;
    //放入到对应的桶中
    bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j];
    bucketElementCounts[digitOfElement]++;
   }
   //按照这个桶的顺序(一维数组的下标依次取出数据,放入原来数组)
   int index = 0;
   //遍历每一桶,并将桶中是数据,放入到原数组
   for(int k = 0; k < bucketElementCounts.length; k++) {
    //如果桶中,有数据,我们才放入到原数组
    if(bucketElementCounts[k] != 0) {
     //循环该桶即第k个桶(即第k个一维数组), 放入
     for(int l = 0; l < bucketElementCounts[k]; l++) {
      //取出元素放入到arr
      arr[index++] = bucket[k][l];
     }
    }
    //第i+1轮处理后,需要将每个 bucketElementCounts[k] = 0 !!!!
    bucketElementCounts[k] = 0;
    
   }
   //System.out.println("第"+(i+1)+"轮,对个位的排序处理 arr =" + Arrays.toString(arr));
  }

主方法调用

public static void main(String[] args) {
  int arr[] = { 53, 3, 542, 748, 14, 214};
  System.out.println("基数排序前 " + Arrays.toString(arr));
  radixSort(arr);
  System.out.println("基数排序后 " + Arrays.toString(arr));
 }

控制台输出
在这里插入图片描述

(2)说明

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值