8个常用的排序算法
Posted 77的小白
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了8个常用的排序算法相关的知识,希望对你有一定的参考价值。
8个常用的排序算法
冒泡排序
冒泡排序思路比较简单:
- 将序列当中的左右元素,依次比较,保证右边的元素始终大于左边的元素;
( 第一轮结束后,序列最后一个元素一定是当前序列的最大值;) - 对序列当中剩下的n-1个元素再次执行步骤1。
- 对于长度为n的序列,一共需要执行n-1轮比较
(利用while循环可以减少执行次数)
package com.xiaobai.callable;
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
int[] arrays = {24,523,-3,1202,25,63,354,0};
sort(arrays);
System.out.println(Arrays.toString(arrays));
}
public static int[] sort(int[] arrays){
int temp;
for (int i = 0; i < arrays.length-1; i++) {
boolean flag = true;
for (int j = 0; j < arrays.length-i-1; j++) {
if(arrays[j]>arrays[j+1]){
temp = arrays[j];
arrays[j]=arrays[j+1];
arrays[j+1]=temp;
flag = false;
}
}
if (flag){
break;
}
}
return arrays;
}
}
插入排序
插入排序是一种最简单直观的排序算法,它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
算法步骤:
1)将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。
2)从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。)
package com.xiaobai.callable;
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
int[] arrays = {24,523,-3,1202,25,63,354,0};
sort(arrays);
System.out.println(Arrays.toString(arrays));
}
public static int[] sort(int[] arrays){
for (int i = 1; i < arrays.length; i++) {
int key = arrays[i];
int j = i-1;
while (j>=0&&arrays[j]>key){
arrays[j+1]=arrays[j];
j--;
}
arrays[j+1]=key;
}
return arrays;
}
}
希尔排序
希尔排序的算法思想:将待排序数组按照步长gap进行分组,然后将每组的元素利用直接插入排序的方法进行排序;每次将gap折半减小,循环上述操作;当gap=1时,利用直接插入,完成排序。
同样的:从上面的描述中我们可以发现:希尔排序的总体实现应该由三个循环完成:
- 第一层循环:将gap依次折半,对序列进行分组,直到gap=1
- 第二、三层循环:也即直接插入排序所需要的两次循环。具体描述见上。
package com.xiaobai.callable;
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
int[] arrays = {24,523,-3,1202,25,0,24,0};
shell_sort(arrays);
System.out.println(Arrays.toString(arrays));
}
public static int[] sort(int[] arrays,int grp){
for (int i = grp; i < arrays.length; i++) {
int key = arrays[i];
int j = i-grp;
while (j>=0&&arrays[j]>key){
arrays[j+grp]=arrays[j];
j-=grp;
}
arrays[j+grp]=key;
}
return arrays;
}
public static int[] shell_sort(int[] arrays){
int grp = arrays.length/2;
while (grp>=1){
arrays = sort(arrays,grp);
grp=grp/2;
}
return arrays;
}
}
选择排序
原理:选择排序与冒泡排序有点像,只不过选择排序每次都是在确定了最小数的下标之后再进行交换,大大减少了交换的次数
package com.xiaobai.callable;
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
int[] arrays = {24,523,-3,1202,25,0,24,0};
sort(arrays);
System.out.println(Arrays.toString(arrays));
}
public static int[] sort(int[] arrays){
for (int i = 0; i < arrays.length-1; i++) {
int min = i;
for (int j = i; j < arrays.length; j++) {
if (arrays[min]>arrays[j]){
min = j;
}
}
if (i!=min){
int key = arrays[i];
arrays[i]=arrays[min];
arrays[min]=key;
}
}
return arrays;
}
}
堆排序
原理:假设序列有n个元素,先将这n建成大顶堆(父节点比2个子子节点都大),然后取堆顶元素,与序列第n个元素交换,然后调整前n-1元素,使其重新成为堆,然后再取堆顶元素,与第n-1个元素交换,再调整前n-2个元素...直至整个序列有序。
详细可看:快速入门堆排序
package com.xiaobai.callable;
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
int[] arrays = {24,523,-3,1202};
sort(arrays);
System.out.println(Arrays.toString(arrays));
}
public static int[] sort(int[] a){
// 把无序数组构建成最大堆, 这里-2,是因为从索引0开始、另外就是叶子节点【最后一层是不需要堆化的】
for (int i = (a.length-2)/2; i >=0 ; i--) {
addHeap(a, i, a.length);
}
// 循环删除堆顶元素,并且移到集合尾部,调整堆产生新的堆顶
for (int i = a.length-1 ; i > 0 ; i--) {
// 交换最后一个元素与第一个元素
int temp = a[i];
a[i]=a[0];
a[0]=temp;
// 下沉调整最大堆
addHeap(a,0,i);
}
return a;
}
public static int[] addHeap(int[] a ,int parentIndex,int length){
// temp保存父节点的值,用于最后赋值
int temp = a[parentIndex];
int chirldIndex = parentIndex*2+1;
while (chirldIndex<length){
// 如果有右孩子,且右孩子大于左孩子的值,则定位到右孩子
// 这里其实是比较左、右子树的大小,选择更大的
if(chirldIndex+1<length&&a[chirldIndex+1]>a[chirldIndex]){
chirldIndex++;
}
// 如果父节点大于任何一个孩子得值,则直接跳出
if (temp>a[chirldIndex]){
break;
}
// 当左、右子树比父节点更大,进行交换
a[parentIndex]=a[chirldIndex];
//子节点变为父节点,循环判断
parentIndex = chirldIndex;
chirldIndex = parentIndex*2+1;
}
//将原始父节点插入空出来的父节点
a[parentIndex]=temp;
return a;
}
}
快速排序
原理:
通过一趟排序将序列分成左右两部分,其中左半部分的的值均比右半部分的值小,
然后再分别对左右部分的记录进行排序,直到整个序列有序。
详细讲解:快速排序详解
package com.xiaobai.callable;
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
int[] arrays = {24,523,-3,1202,52,0,24,585,102};
sort(arrays,0, arrays.length-1);
System.out.println(Arrays.toString(arrays));
}
public static int[] sort(int[] a,int low,int high){
if (low<high){
// 找寻基准数据的正确索引
int index = getIndex(a, low, high);
// 进行迭代对index之前和之后的数组进行相同的操作使整个数组变成有序
sort(a,low,index-1);
sort(a,index+1, high);
}
return a;
}
public static int getIndex(int[]a,int low,int high){
// 基准数据
int temp = a[low];
while (low<high){
// 当队尾的元素大于等于基准数据时,向前挪动high指针
while (low<high&&a[high]>=temp){
high--;
}
// 如果队尾元素小于tmp了,需要将其赋值给low
a[low]=a[high];
// 当队首元素小于等于tmp时,向前挪动low指针
while (low<high&&a[low]<=temp){
low++;
}
// 当队首元素大于tmp时,需要将其赋值给high
a[high]=a[low];
}
// 跳出循环时low和high相等,此时的low或high就是tmp的正确索引位置
// 由原理部分可以很清楚的知道low位置的值并不是tmp,所以需要将tmp赋值给arr[low]
a[low]=temp;
return low;// 返回tmp的正确位置
}
}
归并排序
package com.xiaobai.callable;
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
int[] arrays = {24,523,-3,1202,52,0,24,585,102};
sort(arrays);
System.out.println(Arrays.toString(arrays));
}
public static void sort(int []arr){
int []temp = new int[arr.length];//在排序前,先建好一个长度等于原数组长度的临时数组,避免递归中频繁开辟空间
sort(arr,0,arr.length-1,temp);
}
private static void sort(int[] arr,int left,int right,int []temp){
if(left<right){
int mid = (left+right)/2;
sort(arr,left,mid,temp);//左边归并排序,使得左子序列有序
sort(arr,mid+1,right,temp);//右边归并排序,使得右子序列有序
merge(arr,left,mid,right,temp);//将两个有序子数组合并操作
}
}
private static void merge(int[] arr,int left,int mid,int right,int[] temp){
int i = left;//左序列指针
int j = mid+1;//右序列指针
int t = 0;//临时数组指针
while (i<=mid && j<=right){
if(arr[i]<=arr[j]){
temp[t++] = arr[i++];
}else {
temp[t++] = arr[j++];
}
}
while(i<=mid){//将左边剩余元素填充进temp中
temp[t++] = arr[i++];
}
while(j<=right){//将右序列剩余元素填充进temp中
temp[t++] = arr[j++];
}
t = 0;
//将temp中的元素全部拷贝到原数组中
while(left <= right){
arr[left++] = temp[t++];
}
}
}
基数排序
以上是关于8个常用的排序算法的主要内容,如果未能解决你的问题,请参考以下文章