当然,如果不是比较排序,就可以突破这种现状。线性排序算法我在另一篇文章中已经写到,见 线性排序的Java实现 。
下面的图是网上对于常见排序算法的总结:
1.插入排序Java代码如下:
//插入排序 希尔排序是它的变形
public static void insertSort(int[] a)
{
for(int i=0;i<a.length-1;i++)
{
int j=i+1;
int tmp=a[j];
for(;j>0 && tmp<a[j-1];j--)
a[j]=a[j-1];
a[j]=tmp;
}
}
2.选择排序
//选择排序 不稳定排序
public static void chooseSort(int[] a)
{
for(int i=0;i<a.length-1;i++)
{
int min=i;
for(int j=i+1;j<a.length;j++)
{
if(a[j]<a[min])
min=j;
}
int tmp=a[i];
a[i]=a[min];
a[min]=tmp;
}
}
3.冒泡排序,进行改进可以达到最快时间O(N)
//冒泡排序 基本版
public static void bubbleSort(int[] a)
{
for(int i=0;i<a.length;i++)
{
for(int j=1;j<a.length-i;j++)
{
if(a[j-1]>a[j])
{
int tmp=a[j-1];
a[j-1]=a[j];
a[j]=tmp;
}
}
}
}
//冒泡排序改进 最优时间复杂度O(N)
public static void bubbleSortN(int[] a)
{
boolean doswap;
for(int i=0;i<a.length;i++)
{
doswap=false;
for(int j=1;j<a.length-i;j++)
{
if(a[j-1]>a[j])
{
int tmp=a[j-1];
a[j-1]=a[j];
a[j]=tmp;
doswap=true;
}
}
if(doswap==false) //说明没有交换,数组是顺序的
break;
}
}
4.希尔排序,它是插入排序的变形,可以选取不同的增量
//希尔排序,就是插入排序的一种变形
public static void shellsort(int[] a){
for(int gap=a.length/2;gap>0;gap=gap/2){
for(int i=gap;i<a.length;i++){
int tmp=a[i];
int j=i;
for(;j>=gap && tmp<a[j-gap];j=j-gap)
a[j]=a[j-gap];
a[j]=tmp;
}
}
}
5.堆排序 这里需要有建堆,维护堆,堆排序
//维护堆
public static void maxHeapify(int[] a,int i,int size)
{
int tmp=a[i];
int child=i*2;
while(child<=size)
{
if(child+1<size && a[child+1]<a[child])
child++;
if(a[child]<tmp)
a[child/2]=a[child];
else
break;
child=2*child;
}
a[child/2]=tmp;
}
//建堆 时间复杂度O(N)
public static void buildHeap(int[] a)
{
for(int i=(a.length-1)/2;i>0;i--) //只要对堆前一半的元素进行维护
{
maxHeapify(a,i,a.length-1);
}
}
//堆排序算法 这是最小堆 输出的数组是从大到小 且a[0]不算堆元素
public static void heapSort(int[] a)
{
int temp;
buildHeap(a);
int size=a.length-1; //去掉a[0]
for(int i=size;i>1;i--)
{
temp=a[i];
a[i]=a[1];
a[1]=temp;
size--;
maxHeapify(a,1,size);
}
}
6.归并排序
//归并排序 递归方法 O(N)的空间复杂度
public static void mergeSort(int[] a){
int[] tmp=new int[a.length];
mergeSort(a,tmp,0,a.length-1);
}
private static void mergeSort(int[] a,int[] tmp,int left,int right){
if(left<right)
{
int center=(left+right)/2;
mergeSort(a,tmp,left,center); //先分割,再合并处理;和快速排序是反的(快排:先处理,再分割)
mergeSort(a,tmp,center+1,right);
merge(a,tmp,left,center,right);
}
}
private static void merge(int[] a,int[] tmp,int left,int center,int right){
int num=right-left+1;
int i=left;
int j=center+1;
int pos=left;
while(i<=center&&j<=right)
{
if(a[i]<a[j])
tmp[pos++]=a[i++];
else
tmp[pos++]=a[j++];
}
while(i<=center)
{
tmp[pos++]=a[i++];
}
while(j<=right)
{
tmp[pos++]=a[j++];
}
for(int q=left;q<=right;q++)
{
a[q]=tmp[q];
}
}
//合并过程 O(1)空间复杂度,不建立临时数组空间,但是时间代价会变大
private static void merge(int[] a,int left,int center,int right){
int lpos=left;
int rpos=center+1;
while(lpos<=center && rpos<=right) //类似插入过程
{
if(a[lpos]<=a[rpos])
lpos++;
else
{
int tmp=a[rpos];
for(int i=rpos;i>=lpos;i--)
{
a[i]=a[i-1];
}
a[lpos]=tmp;
rpos++;
lpos++;
}
}
}
7.快速排序
//快速排序
public static void quickSort(int[] a)
{
quickSort(a,0,a.length-1);
}
private static void quickSort(int[] a,int left,int right)
{
if(left<right)
{
int pivot=a[left];
int i=left;
int j=right;
while(i<j)
{
while(a[j]>pivot && i<j){j--;}
if(i<j)
a[i++]=a[j];
while(a[i]<pivot && i<j){i++;}
if(i<j)
a[j--]=a[i];
}
a[i]=pivot;
quickSort(a,left,i-1);
quickSort(a,i+1,right);
}
}
非递归实现,使用栈存储
//快速排序的非递归实现,利用系统的栈stack
public class QuickSortNonRecursion {
public static void main(String[] args) {
QuickSortNonRecursion qsnr = new QuickSortNonRecursion();
int[] array = {0, 2, 11, 121, 18, 99, 3, 5, 101, 22, 9, 100};
qsnr.quicksort(array); for (int i : array) {
System.out.print(i + " "); }
}
public void quicksort(int[] array) {
if (array == null || array.length == 1) return;
//存放开始与结束索引 Stack<Integer> s = new Stack<Integer>();
//压栈
s.push(0);
s.push(array.length - 1);
//利用循环里实现
while (!s.empty()) {
int right = s.pop();
int left = s.pop();
//如果最大索引小于等于左边索引,说明结束了
if (right <= left) continue;
int i = partition(array, left, right);
if (left < i - 1) {
s.push(left); s.push(i - 1);
}
if (i + 1 < right) {
s.push(i+1); s.push(right);
}
}
}
//找到轴心,进行交换
public int partition (int[] data, int first, int end) {
int temp;
int i=first,j=end;
if(first<end) {
temp=data[i];
//当i=j的时候,则说明扫描完成了
while(i<j) {
//从右边向左边扫描找到一个小于temp的元素
while(j>i&&data[j]>temp)j--; if(i<j) {
//将该元素赋值给temp
data[i]=data[j];
//赋值后就应该将i+1指向下一个序号
i++; }
//然后从左边向右边开始扫描,找到一个大于temp的元素
while(i<j&&temp>data[i])i++;
if(i<j) {
//将该元素赋值给temp
data[j]=data[i];
//赋值后就应该将j-1指向前一个序号
j--;
}
} //将轴数据放在i位置中
data[i]=temp;
}
return i;
}
}