2021-11-11

排序算法

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);
		
	}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

灵魂的孤独

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值