十大排序算法 java 实现(可以跑通)
网上关于十大排序算法的文章参差不齐,作者理解不同,注释不同,致使像我们这初学者理解起来不那么容易,所以我查阅了很多资料,整理以下十个排序算法的java实现。具有以下特点:
- 代码用java实现,可以跑通
- 代码加了很多注释,便于理解
- 相关的排序算法加了相关的阅读文章,便于理解。
希望能够帮助到你。
冒泡排序 插入排序 选择排序 希尔排序 快速排序 归并排序 堆排序 桶排序 计数排序 基数排序
希尔排序对应文章
快速排序
归并排序文章1
归并排序文章2
堆排序文章1
堆排序文章2
桶排序
计数排序1
计数排序2
基数排序
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* @description:用于整理排序算法
* @author: 12345ua
* @create: 2021-10-15 20:05
*/
public class SortTest {
/**
*冒泡排序
* 外循环控制总共循环的次数
* 内循环控制进行具体的操作
* @param a
* @param n
* @return
*/
public void bubbleSort(int a[],int n){
for (int i = 0; i < n-1; i++) {
for (int j = 0; j < n-i-1; j++) {
if(a[j]>a[j+1]){
int tmp=a[j];//交换
a[j]=a[j+1];
a[j+1]=tmp;
}
}
}
}
public void bubbleSort1(int a[],int n){
for (int i = n-1; i >=0; i--) {
for (int j = 0; j < i; j++) {
if(a[j]>a[j+1]){
int tmp=a[j];//交换
a[j]=a[j+1];
a[j+1]=tmp;
}
}
}
}
/**
* 选择排序
* @param arr
*/
public void selecttionSort(int arr[]){
int len=arr.length;
int minIndex=0;
for (int i = 0; i < len-1; i++) {
minIndex=i;
for (int j = i; j < len; j++) {
if(arr[j]<arr[minIndex]){
minIndex=j;
}
}
int temp=arr[i];
arr[i] = arr[minIndex];
arr[minIndex]=temp;
}
}
/**
* 先找多少趟,然后再找切入点,w往后移动
* 插入排序
* @param a
*/
public int[] InsertSort(int a[]){
for (int i = 1; i < a.length; i++) {
int temp=a[i];
int j=i-1;
for (; j >=0; j--) {
if(temp<a[j]){
a[j+1]=a[j];
}else{
break;
}
}
a[j+1]=temp;
}
return a;
}
/**
* 冒泡排序的改进
* 快速排序
* @param a
*/
public void quickSort(int[] a,int low,int high){
int p,i,j,temp;
if(low>=high){
return;
}
// p是基准数
p = a[low];
i=low;
j=high;
while(i<j){
// 右边当发现小于p的值时 停止循环
while(a[j]>=p && i<j){
j--;
}
//左边发现 大于p的值时 停止操作
while(a[i]<=p && i<j){
i++;
}
temp=a[j];
a[j]=a[i];
a[i]=temp;
}
// 基准值和第一个元素发生位置互换
a[low]=a[i];
a[i]=p;
// 对左边快排
quickSort(a,low,j-1);
// 对右边快排
quickSort(a, j + 1, high);
for (int i1 : a) {
System.out.println(i1);
}
}
/**
* 递归 自上而下创建堆
* @param array
* @param parent
* @param length
*/
public void adjustHeap1(int[] array,int parent,int length){
// 左边子节点
int left=2*parent+1;
int right=2*parent+2;
int bigger=left;// 记录节点较大的点的下标
// 选择坐标大的子节点下标
if (left < length - 1 && array[left] < array[right]) {
bigger = right;
}
if (bigger > length - 1 || array[parent] >= array[bigger]) {
return;
}else{
// 堆顶元素和左右子节点中较大的节点交换
int temp = array[parent];
array[parent] = array[bigger];
array[bigger] = temp;
adjustHeap1(array, bigger, length);
}
}
/**
*自上而下构建大顶堆,将array看成完全二叉树的顺序结构
* @param array
* @return
*/
public int[] buildMaxHeap(int[] array){
// 从最后一个节点array.length-1-1 的父节点(array.length-1)/2开始,知道根节点0,反复调整堆
for (int i = (array.length-2)/2; i >=0 ; i--) {
adjustHeap1(array,i,array.length);
}
return array;
}
/**
* 堆排序
* @param array
*/
public void heapSort(int[] array){
// 初始化堆,array[0]为第一趟值最大的元素
array = buildMaxHeap(array);
// 将堆顶元素和堆底元素交换,即得到当前最大元素正确的排序位置
for (int i = array.length-1; i >=1; i--) {
int temp = array[0];
array[0] = array[i];
array[i] = temp;
// 整理,将剩余的元素整理成大顶堆
adjustHeap1(array, 0, i);
}
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
}
/**
* 合并数组
* @param arrays 数组
* @param left 指向数组的第一个元素
* @param mid 指向数组分隔的元素
* @param right 指向数组最后的元素
*/
public void merge(int[] arrays,int left,int mid,int right){
// 左边数组的大小
int[] leftArray = new int[mid - left];
// 右边数组
int[] rightAyyay = new int[right - mid + 1];
// 往这两个数组填充数据
for (int i = left; i <mid ; i++) {
leftArray[i-left]=arrays[i];
}
for (int i = mid; i <=right ; i++) {
rightAyyay[i - mid] = arrays[i];
}
int i=0,j=0;
// arrays数组的第一个元素
int k = left;
// 比较这两个数组的值,哪个小就往哪个数组上放
while (i < leftArray.length && j < rightAyyay.length) {
// 谁比较小,谁将元素放入到大数组中,移动指针,继续比较下一个
// 等于是保证稳定
if(leftArray[i]<=rightAyyay[j]){
arrays[k] = leftArray[i];
i++;
k++;
}else{
arrays[k] = rightAyyay[j];
j++;
k++;
}
}
// 如果左边的数组上还没有比较完,右边的数组都已经完了,那么将左边的数抄到大数组中(剩下的都是大数字)
while (i < leftArray.length) {
arrays[k] = leftArray[i];
k++;
i++;
}
//如果右边的数组还没比较完,左边的数都已经完了,那么将右边的数抄到大数组中(剩下的都是大数字)
while (j < rightAyyay.length) {
arrays[k] = rightAyyay[j];
k++;
j++;
}
}
/**
* 归并排序
* @param arrays
* @param left
* @param right
*/
public void mergeSort(int[] arrays, int left, int right) {
//如果只有一个元素,那就不用排序
if (left == right) {
return;
}else{
// 取中间的数,进行拆分
int mid = (left + right) / 2;
// 左边的数不断进行拆分
mergeSort(arrays, left, mid);
// 右边的数不断碱性拆分
mergeSort(arrays, mid + 1, right);
// 合并
merge(arrays, left, mid + 1, right);
}
for (int array : arrays) {
System.out.println(array);
}
}
/**
* 希尔排序
* @param arrays
*/
public void shellSort(int[] arrays){
int length = arrays.length;
// 增量每次都是/2
for (int step=length/2; step>0; step/=2) {
//从增量那组开始插入排序,直至完毕
for (int i = step; i <length ; i++) {
// i代表即将插入的元素的角标,作为每一组比较数据的最后一个元素角标
// j代表与i同一组的数组元素角标
// 根据该比较序列的最后一个数的位置,依次向前执行插入排序
// -step代表即将插入的元素的所在角标
for (int j = i-step; j>=0 ; j=j-step) {
if(arrays[j]>arrays[j+step]){
int temp = arrays[j];
arrays[j] = arrays[j + step];
arrays[j + step] = temp;
}
}
}
}
for (int array : arrays) {
System.out.println(array);
}
}
/**
*计数排序
* @param a
*/
public void CountSort(int[] a){
int max=Integer.MIN_VALUE;
int min=Integer.MAX_VALUE;
// 找出最大值和最小值
for (int i = 0; i < a.length; i++) {
if (a[i] >max ) {
max = a[i];
}
if (a[i] < min) {
min = a[i];
}
}
int[] help = new int[max - min + 1];
// 找出每个数字出现的次数
for (int i=0;i<a.length;i++) {
int mapPos = a[i] - min;
help[mapPos]++;
}
// 计算每个数字应该在排序后数组应该处于的位置
for (int i = 1; i < help.length; i++) {
help[i] = help[i-1] + help[i];
}
//根据help数组进行排序
int[] res = new int[a.length];
for (int i = 0; i < a.length; i++) {
int post = --help[a[i] - min];
res[post] = a[i];
}
for (int i : res) {
System.out.println(i);
}
}
/**
* 桶排序
* 把数组 arr 划分为n个大小相同子区间(桶),每个子区间各自排序,最后合并
* @param a
*/
public void bucketSort(int[] a) {
int max=Integer.MIN_VALUE;
int min=Integer.MAX_VALUE;
// 找出最大值和最小值
for (int i = 0; i < a.length; i++) {
if (a[i] >max ) {
max = a[i];
}
if (a[i] < min) {
min = a[i];
}
}
// 桶数
int bucketNum = (max - min) / a.length + 1;
List<ArrayList<Integer>> bucketArr = new ArrayList<>();
for (int i = 0; i < bucketNum; i++) {
bucketArr.add(new ArrayList<Integer>());
}
// 将每个元素放入桶
for (int i = 0; i < a.length; i++) {
int num = (a[i] - min) / a.length;
bucketArr.get(num).add(a[i]);
}
// 对每个桶进行排序
for (int i = 0; i < bucketArr.size(); i++) {
Collections.sort(bucketArr.get(i));
}
System.out.println(bucketArr.toString());
}
/**
* 基数排序
* @param a
*/
public void radixSort(int[] a){
// 1.得到数组中的最大值,并获得该取值的位数,用于循环几轮
int max = Integer.MIN_VALUE;
for (int i = 0; i < a.length; i++) {
if (a[i] > max) {
max = a[i];
}
}
// 得到位数
int maxLength = (max + "").length();
// 定义桶 和桶标识元素的个数
int[][] bucket = new int[10][a.length];
int[] bucketCounts = new int[bucket.length];
//总共需要进行 maxLength 轮
for (int k = 1, n = 1; k <= maxLength; k++, n *= 10) {
// 进行桶排序
for (int i = 0; i < a.length; i++) {
// 获取该轮的桶索引,每一轮按10的倍数递增,获取对应数位数
// 这里额外使用一个步长为10的变量n来得到每次递增后的值
int bucketIndex = a[i] / n % 10;
// 放入该桶中
bucket[bucketIndex][bucketCounts[bucketIndex]] = a[i];
// 标识该桶元素多了一个
bucketCounts[bucketIndex]++;
}
// 将桶中元素获取出来,放到原数组中
int index=0;
for (int i = 0; i < bucket.length; i++) {
if (bucketCounts[i] == 0) {
// 该桶无有效元素,跳过不获取
continue;
}
// 获取桶中有效元素个数
for (int j = 0; j < bucketCounts[i]; j++) {
a[index++]=bucket[i][j];
}
// 取完后,重置该桶的元素个数为0,下一次不会错乱数据
bucketCounts[i] = 0;
}
}
for (int ai : a) {
System.out.println(ai);
}
}
public static void main(String[] args) {
int[] a={12,73,45,69,35,44};
SortTest s = new SortTest();
// s.mergeSort(a,0,a.length-1);
// s.shellSort(a);
// s.CountSort(a);
// s.bucketSort(a);
s.radixSort(a);
}