Java--排序算法

Java–排序算法

(1)计数排序

用额外数组存储各个待排序列数出现的次数

在这里插入图片描述

import java.util.Scanner;
public class Main 
{
	public static void main(String[] args) 
    {
		Scanner sca = new Scanner(System.in);
		int n = sca.nextInt();//输入n个整数
		int [] arr = new int [n];
		arr[0] = sca.nextInt();
		int max = arr[0];
		for (int i = 1; i < n; i++)
		{
			arr[i] = sca.nextInt();//把输入的数依次输入到数组中
			if (max < arr[i])//找出最大数
			{
				max = arr[i];
			}
		}
		int [] book = new int [max + 1];//开max+1的额外数组
		for (int i = 0; i < n; i++)//标记出现次数
		{
			book[arr[i]]++;
		}
		for (int i = 0; i <= max; i++)//循环book数组
		{
			for (int j = 1; j <= book[i]; j++)
			{
				System.out.print(i);
			}
		}
		sca.close();
	}
}
排序算法平均时间复杂度最好情况最坏情况空间复杂度稳定性
计数排序O(n + k)O(n + k)O(n + k)O(k)稳定

PS: k为桶的个数

​ 需要额外数组空间,利用空间换时间


(2)基数排序

第一趟依次根据待排序数的个位数排序,第二趟依次根据待排序数的十位数排序,……

在这里插入图片描述

import java.util.Arrays;
import java.util.Scanner;
public class Main
{
	public static void main(String[] args)
    {
		Scanner sca = new Scanner(System.in);
		int n = sca.nextInt();//n个待排序数
		int [] arr = new int [n];
		for (int i = 0; i < n; i++)//随机生成1000以内n个数
		{
			arr[i] = (int)(Math.random() * 1000);
		}
		radixSort(arr);//基数排序
		System.out.println(Arrays.toString(arr));//输出
		sca.close();
	}
	/**
	 * 基数排序
	 * @param arr 待排序数组
	 */
	public static void radixSort(int [] arr)
	{
		int len = arr.length;//待排序数组长度
		int [][] book = new int [10][len];//开十个桶,每个桶最大容量是待排序数组的容量
		int [] index = new int [10];//桶的索引
		int max = arr[0];       
		for (int i = 1; i < len; i++)//求出最大值
		{
			if (max < arr[i])
			{
				max = arr[i];
			}
		}
		int maxSize = (max + "").length();//根据最大值得到要循环到几位数
		for (int i = 0, m = 1; i < maxSize; i++, m *= 10)
		{
			for (int j = 0; j < len; j++)//利用桶排序,看图解
			{
				int t = arr[j] / m % 10;
				book[t][index[t]] = arr[j];
				index[t]++;
			}
			int arr_index = 0;
			for (int j = 0; j < 10; j++)//更新arr数组
			{
				for (int k = 0; k < index[j]; k++)
				{
					arr[arr_index] = book[j][k];
					arr_index++;
				}
				index[j] = 0;
			}
		}
	}
}
排序算法平均时间复杂度最好情况最坏情况空间复杂度稳定性
基数排序O(n * k)O(n * k)O(n * k)O(n + k)稳定

PS: k为桶的个数

​ 需要额外数组空间,利用空间换时间


(3)冒泡排序

n - 1趟循环相邻两两比较交换,第 i 趟实现第 i(或 n - i + 1)位数完成排序

在这里插入图片描述

import java.util.Arrays;
import java.util.Scanner;
public class Main 
{
	public static void main(String[] args) 
    {
		Scanner sca = new Scanner(System.in);
		int n = sca.nextInt();//n个待排序数
		int [] arr = new int [n];
		for (int i = 0; i < n; i++)//随机生成1000以内n个数
		{
			arr[i] = (int)(Math.random() * 1000);
		}
		bubbleSort(arr, n);//冒泡排序
		System.out.println(Arrays.toString(arr));//输出
		sca.close();
	}
	/**
	 * 冒泡排序
	 * @param arr 待排序数组
	 * @param n 待排序数组长度
	 */
	public static void bubbleSort(int [] arr, int n)
	{
		boolean flag = false;//优化
		for (int i = 0; i < n - 1; i++)//走n - 1趟即可
		{
			for (int j = 0; j < n - i - 1; j++)
			{
				if (arr[j] > arr[j + 1])//两两比较交换
				{
					flag = true;//说明该趟排序有交换
					int temp = arr[j + 1];
					arr[j + 1] = arr[j];
					arr[j] = temp;
				}
			}
			if (!flag)//如果某趟排序没有交换说明数组已经排好序
			{
				return;
			}
			else
			{
				flag = false;//重置
			}
		}
	}
}
排序算法平均时间复杂度最好情况最坏情况空间复杂度稳定性
冒泡排序O(n^2)O(n)O(n^2)O(1)稳定

