在排序算法的复习当中,有些算法还是比较难理解的,好在以前打下的基础,再次学习轻松很多,下面记录下手写常用的排序算法。
直接插入排序的性能分析:
1. 最好情况:O(n)
2. 平均情况:O(n^2)
3. 最坏情况:O(n^2)
空间复杂度:O(1)
稳定性:稳定(相同元素的相对位置不会改变)
希尔排序(第一个突破O(n^2)的排序算法)的性能分析:
会根据增量的不同而不同,一般来说:
1. 最好情况:O(n^1.3)
2. 最坏情况:O(n^2)
空间复杂度:O(1)
稳定性:不稳定(相同元素的相对位置会改变)
快速排序的性能分析:
1. 最好情况:O(nlog2(n))
2. 平均情况:O(nlog2(n))
3. 最坏情况:O(n^2)
空间复杂度:O(log2(n))
稳定性:不稳定(相同元素的相对位置会改变)
简单选择排序的性能分析:
1. 最好情况:O(n^2)
2. 平均情况:O(n^2)
3. 最坏情况:O(n^2)
空间复杂度:O(1)
稳定性:不稳定(相同元素的相对位置会改变)
堆排序的性能分析:
1. 最好情况:O(nlog2(n))
2. 平均情况:O(nlog2(n))
3. 最坏情况:O(nlog2(n))
空间复杂度:O(1)
稳定性:不稳定(相同元素的相对位置会改变)
package com.me.sorts;
import java.net.InetAddress;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter.DEFAULT;
public class Sorts {
/**
* 插入排序
* @param a
*/
public static void InsertSort(int[] a) {
if (a==null || a.length<=0) { //排空
System.out.println("数组为空");
return ;
}
int temp=0; //暂存要插入的元素
int j=0;
for (int i = 1,len=a.length; i <len; i++) { //遍历数组
temp=a[i];
j=i-1;
for (; j>=0 && a[j]>temp;j--) { //如果a[i]之前的数比要插入的temp大,该数后移。注意j>=0
a[j+1]=a[j];
}
a[j+1]=temp; //当循环结束,也就是temp比a[j]大或者相等,或者最小时(j=-1),插入到a[j]后面
}
}
/**
* 希尔排序
* @param a
*/
public static void shellSort(int[] a) {
if (a==null || a.length<=0) { //排空
System.out.println("数组为空");
return ;
}
int temp=0; //暂存要插入的元素
int len=a.length;
int j=0;
for (int d = len/2; d>0; d/=2) { //取d/2来分割排序记录
for (int i = d; i<len; i++) {//从d开始,循环到结束
temp=a[i];
j=i-d; //取第前d个元素作为比较
for (; j>=0 && a[j]>temp; j-=d) { //连续以d为分割比较
a[j+d]=a[j];
}
a[j+d]=temp; //插入
}
}
}
/**
* 冒泡排序改进版
* @param a
*/
public static void bubbleSort(int[] a) {
int exchange=a.length-1;
int bound=0;
while (exchange!=0) {
bound=exchange;
exchange=0;
for (int i = 0; i < bound; i++) {
if (a[i]>a[i+1]) {
a[i]=a[i]+a[i+1];
a[i+1]=a[i]-a[i+1];
a[i]=a[i]-a[i+1];
exchange=i;
}
}
}
}
/**
* 快速排序算法
* @param a
* @param first
* @param end
*/
public static void quickSort(int[] a,int first,int end) {
if (first<end) {
int pivot=partition(a, first, end); //开始对区间进行排序,返回最终的轴值
quickSort(a, first, pivot-1); //递归排序左区间,轴值不需要参与排序
quickSort(a, pivot+1, end); //递归排序右区间
}
}
/**
* 快速排序一次划分算法
* @param a
* @param first
* @param end
* @return
*/
public static int partition(int a[],int first,int end) {
int i=first,j=end;
while (i<j) {
while (i<j && a[j]>=a[i]) { //从右侧开始扫描,直到找到右侧的比左侧小的数,然后交换位置
j--;
}
if (i<j) { //交换位置
a[i]=a[i]+a[j];
a[j]=a[i]-a[j];
a[i]=a[i]-a[j];
i++;
}
while (i<j && a[j]>=a[i]) { //从左侧开始扫描,直到找到右侧的比左侧小的数,然后交换位置
i++;
}
if (i<j) { //交换位置
a[i]=a[i]+a[j];
a[j]=a[i]-a[j];
a[i]=a[i]-a[j];
j--;
}
}
return i; //轴值记录的最终位置
}
/**
* 选择排序
* @param a
*/
public static void selectSort(int[] a) {
int index=0;
for (int i = 0,len=a.length; i < len-1; i++) {
index=i; //存储要交换的位置
for (int j = i+1; j < len; j++) { //每次循环寻找最小的
if (a[j]<a[index]) {
index=j;
}
}
if (index!=i) { //需要交换
a[i]=a[i]+a[index];
a[index]=a[i]-a[index];
a[i]=a[i]-a[index];
}
}
}
/**
* 堆排序
* @param a
*/
public static void heapSort(int[] a ) {
int len=a.length;
for (int i = len/2-1; i >=0; i--) { //初始化建堆
sift(a,i,len);
}
//调整堆结构+交换堆顶元素与末尾元素
for(int i=len-1;i>0;i--){
a[0]=a[i]+a[0];
a[i]=a[0]-a[i];
a[0]=a[0]-a[i];
sift(a,0,i);//重新对堆进行调整
}
}
/**
* 堆排序,调整堆方法
* @param a
* @param i
*/
public static void sift(int[] a, int k,int m) {
int i=k;
int j=2*i+1;
while (j<m) {
if (j+1<m && a[j]<a[j+1]) { //比较j的左右孩子,指向最大的
j++;
}
if (a[i]>a[j]) { //根节点已经大于左右孩子的较大者,排序结束
break;
}else {
//将根节点与结点j交换
a[i]=a[i]+a[j];
a[j]=a[i]-a[j];
a[i]=a[i]-a[j];
i=j; j=2*i+1;
}
}
}
public static void main(String[] args) {
int[] a = {3, 5, 1, 2, 6, 4, 7, 11, 23, 44, 3, 34};
InsertSort(a);
System.out.print("直接插入排序:");
for(int i = 0; i < a.length; i++) {
System.out.print(a[i] + " ");
}
System.out.println();
int[] b={3, 5, 1, 2, 6, 4, 7, 11, 23, 44, 3, 34};
shellSort(b);
System.out.print("希尔排序:");
for(int i = 0; i < b.length; i++) {
System.out.print(b[i] + " ");
}
System.out.println();
int[] c={3, 5, 1, 2, 6, 4, 7, 11, 23, 44, 3, 34};
bubbleSort(c);
System.out.print("冒泡排序改进版:");
for(int i = 0; i < c.length; i++) {
System.out.print(c[i] + " ");
}
System.out.println();
int[] d={3, 5, 1, 2, 6, 4, 7, 11, 23, 44, 3, 34};
quickSort(d, 0, d.length-1);
System.out.print("快速排序:");
for(int i = 0; i < d.length; i++) {
System.out.print(d[i] + " ");
}
System.out.println();
int[] e={3, 5, 1, 2, 6, 4, 7, 11, 23, 44, 3, 34};
selectSort(e);
System.out.print("选择排序:");
for(int i = 0; i < e.length; i++) {
System.out.print(e[i] + " ");
}
System.out.println();
int[] f={3, 5, 1, 2, 6, 4, 7, 11, 23, 44, 3, 34};
heapSort(f);
System.out.print("堆排序:");
for(int i = 0; i < f.length; i++) {
System.out.print(f[i] + " ");
}
}
}