排序算法

几个经典排序算法自己手写一下练习练习

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);  
        }  
    }  
} 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值