PS: 待排序列越趋向有序,冒泡排序的时间复杂度越接近O(n)


(4)快速排序

找一个基准(随意一个数),把大于基准的数放在基准的右边,把小于基准的数放在小于基准的左边,基准的左边以此类推,基准的右边也以此类推

在这里插入图片描述

import java.util.Arrays;
import java.util.Scanner;
public class Main
{
	public static void main(String[] args)
    {
		Scanner sca = new Scanner(System.in);
		int n = sca.nextInt();
		int [] arr = new int [n];
		for (int i = 0; i < n; i++)//随机生成10以内n个数
		{
			arr[i] = (int)(Math.random() * 10);
		}
		quickSort(arr, 0, n - 1);//快排
		System.out.println(Arrays.toString(arr));//输出
		sca.close();
	}
	/**
	 * 快速排序
	 * @param arr 待排序数组
	 * @param left 数组最左边
	 * @param right 数组最右边
	 */
	public static void quickSort(int [] arr, int left, int right)
	{
		int mid = arr[(left + right) / 2];//找中间数作为基准
		int l = left;
		int r = right;
		while (l < r)//l >= r时跳出循环
		{
			while (arr[l] < mid)//直到找到大于等于基准的数
			{
				l++;
			}
			while (arr[r] > mid)//直到找到小于等于基准的数
			{
				r--;
			}
			if (l >= r)//l >= r时跳出循环
			{
				break;
			}
			int temp = arr[l];//交换
			arr[l] = arr[r];
			arr[r] = temp;
			if (arr[l] == arr[r])//当遇到arr[l] = arr[r] = 基准数时会陷入循环
			{
				l++;//l++或者r--都可
			}
		}
		if (left < r - 1)//左边递归
		{
			quickSort(arr, left, r - 1);
		}
		if (l + 1 < right)//右边递归
		{
			quickSort(arr, l + 1, right);
		}
	}
}
排序算法平均时间复杂度最好情况最坏情况空间复杂度稳定性
快速排序O(n log n)O(n log n)O(n^2)O(log n)不稳定

PS:空间主要是递归时消耗


(5)选择排序

在arr[0]arr[n]寻找最小值与arr[0]交换,在arr[1]arr[n]寻找最小值与arr[1]交换,……

在这里插入图片描述

import java.util.Arrays;
import java.util.Scanner;
public class Main
{
	public static void main(String[] args)
    {
		Scanner sca = new Scanner(System.in);
		int n = sca.nextInt();//n个数
		int [] arr = new int [n];
		for (int i = 0; i < n; i++)//随机生成1000以内n个数
		{
			arr[i] = (int)(Math.random() * 1000);
		}
		selectSort(arr, n);//调用选择排序
		System.out.println(Arrays.toString(arr));//输出
		sca.close();
	}
	/**
	 * 选择排序
	 * @param arr 待排序数组
	 * @param n 待排序数组长度
	 */
	public static void selectSort(int [] arr, int n)
	{
		int min, minIndex; 
		for (int i = 0; i < n - 1; i++)//从最小位开始排序
		{
			min = arr[i];
			minIndex = i;
			for (int j = i + 1; j < n; j++)//从第i+1位到第n位中找比第i位还小的值
			{
				if (min > arr[j])//更新
				{
					min = arr[j];
					minIndex = j;
				}
			}
			arr[minIndex] = arr[i];
			arr[i] = min;//第i位完成排序
		}
	}
}
排序算法平均时间复杂度最好情况最坏情况空间复杂度稳定性
选择排序O(n^2)O(n^2)O(n^2)O(1)不稳定

(6)插入排序

将待排序数组中的数依次取出插入到有序的数组中

在这里插入图片描述

