排序算法

幾個經典排序算法自己手寫一下練習練習

1、冒泡排序

private static int[] bubleSort(int[] arr) {
	for(int i=0;i<arr.length;i++){
		for(int j=0;j<arr.length-i-1;j++){
			if(arr[j]>arr[j+1]){
				int tmp=arr[j+1];
				arr[j+1]=arr[j];
				arr[j]=tmp;
			}
		}
	}
	return arr;
}

最簡單的冒泡排序,沒什麼多說的,兩個for循環,每次循環把最大的數排到後面。

冒泡排序最好的時間複雜度爲O(n),最差的時間複雜度爲O(n²),平均時間複雜度爲O(n²);


2、插入排序

給定一個數組{8,7,9,5,6,4,0,1,2,3},for循環,從7遍歷到3,從第2個元素7開始,與前面各個元素比較,將它插入到前面數組中相應的位置。比如5插入到{1,2,3,4,6,10}中的4和6之間。

private static int[] insertSort(int[] arr) {  //插入排序 
	for(int i=1;i<arr.length;i++){
		int tmp=arr[i];
		for(int j=i-1;j>=0;j--){
			if(tmp<arr[j]){
				arr[j+1]=arr[j];
				arr[j]=tmp;
			}
			if(tmp>arr[j]){
				break;
			}
		}
	}
	return arr;
}

空間複雜度O(1) 
時間複雜度O(n2) 
最差情況:反序,需要移動n*(n-1)/2個元素 
最好情況:正序,不需要移動元素
數組在已排序或者是“近似排序”時,插入排序效率的最好情況運行時間爲O(n);
插入排序最壞情況運行時間和平均情況運行時間都爲O(n²)。


3、希爾排序

基於插入排序的思想,增加了步長,一般先取array.length/2,然後依次二分直到爲1。每次對第i個,i+step,i+2step等等元素進行插入排序。

例:{6,3,4,5,1,7,2,9,10,8}

第一次排序,step爲10/2=5,第一次分爲5組,每組爲{6,7}{3,2}{4,9}{5,10}{1,8}

排序之後爲{6,2,4,5,1,7,3,9,10,8}

第二次排序,step爲5/2=2,分2組,每組爲{6,4,1,2,10}{3,5,7,9,8}

排序之後爲{1,3,2,5,4,7,6,8,10,9}

最後一次排序,step爲1,插入排序。

private static int[] shellSort(int[] array) {
		int step=array.length/2;
		while(step>0){
			System.out.println("step="+step);
			for(int i=0;i<step;i++){
				for(int j=i+step;j<array.length;j=j+step){
					int k=j;
					int tmp=array[k];
					while(k>=0){
						if(tmp<array[k]){
							array[k+step]=array[k];
							array[k]=tmp;
						}
						if(tmp>array[k]){
							break;
						}
						k=k-step;
					}
				}
			}
			step=step/2;
		}
		return array;
	}

平均時間複雜度O(n的1.3次方)(這個牛逼了,居然還有1.3次方)

最好情況O(n),最壞情況O(n²)。

4、簡單選擇排序

從i=0開始循環,每次選出最小或者最大的元素與第 i個元素交換,跟冒泡排序有點像。

private static int[] selectSort(int[] array) {  //選擇排序
		for(int i=0;i<array.length;i++){
			int min=Integer.MAX_VALUE;
			int minJ=0;
			for(int j=i;j<array.length;j++){
				if(array[j]<min){
					min=array[j];
					minJ=j;
				}
			}
			array[minJ]=array[i];
			array[i]=min;
		}
		return array;
	}

時間複雜度爲O(n²)。


5、歸併排序

分治法的經典例子,先把數組二分二分再二分,直到分爲只剩一個元素,然後再兩兩比較大小,歸併。


