06-冒泡排序,选择排序,插入排序基本思路及代码实现
作者:互联网
6.3 冒泡排序
6.3.1基本思想
基本思想:给定待排序的一组数,从下标小的元素开始,依次和后一个相邻元素比较,满足条件则交换,使得较大的元素逐渐向后移动,就像水底的气泡一样逐渐上浮
6.3.2流程分析
通过上图的流程分析,可以发现:
- 对于给定长度为n的待排序数组,需要进行n-1次外层循环,进行趟数的比较
- 在内层循环中,每一趟的比较次数在逐次减少
- 如果在其中某一趟中,没有发生比较和交换,则说明数组已经是有序的状态,可以提前退出
6.3.3代码实现
代码中分为对冒泡排序的逐层解析,冒泡排序以及其优化三部分
package com.kevin.sortAlgorithm;
import java.util.Arrays;
/**
* @author : kevin ding
* @date : 2022/2/28 21:07
* @description : 冒泡排序:基本思想是通过对 待排序的一组数,从下标小的元素开始,依次和后一个相邻元素比较,满足条件则交换,使得较大的元素逐渐向后移动,就像水底的气泡一样逐渐上浮
*/
public class BubbleSortDemo {
public static void main(String[] args) {
// int[] array = {32, 11, 46, 23, 2};
// int[] array = {2, 11, 14, 29, 23};
// System.out.println("排序之前,结果为:");
// System.out.println(Arrays.toString(array));
// sortAnalysis(array);
// bubbleSort(array);
int[] array = new int[80000];
for (int i = 0; i < array.length; i++) {
array[i] = (int) (Math.random() * 8000000);
}
Long startTime = System.currentTimeMillis();
bubbleSortOptimize(array);
Long endTime = System.currentTimeMillis();
System.out.println("冒泡排序 所耗费的时间是:" + (endTime-startTime) + "ms"); // 6621ms
}
public static void sortAnalysis(int[] array){
// 定义临时变量,用于两数之间的交换
int temp = 0;
// 第一趟排序 总共进行了array.length-1次循环比较
for(int j = 0; j < array.length - 1; j++){
// 如果当前值大于其下一个,两者交换
if(array[j] > array[j+1]){
temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
}
System.out.println("第 1 趟排序之后,结果为:");
System.out.println(Arrays.toString(array));
// 第 2趟排序 总共进行了array.length-1-1次循环比较
for(int j = 0; j < array.length - 1 - 1; j++){
// 如果当前值大于其下一个,两者交换
if(array[j] > array[j+1]){
temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
}
System.out.println("第 2 趟排序之后,结果为:");
System.out.println(Arrays.toString(array));
// 第 3 趟排序 总共进行了array.length-1-2次循环比较
for(int j = 0; j < array.length - 1 - 2; j++){
// 如果当前值大于其下一个,两者交换
if(array[j] > array[j+1]){
temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
}
System.out.println("第 3 趟排序之后,结果为:");
System.out.println(Arrays.toString(array));
// 第 4 趟排序 总共进行了array.length-1-3 次循环比较
for(int j = 0; j < array.length - 1 - 3; j++){
// 如果当前值大于其下一个,两者交换
if(array[j] > array[j+1]){
temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
}
System.out.println("第 4 趟排序之后,结果为:");
System.out.println(Arrays.toString(array));
}
public static void bubbleSort(int[] array){
// 通过对sortAnalysis的分析,发现规律,每趟的排序,只需要改动for循环中的上界 ,并且上界值在逐渐减小,其他代码全部进行复用,用循环来代替:
// 发现总共循环的趟数是array.length-1次,每趟中比较的次数少一次
int temp = 0; // 用于交换的临时变量
for(int i = 0; i < array.length-1; i++){
for (int j = 0; j < array.length-1-i; j++) {
if(array[j] > array[j+1]){
temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
}
System.out.println("第 " + (i+1) +" 趟排序之后,结果为:");
System.out.println(Arrays.toString(array));
}
}
/**
* @description 对bubbleSort方法的优化
* @param array
*/
public static void bubbleSortOptimize(int[] array){
// 通过分析发现,若在其中某一趟循环的时候,数组已经处于有序状态,则无需进行接下来的几趟循环,可以直接退出
int temp; // 用于进行数据交换的临时变量
boolean flag; // 用于进行判断是否需要接着循环的标记
for(int i = 0; i < array.length-1; i++){
// 在每一轮循环开始之前,需要将标记位置为false
flag = false;
for (int j = 0; j < array.length-1-i; j++) {
if(array[j] > array[j+1]){
// 如果进行了循环,就将标记置为true
flag = true;
temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
}
// 每趟循环结束之后,判断标记位的值
if(!flag){
// 表示没有进去进行交换,即已经处于由于状态,可直接退出
break;
}
}
}
}
6.3.4 冒泡排序的最终版代码:
/**
* @description bubbleSort方法的最终版本
* @param array
*/
public static void bubbleSort(int[] array){
// 通过分析发现,若在其中某一趟循环的时候,数组已经处于有序状态,则无需进行接下来的几趟循环,可以直接退出
int temp; // 用于进行数据交换的临时变量
boolean flag; // 用于进行判断是否需要接着循环的标记
for(int i = 0; i < array.length-1; i++){
// 在每一轮循环开始之前,需要将标记位置为false
flag = false;
for (int j = 0; j < array.length-1-i; j++) {
if(array[j] > array[j+1]){
// 如果进行了循环,就将标记置为true
flag = true;
temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
}
// 每趟循环结束之后,判断标记位的值
if(!flag){
// 表示没有进去进行交换,即已经处于由于状态,可直接退出
break;
}
}
}
6.4 选择排序
6.4.1 选择排序的思想:
第一次从array[0]
-arr[n-1]
中选取最小值,与array[0]
交换,第二次从array[1]
– array[n-1]
中选取最小值,array[1]
交换,第三次从array[2]
– array[n-1]
中选取最小值,与arr[2]交换,…, 第n-1次从array[n-2]
–array[n-1]
中选取最小值,与array[n-2]交换,总共通过n-1次,得到一个按排序码从小到大排列的有序序列。
选择排序的图解:
6.4.2 代码实现:
代码中分为对选择排序的逐层解析,选择排序以及其优化三部分
package com.kevin.sortAlgorithm;
import sun.security.util.AuthResources_it;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
/**
* @author : kevin ding
* @date : 2022/3/1 21:44
* @description : 选择排序思想:第1次,array[0] - array[n-1]的所有数中,默认最小值为array[0], 从array[0+1] - arr[n-1]中找到最小值,与array[0]进行交换,使得0索引位置为最小值;
* 第2次,array[1] - array[n-1]的所有数中,默认最小值为array[1], 从array[1+1] - arr[n-1]中找到最小值,与array[1]进行交换,使得1索引位置为最小值;
* 第3次,array[2] - array[n-1]的所有数中,默认最小值为array[2], 从array[2+1] - arr[n-1]中找到最小值,与array[2]进行交换,使得2索引位置为最小值;
* ... 一直到第 n-1 次
*/
public class SelectSortDemo {
public static void main(String[] args) {
// int[] array = {32, 11, 46, 23, 2};
// System.out.println("排序之前,结果为:");
// System.out.println(Arrays.toString(array));
// 对于 100000个数据进行排序,求其时间
int[] array = new int[80000];
for (int i = 0; i < array.length; i++) {
array[i] = (int) (Math.random() * 8000000);
}
Long startTime = System.currentTimeMillis();
selectSort(array);
Long endTime = System.currentTimeMillis();
System.out.println("选择排序所耗费的时间是:" + (endTime-startTime) + "ms"); // 1539
}
public static void selectSortAnalysis(int[] array){
// 定义辅助变量 temp用于进行交换,minIndex存放最小值对应的索引下标
int temp;
int minIndex;
// 第1次:每次循环只需要改变minIndex的初始值,及for循环的起始值即可
minIndex = 0;
for(int j = 0+1; j<array.length; j++){
// 如果当前位置的值小于minValue,更换最小值及最小值的索引
if(array[minIndex] > array[j]){
minIndex = j;
}
}
// 循环结束之后,找到了当前的最小值,与array[0]进行交换
temp = array[minIndex];
array[minIndex] = array[0];
array[0] = temp;
System.out.println("第 1 趟选择之后,结果为:");
System.out.println(Arrays.toString(array));
// 第2次:每次循环只需要改变minIndex的初始值,及for循环的起始值即可
minIndex = 1;
for(int j = 1+1; j<array.length; j++){
// 如果当前位置的值小于minValue,更换最小值及最小值的索引
if(array[minIndex] > array[j]){
minIndex = j;
}
}
// 循环结束之后,找到了当前的最小值,与array[0]进行交换
temp = array[minIndex];
array[minIndex] = array[1];
array[1] = temp;
System.out.println("第 2 趟选择之后,结果为:");
System.out.println(Arrays.toString(array));
// 第3次:每次循环只需要改变minIndex的初始值,及for循环的起始值即可
minIndex = 2;
for(int j = 2+1; j<array.length; j++){
// 如果当前位置的值小于minValue,更换最小值及最小值的索引
if(array[minIndex] > array[j]){
minIndex = j;
}
}
// 循环结束之后,找到了当前的最小值,与array[0]进行交换
temp = array[minIndex];
array[minIndex] = array[2];
array[2] = temp;
System.out.println("第 3 趟选择之后,结果为:");
System.out.println(Arrays.toString(array));
// 第4次: 每次循环只需要改变minIndex的初始值,及for循环的起始值即可
minIndex = 3;
for(int j = 3+1; j<array.length; j++){
// 如果当前位置的值小于minValue,更换最小值及最小值的索引
if(array[minIndex] > array[j]){
minIndex = j;
}
}
// 循环结束之后,找到了当前的最小值,与array[0]进行交换
temp = array[minIndex];
array[minIndex] = array[3];
array[3] = temp;
System.out.println("第 4 趟选择之后,结果为:");
System.out.println(Arrays.toString(array));
}
public static void selectSort(int[] array){
// 通过对selectSortAnalysis代码分析发现,对于一个长度为n的数组,需要循环n-1次,每次循环时从未排序的序列中找最小值,
// 查找范围在逐渐缩小,下界在发生变化,上界一直为数组的最后一个元素,且每次默认的最小值索引逐次递增
int temp;
int minIndex;
for (int i = 0; i < array.length-1; i++) {
minIndex = i;
for (int j = i+1; j <array.length ; j++) {
// 如果当前位置的值小于minValue,更换最小值及最小值的索引
if(array[minIndex] > array[j]){
minIndex = j;
}
}
// 每次遍历结束之后,将和当前第i个元素进行交换,使得最小值始终 位于第一个
temp = array[minIndex];
array[minIndex] = array[i];
array[i] = temp;
// System.out.println("第 "+ (i+1)+" 趟选择之后,结果为:");
// System.out.println(Arrays.toString(array));
}
}
public static void selectSortOptimize(int[] array){
// 对选择排序进行分析,每次遍历结束找到最小值的索引之后进行交换,如果当前i即为最小值索引,则交换没有意义,可进行优化
int temp;
int minIndex;
for (int i = 0; i < array.length-1; i++) {
minIndex = i;
for (int j = i+1; j <array.length ; j++) {
// 如果当前位置的值小于minValue,更换最小值及最小值的索引
if(array[minIndex] > array[j]){
minIndex = j;
}
}
// 每次遍历结束之后,将和当前第i个元素进行交换,使得最小值始终 位于第一个
// 当i和minIndex不相等的时候, 才进行交换
if(i != minIndex){
temp = array[minIndex];
array[minIndex] = array[i];
array[i] = temp;
}
System.out.println("第 "+ (i+1)+" 趟选择之后,结果为:");
System.out.println(Arrays.toString(array));
}
}
}
6.4.3 最终选择排序代码
public static void selectSort(int[] array){
// 对选择排序进行分析,每次遍历结束找到最小值的索引之后进行交换,如果当前i即为最小值索引,则交换没有意义,可进行优化
int temp;
int minIndex;
for (int i = 0; i < array.length-1; i++) {
minIndex = i;
for (int j = i+1; j <array.length ; j++) {
// 如果当前位置的值小于minValue,更换最小值及最小值的索引
if(array[minIndex] > array[j]){
minIndex = j;
}
}
// 每次遍历结束之后,将和当前第i个元素进行交换,使得最小值始终 位于第一个
// 当i和minIndex不相等的时候, 才进行交换
if(i != minIndex){
temp = array[minIndex];
array[minIndex] = array[i];
array[i] = temp;
}
System.out.println("第 "+ (i+1)+" 趟选择之后,结果为:");
System.out.println(Arrays.toString(array));
}
}
6.5 插入排序
6.5.1介绍
对于欲排序的元素以插入的方式找寻该元素的适当位置,以达到排序的目的。
6.5.2 思想
把一组待排序的元素看成为一个有序表和一个无序表,开始时有序表中只包含一个元素(最左边元素),无序表中包含有n-1个元素(后面n-1个元素),排序过程中每次从无序表中取出第一个元素,把它的排序码依次与有序表元素的排序码进行比较,将它插入到有序表中的适当位置,使之成为新的有序表。
插入排序图解:
6.5.3 代码实现:
包括对插入排序的逐层分析,以及实现
package com.kevin.sortAlgorithm;
import com.kevin.arrayStack.ArrayStack;
import java.sql.Array;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
/**
* @author : kevin ding
* @date : 2022/3/1 22:16
* @description : 插入排序 思想:对于一组待排序的数据,看成是一个有序列表和无序列表,初始时,有序列表只包含一个元素,无需列表包含n-1个元素,从array[1] ~ array[n-1],
* 分别将其下标与前面有序元素进行比较,找到适当的位置,并插入到该位置,以达到排序的目的;
* 每次对于待排序的元素,其左半部分已经是有序状态,右半部分是待排序的元素
*/
public class InsertSortDemo {
public static void main(String[] args) {
// int[] array = {32, 11, 46, 23, 2};
// System.out.println("排序之前,结果为:");
// System.out.println(Arrays.toString(array));
//
// // insertSortAnalysis(array);
//
// insertSort(array);
// 对于 100000个数据进行排序,求其时间
int[] array = new int[80000];
for (int i = 0; i < array.length; i++) {
array[i] = (int) (Math.random() * 8000000);
}
Long startTime = System.currentTimeMillis();
insertSort(array);
Long endTime = System.currentTimeMillis();
System.out.println("插入排序 所耗费的时间是:" + (endTime-startTime) + "ms"); // 395ms
}
public static void insertSortAnalysis(int[] array){
// 定义变量 insertValue为当前带插入的元素,insertIndex为带插入元素的位置
int insertValue;
int insertIndex;
// 第一次排序: 选择array[1]为待排数,
insertValue = array[1];
insertIndex = 1;
// 给待排元素insertValue往前找到合适的位置
while(insertIndex > 0 && insertValue < array[insertIndex-1] ){
// 带插入元素小于前一个,且不能越界
array[insertIndex] = array[insertIndex-1];
insertIndex -= 1;
}
// 当退出循环的时候,要么inserIndex已经到了第一个位置,要么已经在合适的位置,insertIndex即为合适的插入位置
array[insertIndex] = insertValue;
System.out.println("第一轮插入之后:");
System.out.println(Arrays.toString(array));
// 第2次排序: 选择array[1]为待排数,
insertValue = array[2];
insertIndex = 2;
// 给待排元素insertValue往前找到合适的位置
while(insertIndex > 0 && insertValue < array[insertIndex-1] ){
// 带插入元素小于前一个,且不能越界
array[insertIndex] = array[insertIndex-1];
insertIndex -= 1;
}
// 当退出循环的时候,找到了正确的位置
array[insertIndex] = insertValue;
System.out.println("第2轮插入之后:");
System.out.println(Arrays.toString(array));
// 第3次排序: 选择array[1]为待排数,
insertValue = array[3];
insertIndex = 3;
// 给待排元素insertValue往前找到合适的位置
while(insertIndex > 0 && insertValue < array[insertIndex-1] ){
// 带插入元素小于前一个,且不能越界
array[insertIndex] = array[insertIndex-1];
insertIndex -= 1;
}
// 当退出循环的时候,找到了正确的位置
array[insertIndex] = insertValue;
System.out.println("第3轮插入之后:");
System.out.println(Arrays.toString(array));
// 第4次排序: 选择array[1]为待排数,
insertValue = array[4];
insertIndex = 4;
// 给待排元素insertValue往前找到合适的位置
while(insertIndex > 0 && insertValue < array[insertIndex-1] ){
// 带插入元素小于前一个,且不能越界
array[insertIndex] = array[insertIndex-1];
insertIndex -= 1;
}
// 当退出循环的时候,找到了正确的位置
array[insertIndex] = insertValue;
System.out.println("第4轮插入之后:");
System.out.println(Arrays.toString(array));
}
public static void insertSort(int[] array){
// 通过对上面的逐步分析,可以将外层通过循环来进行控制每一轮的选择:
int insertValue;
int insertIndex;
// 从1开始到n-1
for (int i = 1; i < array.length; i++) {
insertValue = array[i];
insertIndex = i;
// 给待排元素insertValue往前找到合适的位置
while(insertIndex > 0 && insertValue < array[insertIndex-1] ){
// 带插入元素小于前一个,且不能越界
array[insertIndex] = array[insertIndex-1];
insertIndex -= 1;
}
// 当退出循环的时候,找到了正确的位置
array[insertIndex] = insertValue;
}
}
}
6.5.4 最终版插入排序代码
public static void insertSort(int[] array){
// 通过对上面的逐步分析,可以将外层通过循环来进行控制每一轮的选择:
int insertValue;
int insertIndex;
// 从1开始到n-1
for (int i = 1; i < array.length; i++) {
insertValue = array[i];
insertIndex = i;
// 给待排元素insertValue往前找到合适的位置
while(insertIndex > 0 && insertValue < array[insertIndex-1] ){
// 带插入元素小于前一个,且不能越界
array[insertIndex] = array[insertIndex-1];
insertIndex -= 1;
}
// 当退出循环的时候,找到了正确的位置
array[insertIndex] = insertValue;
}
}
标签:minIndex,insertIndex,06,int,插入排序,System,冒泡排序,println,array 来源: https://blog.csdn.net/weixin_43155804/article/details/123218201