import java.util.Arrays;
import java.util.Scanner;
public class Main
{
	public static void main(String[] args)
    {
		Scanner sca = new Scanner(System.in);
		int n = sca.nextInt();
		int [] arr = new int [n];
		for (int i = 0; i < n; i++)//随机生成n个1000以内的数
		{
			arr[i] = (int)(Math.random() * 1000);
		}
		insertSort(arr, n);//插入排序
		System.out.println(Arrays.toString(arr));//输出
		sca.close();
	}
	/**
	 * 插入排序
	 * @param arr 待排序数组
	 * @param n 待排序数组长度
	 */
	public static void insertSort(int [] arr, int n)
	{
		int t, value;
		for (int i = 1; i < n; i++)//把arr[0]看作已排序序列,arr[1]~arr[n]看作未排序序列
		{
			t = i - 1;
			value = arr[i];
			while (t >= 0 && value < arr[t])//从已排序后面开始比较,得到插入的位置
			{
				arr[t + 1] = arr[t];
				t--;
			}
			if (t + 1 != i)//插入
			{
				arr[t + 1] = value;
			}
		}
	}
}
排序算法平均时间复杂度最好情况最坏情况空间复杂度稳定性
插入排序O(n^2)O(n)O(n^2)O(1)稳定

(7)希尔排序

先分 len(数组长度)/2 组进行插入排序,再分 len(数组长度)/2/2 组进行插入排序,直到整体进行插入排序,主要解决插入排序碰到最坏情况,减少后移的次数提供速度

在这里插入图片描述

import java.util.Arrays;
import java.util.Scanner;
public class Main
{
	public static void main(String[] args)
    {
		Scanner sca = new Scanner(System.in);
		int n = sca.nextInt();
		int [] arr = new int [n];
		for (int i = 0; i < n; i++)//随机生成n个1000以内的数
		{
			arr[i] = (int)(Math.random() * 1000);
		}
		shellSort(arr);//希尔排序
		System.out.println(Arrays.toString(arr));//输出
		sca.close();
	}
	/**
	 * 希尔排序
	 * @param arr 待排序数组
	 */
	public static void shellSort(int [] arr)
	{
		int len = arr.length;//数组长度
		for (int i = len / 2; i >= 1; i /= 2)//把数组分为i组
		{
			for (int j = i; j < len; j++)//从第i位开始向后扫描
			{
				int k = j;
				int temp = arr[k];
				while (k - i >= 0 && temp < arr[k - i])//插入排序原理
				{
					arr[k] = arr[k - i];
					k -= i;
				}
				if (temp < arr[k])
				{
					arr[k] = temp;
				}
			}
		}
	}
}
排序算法平均时间复杂度最好情况最坏情况空间复杂度稳定性
希尔排序O(n log n)O(nlog2n)O(nlog2n)O(1)不稳定

PS:希尔排序是对插入排序的优化


(8)归并排序

把数组不断细分到最小单位再根据需要组合

在这里插入图片描述

import java.util.Arrays;
import java.util.Scanner;
public class Main
{
	public static void main(String[] args)
    {
		Scanner sca = new Scanner(System.in);
		int n = sca.nextInt();
		int [] arr = new int [n];
		for (int i = 0; i < n; i++)//随机生成n个1000以内的数
		{
			arr[i] = (int)(Math.random() * 1000);
		}
		mergeSort(arr, 0, n - 1);//归并排序
		System.out.println(Arrays.toString(arr));//输出
		sca.close();
	}
    /**
	 * 分和治结合
	 * @param arr 待排序数组
	 * @param left 左
	 * @param right 右
	 */
	public static void mergeSort(int [] arr, int left, int right)
	{
		if (left < right)
		{
			int mid = (left + right) / 2;
			mergeSort(arr, left, mid);//左递归
			mergeSort(arr, mid + 1, right);//右递归
			merge(arr, left, mid, right);//治
		}
	}
	/**
	 * 治
	 * @param arr 待排序数组
	 * @param left 左
	 * @param mid 中间
	 * @param right 右
	 */
	public static void merge(int [] arr, int left, int mid, int right)
	{
		int l = left;
		int r = mid + 1;
		int t = 0;
		int [] temp = new int [right - left + 1];
		while (l <= mid && r <= right)
		{
			if (arr[l] <= arr[r])//两个子数组从左到右比较,哪个小就先插入到临时数组
			{
				temp[t] = arr[l];
				t++;
				l++;
			}
			else
			{
				temp[t] = arr[r];
				t++;
				r++;
			}
		}
		while (l <= mid)//左数组如果还有剩余直接把全部插入到临时数组
		{
			temp[t] = arr[l];
			t++;
			l++;
		}
		while (r <= right)//右数组如果还有剩余直接把全部插入到临时数组
		{
			temp[t] = arr[r];
			t++;
			r++;
		}
		t = 0;
		for (int i = left; i <= right; i++)//更新数组left到right位置,而不是全部数组
		{
			arr[i] = temp[t];
			t++;
		}
		
	}
}
排序算法平均时间复杂度最好情况最坏情况空间复杂度稳定性
归并排序O(n log n)O(n log n)O(n log n)O(n)稳定

PS:分治思想

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值