排序算法
1.冒泡排序
冒泡(Bubble Sort)排序是一种简单排序算法,它通过依次比较交换两个相邻元素实现功能。每一次冒泡会让至少一个元素移动到它应
该在的位置上,这样 n 次冒泡就完成了 n 个数据的排序工作。
这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列
的顶端(升序或降序排列),就如同碳酸饮料中二氧化碳的气泡最
终会上浮到顶端一样,故名“冒泡排序”。
package com.macro;
import java.util.Arrays;
/**
* 冒泡排序算法实现步骤:
* 1. 比较相邻的元素,如果第一个比第二个大,就交换他们两个。
* 2. 对每一对相邻元素重复上述工作,从第一对到最后一对。完成后,
* 最大的数会放到最后位置。
* 3. 针对所有的元素重复以上的步骤,除了最后一个。
* 4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数
* 字需要比较。
*
* @author macro
*
*/
public class MaoPaoSort {
public static void bubbleSort(int[] arr) {
// 判断数组是否为空,如果数组为空则没有排序的必要
if (arr.length <= 1) {
return;
}
//一共进行了length-1次循环,循环一次排好一个数
for (int i = 1; i < arr.length; i++) {
//设置标志位
boolean flag = true;
//循环一次交换一次
for (int j = 0; j < arr.length - 1; j++) {
//判断前后数据是否进行交换,如果前一个数大于后面的数则发生交换,否则不交换
if (arr[j] > arr[j+1]) {
Swap.swap(arr,j,j+1);
flag = false;
}
}
//在当前冒泡排序中如果所有元素都未进行交换,则说明排序已完成,无需进行后续循环操作
if (flag)
break;
}
System.out.println(Arrays.toString(arr));
}
public static void main(String[] args) {
int[] num = { 9, 2, 6, 1, 5, 3, 8, 7, 0, 4 };
bubbleSort(num);
}
}
2.选择排序
选择排序(Selection Sort)的原理有点类似插入排序,也分已排序区间和未排序区间。但是选择排序每次会从未排序区间中找到最小的元素,将其放到已排序区间的末尾,最终完成排序。
package com.macro;
import java.util.Arrays;
/**
* 1. 初始状态:无序区间为 Arr[0.1..n],有序区间为空;
* 2. 第i==1趟排序开始,从无序区中选出最小的元素Arr[k],将它与无序
* 区的第1个元素交换,从而得到有序区间Arr[0..i-1],无序区间Arr[i..n];
* 3.继续后面第i趟排序(i=2,3…n-1),重复上面第二步过程; 4. 第n-1趟排序结束,数组排序完成。
*
*
* @author macro
*
*/
public class XuanZeSort {
public static void xuanZeSort(int[] arr) {
//判断数组长度是否>1
if(arr.length<=1)
return;
//每一次循环排好有序区中的一个数
for(int i = 0;i<arr.length-1;i++) {
int min = i;
//每次循环找到无序区中最小的一个数,并将它放在有序区
for(int j = i+1;j<arr.length;j++) {
//查找最小值
if(arr[min]>arr[j])
min = j;
}
//如果最小值发生改变则交换位置
if(min!=i)
Swap.swap(arr, i, min);
}
System.out.println(Arrays.toString(arr));
}
public static void main(String[] args) {
int[] num = { 9, 2, 6, 1, 5, 3, 8, 7, 0, 4 };
xuanZeSort(num);
}
}
3.插入排序
插入排序(Insertion Sort),一般也被称为直接插入排序。对于少量元素的排序,它是一个有效的算法。
package com.macro;
import java.util.Arrays;
/**
* 插入排序算法描述: 1. 将数组分成两部分,已排序、未排序区间,初始情况下,已排序区 间只有一个元素,即数组第一个元素;
* 2.取未排序区间中第一个元素,插入到已排序区间中合适的位置,这样子就得到了一个更大的已排序区间; 3. 重复这个过程,直到未排序区间中元素为空,算法结束。
*
* @author macro
*
*/
public class ChaRuSort {
public static void chaRuSort(int[] arr) {
if (arr.length <= 1)
return;
// 外层循环控制 总体循环次数
for (int i = 1; i < arr.length; i++) {
// 内层循环做的事情:将无序列表中第一个元素插入到有序列表中合适位置
int value = arr[i];
// 获取有序列表中最后一个元素下标
int j = i - 1;
for ( ;j >= 0; j--) {
if (value < arr[j]) {
arr[j + 1] = arr[j];
} else {
break;
}
}
arr[j+1] = value;
System.out.println(Arrays.toString(arr));
}
}
public static void main(String[] args) {
int[] num = { 9, 2, 6, 1, 5, 3, 8, 7, 0, 4 };
chaRuSort(num);
}
}
package Homework.Teacher2.ChuanJiangday02;
import java.util.Arrays;
/**
* 从小到大
* 插入排序
* 思想:首先分为有序区和无序区,一般把第一个或者最后一个认为是有序区,
* 用无序区中的一个数和有序区中的数逐个比较,找到合适的位置插入
*
* @author asus
*
*/
public class ChaRuSort {
public static void main(String[] args) {
int[] s = { 9, 2, 6, 1, 5, 3, 8, 7, 0, 4 };// 0~9
// 记录拿出的数
int oldnumber = 0;
// 记录插入的位置
int newIndex = 0;
//外循环,每次循环排好一个数
for (int i = 1; i < s.length; i++) {
//先将要插入的数拿出来
oldnumber = s[i];
//进行内循环,每次循环找到要插入的位置。
for (int j = i - 1; j >= 0; j--) {
//判断要比较的值是否大于它
if (s[j] > oldnumber) {
//如果大于,它的位置往后移一位
s[j + 1] = s[j];
//记录他要插入的位置
newIndex = j;
//如果小于,则停止循环说明该位置就是它的最终位置
}else {
break;
}
//在最终位置中插入取出的数
s[newIndex] = oldnumber;
}
}
System.out.println(Arrays.toString(s));
}
}
4.希尔排序
希尔(shell)排序是Donald Shell于1959年提出的一种排序算法。
希尔排序也是一种插入排序,它是简单插入排序经过改进之后的一个更
高效的版本,也称为缩小增量排序,同时该算法是冲破O(n2)的第
一批算法之一。
package com.macro;
import java.util.Arrays;
/**
* 1. 将有n个元素的数组分成n/2个数字序列,第i个元素和第i+n/2, i+n/2*m...个元素为一组;
* 2. 对一组数列进行简单插入排序;
* 3.然后,调整增量为n/4,从而得到新的几组数列,再次排序;
* 4. 不断重复上述过程,直到增量为1,shell排序完全转化成简单插入
* 排序,完成该趟排序,则数组排序成功。
*
* @author macro
*
*/
public class ShellSort {
public static void shellSort(int[] arr) {
//判断数组长度
int len = arr.length;
if(len<=1) {
return;
}
//设置初始增量
int gap = len/2;
//由增量控制整体排序次数
while(gap>0) {
//记录拿出来的值
int oldnum = 0;
//记录要插入的位置
int newindex = 0;
//插入排序改造
for(int i = gap;i<len;i++) {
//先将要插入的数拿出来
oldnum = arr[i];
//进行内循环,每次循环找到要插入的位置。
for(int j = i-gap;j>=0;j-=gap) {
//如果大于,它的位置往后移一位
if(arr[j]>oldnum) {
arr[j + gap] = arr[j];
newindex = j;
}else {
break;
}
arr[newindex] = oldnum;
}
}
gap /= 2;
System.out.println(Arrays.toString(arr));
}
}
public static void main(String[] args) {
int[] num = { 9, 2, 6, 1, 5, 3, 8, 7, 0, 4 };
shellSort(num);
//[3, 2, 6, 0, 4, 9, 8, 7, 1, 5]
//[1, 0, 3, 2, 4, 5, 6, 7, 8, 9]
//[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
}
}
5.归并排序
归并排序(Merge Sort)算法,使用的是分治思想。分治,顾名思义,
就是分而治之,将一个大问题分解成小的子问题来解决。小的子问
题解决了,大问题也就解决了。
核心源码: mergeSort(m->n) = merge(mergeSort(m->k),mergeSort(k+1->n));
package com.macro;
import java.util.Arrays;
/**
* 如果要排序一个数组,先把数组从中间分成前后两部分,
* 然后对前后两部分分别排序,再将排好序的两部分合并在一起,
* 这样整个数组就都有序了。
*
* @author macro
*
*/
public class GuiBingSort {
public static int[] guiBingSort(int[] arr) {
int len = arr.length;
//确定递归终止条件
if (len < 2)
return arr;
int mid = len / 2;
//拆分数组成左右两个部分
int[] left = Arrays.copyOfRange(arr, 0, mid);
int[] right = Arrays.copyOfRange(arr, mid,arr.length);
//对拆解后的两个数组进行合并
return merge(guiBingSort(left),guiBingSort(right));
}
/**
* 合并两个有序数组,并返回合并后的新数组
* @param left
* @param right
*/
private static int[] merge(int[] left, int[] right) {
//定义好一个新数组
int[] newarr = new int[left.length+right.length];
//往新数组中逐个添加元素
int lIndex = 0;
int rIndex = 0;
for(int i = 0;i<newarr.length;i++) {
if(lIndex>=left.length) {
//左数组遍历完成
newarr[i] = right[rIndex++];
}else if(rIndex>=right.length) {
//右数组遍历完成
newarr[i] = left[lIndex++];
}else if(left[lIndex]<right[rIndex]) {
//左数组当前元素值小于右数组
newarr[i] = left[lIndex++];
}else{
//右数组当前元素值小于左数组
newarr[i] = right[rIndex++];
}
}
return newarr;
}
public static void main(String[] args) {
int[] num = { 9, 2, 6, 1, 5, 3, 8, 7, 0, 4 };
num = guiBingSort(num);
System.out.println(Arrays.toString(num));
}
}
7.桶排序
桶排序(Bucket Sort),顾名思义,会用到“桶”,我们可以认为"桶"就
是一个容器。核心思想是将要排序的数据分到几个桶里,然后对每
个桶里的数据进行排序,最后遍历所有桶中数据即可。
package com.macro;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* 1. 设置固定空桶数
* 2. 将数据放到对应的空桶中
* 3. 将每个不为空的桶进行排序
* 4. 拼接不为空的桶中的数据,得到结果F
*
* @author macro
*
*/
public class TongSort {
/**
*
* @return
*/
public static List<Integer> bucketSort(List<Integer> arr, int bucketSize) {
// 递归算法终止条件,合法性校验
if (arr == null || arr.size() < 2 || bucketSize < 1) {
return arr;
}
// 确定桶的个数
// 找出我们集合中元素的最大值的最小值
int max = arr.get(0);
int min = arr.get(0);
for (int i = 0; i < arr.size(); i++) {
if (arr.get(i) > max) {
max = arr.get(i);
}
if (arr.get(i) < min) {
min = arr.get(i);
}
}
// 计算桶的个数
int bucketCount = (max - min) / bucketSize + 1;
// 将数据分别放到对应的空桶(List)中
ArrayList<List<Integer>> bucketList = new ArrayList<>();
for (int i = 0; i < bucketCount; i++) {
bucketList.add(new ArrayList<Integer>());
}
// b.将待排序的数据添加到对应的桶中
for (int i = 0; i < arr.size(); i++) {
// 找到该数据应该放置的桶
int bucketIndex = (arr.get(i) - min) / bucketSize;
// 将该数据 放入对应桶中
bucketList.get(bucketIndex).add(arr.get(i));
}
// 4.桶内元素的排序
List<Integer> reustList = new ArrayList<>();
// a.遍历所有桶,逐个进行排序
for (int i = 0; i < bucketList.size(); i++) {
List<Integer> everyBucket = bucketList.get(i);
/* 此处为核心代码,不容易理解,可画图分析 */
if (everyBucket.size() > 0) {
// 桶个数为1,则桶容量减1
if (bucketCount == 1) {
bucketSize--;
}
// b.对子桶进行排序(递归实现 桶排序)
List<Integer> temp = bucketSort(everyBucket, bucketSize);
// c.将排好序的
for (int j = 0; j < temp.size(); j++) {
reustList.add(temp.get(j));
}
}
}
return reustList;
}
public static void main(String[] args) {
//int[] num = { 9, 2, 6, 1, 5, 3, 8, 7, 0, 4 };
Integer[] array = {9, 2, 6, 1, 5, 3, 8, 7, 0, 4};
List<Integer> list = Arrays.asList(array);
List<Integer> sort = bucketSort(list,3);
System.out.println(sort);
}
}