##八大排序算法思想,时间复杂度,稳定性、及其java实现
重新总结整理一下八大排序算法的算法思想及代码实现,一起分享一下。
一、归并排序
归并排序
算法思想
- 1.设r[i…n]由两个有序子表r[i…m]和r[m+1…n]组成,两个子表长度分别为n-i +1、n-m。
- j=m+1;k=i;i=i; //置两个子表的起始下标及辅助数组的起始下标
- 2.若i>m 或j>n,转⑷ //其中一个子表已合并完,比较选取结束
- 3.//选取r[i]和r[j]较小的存入辅助数组rf
- 如果r[i]<r[j],rf[k]=r[i]; i++; k++; 转⑵
- 否则,rf[k]=r[j]; j++; k++; 转⑵
- 4.//将尚未处理完的子表中元素存入rf
- 如果i<=m,将r[i…m]存入rf[k…n] //前一子表非空
- 如果j<=n , 将r[j…n] 存入rf[k…n] //后一子表非空
- 合并结束。***
- 时间复杂度:O(nlogn
- 稳定性:稳定
package eightSort;
import java.util.Arrays;
/**
* 归并排序
*
* 1.设r[i…n]由两个有序子表r[i…m]和r[m+1…n]组成,两个子表长度分别为n-i +1、n-m。
* j=m+1;k=i;i=i; //置两个子表的起始下标及辅助数组的起始下标
* 2.若i>m 或j>n,转⑷ //其中一个子表已合并完,比较选取结束
* 3.//选取r[i]和r[j]较小的存入辅助数组rf
* 如果r[i]<r[j],rf[k]=r[i]; i++; k++; 转⑵
* 否则,rf[k]=r[j]; j++; k++; 转⑵
* 4.//将尚未处理完的子表中元素存入rf
* 如果i<=m,将r[i…m]存入rf[k…n] //前一子表非空
* 如果j<=n , 将r[j…n] 存入rf[k…n] //后一子表非空
*
* 合并结束。
*
* 时间复杂度:O(nlogn
*
* 稳定性:稳定
* Created by Administrator on 2017/9/20 0020.
*/
public class MergeSort {
public static void merge(int[] cen,int[] res,int s,int m,int temp){
int ss=s;
int mm=temp;
int i=s;
for (;ss<=temp&&mm<=m;i++){
if (cen[ss]<=cen[mm]){
res[i]=cen[ss];
ss++;
}else {
res[i]=cen[mm];
mm++;
}
}
//把剩下的复制到res中
if (ss<=temp){
for (int j=i;j<=m;j++){
res[i]=cen[ss];
ss++;
}
}
if (mm<=temp){
for (int j=i;j<=m;j++){
res[i]=cen[mm];
mm++;
}
}
}
public static void mergeSort(int[] arr,int[] res,int s,int m){
if (s==m) System.arraycopy(arr,0,res,0,arr.length);
else {
int[] cen=new int[arr.length];
int temp=(s+m)/2;
mergeSort(arr,cen,s,temp);
mergeSort(arr,cen,temp+1,m);
merge(cen,res,s,m,temp);
};
}
public static void main(String[] args){
int[] arr=new int[]{5,59,6,7,15,32,4,5,4,12};
int[] res=new int[arr.length];
mergeSort(arr,res,0,arr.length-1);
System.out.print(Arrays.toString(res));
}
}
二、 插入排序——直接插入排序
插入排序——直接插入排序
算法思想
- 将一个记录插入到已排序好的有序表中,从而得到一个新,记录数增1的有序表。
- 即:先将序列的第1个记录看成是一个有序的子序列,然后从第2个记录逐个进行插入,直至整个序列有序为止。
- 要点:设立哨兵,作为临时存储和判断数组边界之用。
- 时间复杂度:O(n^2).
- 稳定性:稳定
package eightSort;
import java.util.Arrays;
/**
* 插入排序——直接插入排序
*
* 将一个记录插入到已排序好的有序表中,从而得到一个新,记录数增1的有序表。
* 即:先将序列的第1个记录看成是一个有序的子序列,然后从第2个记录逐个进行插入,直至整个序列有序为止。
*
* 要点:设立哨兵,作为临时存储和判断数组边界之用。
*
* 时间复杂度:O(n^2).
*
* 稳定性:稳定
* Created by Administrator on 2017/9/19 0019.
*/
public class InsertSort {
public static void insertSort(int[] arr){
int flag;
for (int i=1;i<arr.length;i++){
flag=arr[i];//哨兵
for (int j=0;j<i;j++){
if (arr[j]>flag){//找到元素插入位置
for (int k=i-1;k>=j;k--){//元素向后移动
arr[k+1]=arr[k];
}
arr[j]=flag;//元素插入
break;
}
}
}
}
public static void main(String[] args){
int[] arr=new int[]{5,59,6,7,15,32,4,5,4,12};
insertSort(arr);
System.out.print(Arrays.toString(arr));
}
}
三、插入排序——希尔排序
插入排序——希尔排序
算法思想
- 选择一个增量序列t1,t2,…,tk,其中ti>tj,tk=1;
- 按增量序列个数k,对序列进行k 趟排序;
- 每趟排序,根据对应的增量ti,将待排序列分割成若干长度为m 的子序列,分别对各子表进行直接插入排序。
- 仅增量因子为1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。
- 时间复杂度:根据具体数据情况
- 稳定性;不稳定
package eightSort;
import java.util.Arrays;
/**
* 插入排序——希尔排序
*
*选择一个增量序列t1,t2,…,tk,其中ti>tj,tk=1;
* 按增量序列个数k,对序列进行k 趟排序;
* 每趟排序,根据对应的增量ti,将待排序列分割成若干长度为m 的子序列,分别对各子表进行直接插入排序。
* 仅增量因子为1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。
*
* 时间复杂度:根据具体数据情况
*
* 稳定性;不稳定
* Created by Administrator on 2017/9/19 0019.
*/
public class ShellInsertSort {
public static void shellInsertSort(int[] data) {
int j = 0;
int temp = 0;
for (int increment = data.length / 2; increment > 0; increment /= 2) {
System.out.println("increment:" + increment);
for (int i = increment; i < data.length; i++) {
// System.out.println("i:" + i);
temp = data[i];
for (j = i - increment; j >= 0; j -= increment) {
// System.out.println("j:" + j);
// System.out.println("temp:" + temp);
// System.out.println("data[" + j + "]:" + data[j]);
if (temp < data[j]) {
data[j + increment] = data[j];
} else {
break;
}
}
data[j + increment] = temp;
}
for (int i = 0; i < data.length; i++)
System.out.print(data[i] + " ");
}
}
public static void main(String[] args){
int[] arr=new int[]{5,59,6,7,15,32,4,5,4,12};
shellInsertSort(arr);
System.out.print(Arrays.toString(arr));
}
}
四、 交换排序——冒泡排序
交换排序——冒泡排序
算法思想
- 每当两相邻的数比较后发现它们的排序与排序要求相反时,就将它们互换
- 时间复杂度:O(n^2)
- 稳定性:稳定
package eightSort;
import java.util.Arrays;
/**
* 交换排序——冒泡排序
*
* 每当两相邻的数比较后发现它们的排序与排序要求相反时,就将它们互换
*
* 时间复杂度:O(n^2)
*
* 稳定性:稳定
* Created by Administrator on 2017/8/21 0021.
*/
public class BobbleSort {
public static void bubbleSort(int[] a) {
int temp;
for (int i = 0; i < a.length - 1; ++i) {
for (int j = a.length - 1; j > i; --j) {
if (a[j] > a[j - 1]) {
temp = a[j];
a[j] = a[j - 1];
a[j - 1] = temp;
}
}
}
}
public static void main(String[] args) {
int arr[] = { 49,38,65,97,76,13,27,49};
bubbleSort(arr);
System.out.println(Arrays.toString(arr));
}
}
五、交换排序——快速排序
交换排序——快速排序
算法思想
- 1、设置一个flag值,把数组一分为二,左边的数小于flag,右边的数大于flag
- 2、对数组的两部分,在进行分组,直到low==high
- 时间复杂度:O(nlog2n)【被认为是同数量级中,平均性能最好的】
- 稳定性:不稳定
package eightSort;
import java.util.Arrays;
/**交换排序——快速排序
*
* 1、设置一个flag值,把数组一分为二,左边的数小于flag,右边的数大于flag
* 2、对数组的两部分,在进行分组,直到low==high
*
* 时间复杂度:O(nlog2n)【被认为是同数量级中,平均性能最好的】
*
* 稳定性:不稳定
* Created by Administrator on 2017/9/20 0020.
*/
public class QuickSort {
/**
* 将arr按照flag,一分为二
* @param arr
* @param low
* @param high
* @return
*/
public static int partition(int[] arr,int low,int high){
int flag=arr[low];//标记
while (low<high){
//如果high位置下的数,大于或者等于flag,则high++
while (low<high&&arr[high]>=flag)
high--;
//如果跳出循环,说明high位置下的数,小于flag,进行交换
arr[low]=arr[high];
arr[high]=flag;
//如果low位置下的数,小于或者等译flag,则high++
while (low<high&&arr[low]<=flag)
low++;
//如果跳出循环,说明low位置下的数,大于flag,进行交换
arr[high]=arr[low];
arr[low]=flag;
}
return low;//如果跳出循环,说明low==high,返回这个位置
}
public static void quickSort(int[] arr,int low,int high){
if (low<high){
int partition= partition(arr,low,high);
//将数组分成两部分,分别对两部分,在进行分组,直到low==high
quickSort(arr,low,partition-1);
quickSort(arr,partition+1,high);
}
}
public static void main(String[] args){
int[] arr=new int[]{5,59,6,7,15,32,4,5,4,12};
quickSort(arr,0,arr.length-1);
System.out.print(Arrays.toString(arr));
}
}
六、选择排序——直接选择排序
选择排序——直接选择排序
算法思想
- 第一趟,从n 个记录中找出关键码最小的记录与第一个记录交换;
- 第二趟,从第二个记录开始的n-1 个记录中再选出关键码最小的记录与第二个记录交换;
- 以此类推…
- 第i 趟,则从第i 个记录开始的n-i+1 个记录中选出关键码最小的记录与第i 个记录交换,
- 直到整个序列按关键码有序。
- 时间复杂度:O(n^2)
- 稳定性:不稳定
package eightSort;
import java.util.Arrays;
/**选择排序——简单选择排序
*
* 第一趟,从n 个记录中找出关键码最小的记录与第一个记录交换;
* 第二趟,从第二个记录开始的n-1 个记录中再选出关键码最小的记录与第二个记录交换;
* 以此类推.....
* 第i 趟,则从第i 个记录开始的n-i+1 个记录中选出关键码最小的记录与第i 个记录交换,
* 直到整个序列按关键码有序。
*
* 时间复杂度:O(n^2)
*
* 稳定性:不稳定
* Created by Administrator on 2017/9/19 0019.
*/
public class SelectSort {
public static void selectSort(int[] arr){
int max;//最大数
int flag;//最大数的位置
for (int i=0;i<arr.length;i++){
max=arr[i];
flag=i;
for (int j=i;j<arr.length;j++){
if (arr[j]>max){
max=arr[j];
flag=j;
}
}
//最大数与第i个位置的数交换位置
arr[flag]=arr[i];
arr[i]=max;
}
}
public static void main(String[] args){
int[] arr=new int[]{5,59,6,7,15,32,4,5,4,12};
selectSort(arr);
System.out.print(Arrays.toString(arr));
}
}
七、 选择排序——堆排序
选择排序——堆排序
算法思想
- 1、建小根(大根)堆
- 2、将小根(大根)堆顶元素输出
- 3、调整剩下元素为小根(大根)堆
- 时间复杂度:O(n*logn)
- 稳定性:不稳定
package eightSort;
import java.util.Arrays;
/**选择排序——堆排序
*
* 1、建小根(大根)堆
* 2、将小根(大根)堆顶元素输出
* 3、调整剩下元素为小根(大根)堆
*
* 时间复杂度:O(n*logn)
*
* 稳定性:不稳定
* Created by Administrator on 2017/9/19 0019.
*/
public class HeapSort {
/**
* 调整堆
* @param arr
* @param s
* @param m
*/
public static void heapAdjust(int[] arr,int s,int m){
int flag=arr[s];
int i=2*s+1;
while (i<m) {
if (i+1<m&&arr[i]>arr[i+1]){
i++;
}
if (flag>arr[i]){
arr[s]=arr[i];
s=i;
}else break;
arr[i]=flag;
i = i * 2+1;
}
}
/**
* 新建堆
* @param arr
*/
public static void builderHeap(int[] arr){
for (int i=arr.length/2;i>=0;i--){
heapAdjust(arr,i,arr.length);
}
}
/**
* 堆排序
*/
public static void heapSort(int[] arr){
builderHeap(arr);
for (int i=arr.length-1;i>0;i--){
int temp=arr[0];
arr[0]=arr[i];
arr[i]=temp;
heapAdjust(arr,0,i);
}
}
public static void main(String[] args){
int[] arr=new int[]{5,59,6,7,15,32,4,5,4,12};
heapSort(arr);
System.out.print(Arrays.toString(arr));
}
}
八、 基数排序
引用:此处为引用
package sort;
public class RadixSort {
private static void radixSort(int[] array,int d)
{
int n=1;//代表位数对应的数:1,10,100...
int k=0;//保存每一位排序后的结果用于下一位的排序输入
int length=array.length;
int[][] bucket=new int[10][length];//排序桶用于保存每次排序后的结果,这一位上排序结果相同的数字放在同一个桶里
int[] order=new int[length];//用于保存每个桶里有多少个数字
while(n<d)
{
for(int num:array) //将数组array里的每个数字放在相应的桶里
{
int digit=(num/n)%10;
bucket[digit][order[digit]]=num;
order[digit]++;
}
for(int i=0;i<length;i++)//将前一个循环生成的桶里的数据覆盖到原数组中用于保存这一位的排序结果
{
if(order[i]!=0)//这个桶里有数据,从上到下遍历这个桶并将数据保存到原数组中
{
for(int j=0;j<order[i];j++)
{
array[k]=bucket[i][j];
k++;
}
}
order[i]=0;//将桶里计数器置0,用于下一次位排序
}
n*=10;
k=0;//将k置0,用于下一轮保存位排序结果
}
}
public static void main(String[] args)
{
int[] A=new int[]{73,22, 93, 43, 55, 14, 28, 65, 39, 81};
radixSort(A, 100);
for(int num:A)
{
System.out.println(num);
}
}
}
更多内容请关注微信公众号“外里科技”