您的位置:首页 > 其它

【基础排序算法】最常见的三种排序算法(冒泡、插入、选择)

2018-04-07 22:59 609 查看
在面试过程中,笔试环节经常要求手写一种或者几种排序算法。如果你还不会写,可能就要被其他的同学给刷下去啦。希望这篇文章能帮到你。

本文实现了三种基本的排序算法:冒泡排序,插入排序,选择排序。并简单的阐述了各自的排序流程以及时间复杂度。

注:

1.本文涉及到的排序均为升序排序,若要实现逆序,将内层for循环的比较符号反过来即可。

2.交换数组中的两个值比较简单,为了提高代码可读性,这里单独写了个swap()方法。

3.为了方便查看结果以理解排序过程,写了一个简单的dispaly()方法来展示数组。

package com.cai.common.utils;

import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
* 提供几种常见的排序算法
* 注:排序方式均为升序
* Created by caidapao on 2018/4/5
* Time 12:00
*/
@Component
public class SortUtil {

public static void main(String args[]) {
int test[] = {444, 666, 333, 888, 555, 999, 777, 222};
SortUtil sortUtil = new SortUtil();
//1.选择排序
sortUtil.selectSort(test);
//2.插入排序
sortUtil.insertSort(test);
//3.冒泡排序
sortUtil.bubbleSort(test);
}

/**
* 冒泡排序
*
* 1.排序过程:
*   比较相邻两个值,若前面的大于后面的就进行交换。
*   每一趟都会将最大的“冒泡”到后面,成为已经排序好的部分
*
* 2.时间复杂度:
*   最好情况:O(n)
*   最坏情况:O(n²)  ps:数组完全逆序,故比较次数为 n+(n-1)+(n-2)+...+1 由等差数列求和公式即可推导出。
*
* @param array 数组
* @return 排序后的数组
*/
public int[] bubbleSort(int[] array) {
display("排序前:", array);
for (int j = 0; j < array.length - 1; j++) {
for (int i = 0; i < array.length - 1 - j; i++) {//注1,见下面冒泡排序过程展示
if (array[i] > array[i + 1]) {
swap(i, i + 1, array);
}
}
display("第" + (j + 1) + "趟:", array);
}
display("排序后:", array);
return array;
}

冒泡排序过程展示:

注1.内层for循环的判断条件经常会有同学错写成

i < array.length - 1  甚至是 i < array.length

前者没有搞清楚:每一趟排序过后,后面的999,888...都是已经排好的元素,已经不需要再排了,所以需要 - j来排除掉这些元素。这个问题还是比较严重的,会导致时间复杂度永远是O(n²),进行了没有意义的多余比较。

而后者相比前者,可能是没搞清楚冒泡排序是 相邻两个 比较。所以当排到倒数第二个的时候,其实已经排完了。



/**
* 插入排
943c
序
*
* 1.排序过程:
*   默认将第一个元素认为是已排序,后面的认为是待排序的。
*   始终将待排序的第一个元素(假定下标为 M),插入到已排序的合适的地方(假定下标为 K)的过程
*   将数组下表为 K到 M-1 的值都往后挪动一位 ,再将 K 的值设为 M 的值
*   重复此步骤直到 K=array.length-1
*
* 2.时间复杂度:
*   最好情况:O(n)
*   最坏情况:O(n²)
* @param array 数组
* @return 排序后的数组
*/
public int[] insertSort(int[] array) {
display("排序前:", array);
for (int j = 1; j < array.length; j++) {
for (int i = 0; i < j; i++) {
if (array[j] < array[i]) {
int k = j;
int tempValue = array[j];
while (k > i) {
array[k] = array[k - 1];
k--;
}
array[i] = tempValue;
}
}
display("第" + j + "趟:", array);
}
display("排序后:", array);
return array;
}

插入排序过程展示:






/**
* 选择排序
*
* 1.排序过程:
*   第一趟,找出最小/大的放在第一位
*   第二趟,从剩下的元素里找出最小/大的放在第二位
*   ...
*   第N趟,从剩下的元素里找出最小/大的放在第N位
*
* 2.时间复杂度:
*   最好情况:O(n²)
*   最坏情况:O(n²)
*
* @param array 数组
* @return 排序后的数组
*/
public int[] selectSort(int[] array) {
display("排序前:", array);
for (int j = 0; j < array.length - 1; j++) {
int tempMinValue = array[j];
int tempMinIndex = j;
for (int i = j + 1; i < array.length; i++) {
if (array[i] < tempMinValue) {
tempMinValue = array[i];
tempMinIndex = i;
}
}
swap(tempMinIndex, j, array);
display("第" + (j + 1) + "趟:", array);
}
display("排序后:", array);
return array;
}

选择排序过程展示:



/**
* 交换数组两个值
* @param j 第一个数下标
* @param i 第二个数下标
* @param array 数组
*/
private void swap(int j, int i, int[] array) {
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}

/**
* 交换数组两个值(不需要开辟临时空间)
* @param array 数组
* @param j 第一个数下标
* @param i 第二个数下标
*/
private void swap(int[] array, int j, int i) {
array[i] = array[j] + array[j];
array[j] = array[i] - array[j];
array[i] = array[i] - array[j];
}

/**
* 数组展示
* @param tip 提示语
* @param array 数组
*/
private void display(String tip, int[] array) {
System.out.println(tip + Arrays.toString(array));
}
}

全文完。如果你发现文中有可以改进或者错误的地方,请在下方评论中指出,非常感谢~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