public class mergeSort {
    public static void main(String[] args) {
        int[] array={6,3,4,5,1,7,2,9,10,8};
        mergeSort(array,0,array.length-1);
        for(int i=0;i<array.length;i++){
        System.out.print(array[i]+" ");
        }
    }
    private static void mergeSort(int[] array,int left,int right) {  //歸併排序
    	if (left >= right) return; 
		int mid=(left+right)/2;
		System.out.println("mid = "+mid);
		mergeSort(array,left,mid);                //對左半邊二分
		mergeSort(array,mid+1,right);             //對右半邊二分
		merge(array,left,mid,mid+1,right);	  //左右合併
	}
    private static int[] merge(int[] array,int leftS,int leftE,int rightS,int rightE) {  //歸併排序
    	System.out.println("sort "+"leftS="+leftS+" leftE="+leftE+" to "+"rightS="+rightS+ "rightE="+rightE);
    	int[] temp = new int[rightE-leftS+ 1]; 
    	int i=leftS;
    	int j=rightS;
    	int k=0;
    	while(i<=leftE&&j<=rightE){
    		if(array[i]<array[j]){
    			temp[k++] = array[i++];  
    		}
    		else{
    			temp[k++] = array[j++];
    		}
    	}
    	while (i <= leftE) { 
			  temp[k++] = array[i++]; 
			 } 
	    while (j <= rightE) { 
			  temp[k++] = array[j++]; 
			 }
    	 k = leftS; 
    	 // 將臨時數組中的內容拷貝回原數組中 // (原left-right範圍的內容被複制回原數組) 
    	 for (int element : temp) { 
    	  array[k++] = element; 
    	  System.out.println("element = "+element);
    	 } 
    	 for(int z=0;z<array.length;z++){
    	        System.out.print(array[z]+" ");
    	        }
    	 System.out.println(000);
		return array;
	}
}

時間複雜度無論是在最好情況下還是在最壞情況下均是O(nlgn),開闢了一個temp空間去暫存數組,所以空間複雜度爲O(n)。


6、快速排序

每次選擇數組的第一個數爲基準數,與後面的數比較,大的放基準數後面,小的放前面。具體實現是設定一個low和high,從高位開始與基準比較,小的話將array[high]與基準數交換,然後從array[low]開始比較,大於基準數的話就和array[high]交換。這樣運行到low=high時,基準數被交換到了array[low],對左右數組array[l],array[low-1],繼續遞歸進行排序。

public class quickSort {
    public static void main(String[] args) {
        int[] array={6,3,4,5,1,7,2,9,10,8};
        quickSort(array,0,array.length-1);
        for(int i=0;i<array.length;i++){
        System.out.print(array[i]+" ");
        }
    }
    private static void quickSort(int[] array, int l, int h) {
    	int low =l;
    	int high=h;
		int target=array[low];
		while(low<high){
			while(low<high&&array[high]>target){
				high--;
			}
			if(array[high]<target){
				int temp = array[low];
				array[low]=array[high];
				array[high]=temp;
				low++;
			}
			while(low<high&&array[low]<target){
				low++;
			}
			if(array[low]>target){
				int temp = array[low];
				array[low]=array[high];
				array[high]=temp;
				high--;
			}
		}
		//當low==high時,本次排序結束,對low前後各半邊再排序
		if(low>l) quickSort(array,l,low-1);
		if(high<h) quickSort(array,high+1,h);
	}
}
平均時間複雜度爲O(nlogn),最差爲O(n²)

7、堆排序

堆頂元素爲最大,左右孩子節點都小於父節點。每次調整時比較孩子節點和父節點,將最大值放在父節點。

(1)構建大根堆

(2)堆頂元素放到最後

(3)對剩下元素重新構建大根堆

(4)重複(2)(3)步直到全部輸出

public class HeapSort {  
    public static void main(String[] args) {  
        int[] array = {6,3,4,5,1,7,2,9,10,8};  
        System.out.println("Before heap:");  
        printArray(array);  
        heapSort(array);  
        System.out.println("After heap sort:");  
        printArray(array);  
    } 
    public static void printArray(int[] array) {  
        System.out.print("{");  
        for (int i = 0; i < array.length; i++) {  
            System.out.print(array[i]);  
            if (i < array.length - 1) {  
                System.out.print(", ");  
            }  
        }  
        System.out.println("}");  
    }  

    public static void exchangeElements(int[] array, int index1, int index2) {  
        int temp = array[index1];  
        array[index1] = array[index2];  
        array[index2] = temp;  
    }  
    public static void heapSort(int[] array) {  
        if (array == null || array.length <= 1) {  
            return;  
        }  
        buildMaxHeap(array);  
        for (int i = array.length - 1; i >= 1; i--) {  
            exchangeElements(array, 0, i);  
            maxHeap(array, i, 0);  
        }  
    }  
    private static void buildMaxHeap(int[] array) {  
        if (array == null || array.length <= 1) {  
            return;  
        }  
        int half = array.length / 2;  
        for (int i = half; i >= 0; i--) {  
            maxHeap(array, array.length, i);  
        }  
    }  
    private static void maxHeap(int[] array, int heapSize, int index) {  
        int left = index * 2 + 1;  
        int right = index * 2 + 2;  
        int largest = index;  
        if (left < heapSize && array[left] > array[index]) {  
            largest = left;  
        }  
        if (right < heapSize && array[right] > array[largest]) {  
            largest = right;  
        }  
        if (index != largest) {  
            exchangeElements(array, index, largest);  
            maxHeap(array, heapSize, largest);  
        }  
    }  
} 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章