简单算法之9种排序
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了简单算法之9种排序相关的知识,希望对你有一定的参考价值。
甭管什么,笔者就喜欢凑个9。这次,关于排序的算法还是9种,小结一下。排序的算法,尽管有很多的方法例子,但这次是自己总结的,挺有意思算法希望大家喜欢。直接上代码楼,以下算法,都经过笔者亲测,并修改使之有效(粘贴可用)。
package com.css.java.learning.massbag;
import java.util.Arrays;
/**算法:
* 排序相关小结
* @author Red_ant
* 20181119
*/
public class OrderMethod {
/*1、冒泡排序
* 通过相邻两个元素比较的方式,依次选出合适的元素放到
* 数组的第i位。
*/
public static int[] bubbleSort(int[] nums){
int num = 0;
for (int i = 0; i < nums.length -1; i++) {
for (int j = 0; j < nums.length - 1 - i; j++) {//两两比较,符合条件的元素居于前面
if(nums[j] > nums[j + 1]){
num = nums[j];
nums[j] = nums[j + 1];
nums[j + 1] = num;
}
}
}
return nums;
}
/*2、选择排序
* 每一趟从待排序列,选择最小的元素放到已排序好的序列末尾,剩下的为待排序序列,
* 重复上述步骤,直至完成。
*/
public static int[] selectSort(int[] nums){
int num = 0;
for (int i = 0; i < nums.length -1; i++) {
int index = i;
for (int j = i + 1; j < nums.length; j++) {//选择合适的元素,直接放到数组的第i位
if(nums[index] > nums[j]){
index = j;
}
if(index != i){
num = nums[i];
nums[i] = nums[index];
nums[index] = num;
}
}
}
return nums;
}
/*3、选择排序:堆排序
* 堆排序是一种树形结构选择排序
* 堆排序需要两个过程,建立堆,堆顶与堆最后一个元素交换位置。所以堆排序有两个函数组成:
* 建堆的***函数,反复调用***函数实现排序的函数
* 基本思路:
* 将序列建成一个堆,根据升序降序选择大顶堆或小顶堆
* 将堆顶元素与末尾元素交换,将最大元素沉到数组末端
* 重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,反复执行调整+交换步骤,直到整个序列有序。
*/
public static int[] HeapSorts(int[] nums){
//建立大顶
for (int i = nums.length/2 - 1; i >= 0; i--) {
//从第一个非叶子节点从下至上,从右至左调整结构
suitHeap(nums, i, nums.length);
}
//调整堆结构,交换堆顶元素与 末尾元素
for (int j = nums.length - 1; j > 0; j--) {
exchangeNum(nums, 0, j);//交换堆顶元素与末尾元素
suitHeap(nums, 0, j);
}
return nums;
}
private static void exchangeNum(int[] nums, int i, int i2) {
int index = nums[i];
nums[i] = nums[i2];
nums[i2] = index;
}
private static void suitHeap(int[] nums, int i, int length) {
int index = nums[i];//取出当前元素
for (int j = i*2 + 1; j < length; j = j*2+1) {
//从i节点的左节点开始,即2i+1处
if(j+1 < length && nums[j] < nums[j+1]){
//如果,左子节点小于右子节点,j指向右子节点
j++;
}
if(nums[j] > index){
//如果子节点大于父节点,将子节点赋值给父节点
nums[i] = nums[j];
i = j;
}else{
break;
}
}
nums[i] = index;//将index值放到最终位置
}
/*4、java Arrays排序
* 该方法是Arrays类的静态方法,在需要对数组进行排序时,非常好用
*/
public static int[] ArraySort(int[] nums){
Arrays.sort(nums);
return nums;
}
/*5、插入排序:直接插入排序
* 将数组分为两部分,将后部分元素逐一与前部分元素比较
* 然后依据比较结果进行移动元素
*/
public static int[] insertSort(int[] nums){
//从头部第一个当做已经排序好的,把后面的一个一个的插入到已经排序好的列表中
for (int i = 1; i < nums.length; i++) {
int j;
int index = nums[i];//index为待插入的元素
for (j = i; j > 0 && index < nums[j - 1]; j--) {
nums[j] = nums[j -1];
}
nums[j] = index;
}
return nums;
}
/*6、插入排序:希尔排序
* 建堆,对顶与堆的最后一个元素进行排序
* 希尔排序是插入排序的一种,先取一个小于n的整数作为第一个增量,把文件的全部记录分组。
* 所有距离为d1的倍数的记录放在同一个组中,先在各组内进行直接插入排序。实际上是一种分组插入排序的方法。
*/
public static int[] shellSrot(int[] nums){
int index = nums.length/2;
while (index >= 1) {
for (int i = index; i < nums.length; i++) {
if(nums[i] < nums[i - index]){
int j;
int x = nums[i];//当前待插入的元素
nums[i] = nums[i - index];
for (j = i - index; j >= 0 && x < nums[j]; j = j-index) {
nums[j + index] = nums[j];
}
nums[j + index] = x;//插入元素
}
}
index = index/2;
}
return nums;
}
/*7、交换排序:快速排序
* 基本思想:
* A选择一个基准元素,通常选择第一个元素或最后一个元素
* B通过一趟排序将待排序的记录分割成独立的两部分:记录均值比基准元素值小,元素值比基准元素值大
* C此时基准元素在排序好的正确位置
* D分别对这两部分记录,用同样的方法继续进行排序,直到整个序列有序。
*/
public static int[] quickSort(int[] nums, int...is){
int low,hight;
if(is.length == 0){
low = 0;
hight = nums.length - 1;
}else{
low = is[0];
hight = is[1];
}
if(low < hight){//判断,让递归函数退出,否则无限循环
int middle = getMiddle(nums, low, hight);
quickSort(nums, 0, middle - 1);//基准元素小
quickSort(nums, middle + 1, hight);//比基准元素大
}
return nums;
}
//获取,均值
private static int getMiddle(int[] nums, int low, int hight) {
int index = nums[low];//选择基准元素
while (low < hight) {
//从hight开始,找出比基准小的,与low换位置
while (low < hight && nums[hight] >= index) {
hight--;
}
nums[low] = nums[hight];
//从low开始找比基准大,放到之前hight空出来的位置上
while (low < hight && nums[low] <= index) {
low++;
}
nums[hight] = nums[low];
}
//此时low = hight是基准元素的位置,也是空缺的位置
nums[low] = index;
return low;
}
/*
* 8、归并排序
* 基本思想:
* 归并排序是,将两个或两个以上有序表合并成一个新的有序表。
* 即把待排序的序列分为若干个子序列,每个子序列是有序的,然后再把有序序列合并成整体有序序列
*/
public static int[] mergeSort(int[] nums){
sortmerge(nums, 0, nums.length - 1);
return nums;
}
private static void sortmerge(int[] nums, int i, int j) {
if(i >= j){
return;
}
//找出中间索引
int middle = (i + j)/2;
//对左边数组进行递归
sortmerge(nums, i, middle);
//对右边数组进行递归
sortmerge(nums, middle + 1, j);
//合并数组
merge(nums, i, middle, j);
}
private static void merge(int[] nums, int i, int middle, int j) {
//创建临时中间量数组
int[] tmpArr = new int[nums.length];
//右数组第一个元素索引
int mid = middle + 1;
//记录临时数组索引
int second = i;
//缓存左侧数组第一个元素的索引
int tmp = i;
while (i <= middle && mid <= j) {
//从两个数组中取出最小的放到临时数组中
if(nums[i] <= nums[mid]){
tmpArr[second++] = nums[i++];
}else{
tmpArr[second++] = nums[mid++];
}
}
//剩余部分依次放入临时数组
while (mid <= j) {
tmpArr[second++] = nums[mid++];
}
while (i <= middle) {
tmpArr[second++] = nums[i++];
}
//将临时数组中内容,拷贝到原数组中
while (tmp <= j) {
nums[tmp] = tmpArr[tmp++];
}
}
/*9、基数排序(桶)
* 将数组中的所有元素按照元素中最长的位数进行统一格式,不足位数的前面补充0
* 然后,一次比较每一位的数字,得到最终的比较结果
* 基本思想:
* A遍历找出最大的数(确定最大的数是几)
* B开辟临时数组,用于中间过程的计算
* C用一个count数组统计原数组中某一位(从低位向高位统计)相同的数据出现的次数;
* D用一个start数组计算原数组中某一位(从最低位向最高位计算)相同数据出现的位置;
* E将桶中数据从小到大用临时数组收集起来;
* F重复(3)(4)(5)直到所有位都被统计并计算过,用临时数组收集起来;
* G将临时数组拷回到原数组中;
*/
public static int[] radixSort(int[] nums) {
int exp; // 指数。当对数组按各位进行排序时,exp=1;按十位进行排序时,exp=10;...
int max = getMax(nums); // 数组a中的最大值
// 从个位开始,对数组a按"指数"进行排序
for (exp = 1; max/exp > 0; exp *= 10) {
countSort(nums, exp);
}
return nums;
}
//获取数组中最大的元素
private static int getMax(int[] nums) {
int i, max;
max = nums[0];
for (i = 1; i < nums.length; i++)
if (nums[i] > max)
max = nums[i];
return max;
}
/*
* 对数组按照"某个位数"进行排序(桶排序)
* 参数说明:
* exp -- 指数。对数组a按照该指数进行排序。
* (01) 当exp=1表示按照"个位"对数组a进行排序
* (02) 当exp=10表示按照"十位"对数组a进行排序
* (03) 当exp=100表示按照"百位"对数组a进行排序
*/
private static void countSort(int[] a, int exp) {
int[] output = new int[a.length]; // 存储"被排序数据"的临时数组
int[] buckets = new int[10];
// 将数据出现的次数存储在buckets[]中
for (int i = 0; i < a.length; i++)
buckets[(a[i] / exp) % 10]++;
// 更改buckets[i]。目的是让更改后的buckets[i]的值,是该数据在output[]中的位置。
for (int i = 1; i < 10; i++)
buckets[i] += buckets[i - 1];
// 将数据存储到临时数组output[]中
for (int i = a.length - 1; i >= 0; i--) {
output[buckets[(a[i] / exp) % 10] - 1] = a[i];
buckets[(a[i] / exp) % 10]--;
}
// 将排序好的数据赋值给a[]
for (int i = 0; i < a.length; i++) {
a[i] = output[i];
}
// 用完清空
output = null;
buckets = null;
}
public static void main(String[] args) {
int[] nums = {1221,232,1242,24,12,4,1,43,14,4,21,4,14,4,1,41,2};
//nums = bubbleSort(nums);冒泡
//nums = selectSort(nums);选择
//nums = ArraySort(nums);数组
//nums = insertSort(nums);插入
//nums = shellSrot(nums);希尔
//nums = HeapSorts(nums);选择排序:堆排序
//nums = quickSort(nums);快速
//nums = mergeSort(nums);归并
nums = radixSort(nums);
for (int k = 0; k < nums.length; k++) {
System.err.println("排序之后的"+nums[k]);
}
}
}
以上是关于简单算法之9种排序的主要内容,如果未能解决你的问题,请参考以下文章