當然,如果不是比較排序,就可以突破這種現狀。線性排序算法我在另一篇文章中已經寫到,見 線性排序的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;
}
}