zoukankan      html  css  js  c++  java
  • 八种常见排序算法:插入、冒泡、选择、希尔、归并、快排、堆排序、基数排序

    package com.algorithm;
    
    import java.util.Random;
    
    /**
     * 八种常见排序算法:插入、冒泡、选择、希尔、归并、快排、堆排序、基数排序
     * @author Wennian
     *
     */
    
    public class Sort {
    
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		// 构建初始化乱序数组,采用随机数的方式,生成整数(正数、0、负数)
    		int N = 100;
    		int[] arr = new int[N];
    		for(int i=0;i<N;i++){
    			// 随机生成0-N-1的数,其中1/10的数为负数
    			arr[i] = new Random().nextInt(N) - N/10;
    		}
    		Sort sort = new Sort();
    		//sort.BubbleSort(arr);
    		//sort.InserSort(arr);
    		//sort.SelectSort(arr);
    		//sort.SheelSort(arr);
    		//sort.QuickSort(arr);
    		//sort.mergeSort(arr);
    		sort.heapSort(arr);
    		for(int i=0;i<N;i++){
    			System.out.print(arr[i]+" ");
    			if(i%10 == 0 && i>0){
    				System.out.println();
    			}
    		}
    		
    	}
    	
    	/**
    	 * 冒泡排序:一组数,每次把最大的数往后沉
    	 * 时间复杂度:o(n^2) 空间复杂度:o(1)
    	 * 稳定
    	 */
    	void BubbleSort(int[] arr){
    		int len = arr.length;
    		int end = len-1; // 初始时,结束位置为数组末尾
    		int start = 0;   // 每次从第一个元素开始往后遍历
    		
    		// 一共需要len趟才能排序完成
    		for(int i=0;i<len;i++){
    			start = 0;
    			while(start < end){
    				if(arr[start]>arr[start+1]){
    					arr[start] ^= arr[start+1];
    					arr[start+1] ^= arr[start];
    					arr[start] ^= arr[start+1];
    				}
    				start++;
    			}
    			end--; //每趟排序之后,待排数组长度减1
    		}
    	}
    	
    	/**
    	 * 插入排序:认为前面的数组已经有序,每次向原来的数组中插入一个数
    	 * 时间复杂度o(n^2) 空间复杂度o(1)
    	 * 稳定
    	 * @param arr
    	 */
    	void InserSort(int[] arr){
    		int len = arr.length;
    		int end = 0; // 已经排序好的数组
    		int start = end+1; // 下一个要插入的元素
    		while(start<=len-1){
    			for(int i = end;i>=0;i--){
    				if(arr[i+1]<arr[i]){
    					arr[i+1] ^= arr[i];
    					arr[i] ^= arr[i+1];
    					arr[i+1] ^= arr[i];
    				}else{
    					break;
    				}
    			}
    			end = start;
    			start++;
    		}
    	}
    	
    	/**
    	 * 选择排序:有序区和无序区,有序区的元素小于无序区,每次选择无需去的最小元素放在有序区后面
    	 * 时间复杂度o(n^2) 空间复杂度o(1)
    	 * 稳定
    	 */
    	void SelectSort(int[] arr){
    		int len = arr.length;
    		int start = 0; // 无序区的第一个元素,认为他是最小值
    		while(start < len){			
    			for(int i=start+1;i<len;i++){
    				if(arr[start]>arr[i]){
    					arr[start] ^= arr[i];
    					arr[i] ^= arr[start];
    					arr[start] ^= arr[i];
    				}
    			}
    			start++;
    		}
    	}
    	
    	/**
    	 * 希尔排序:缩小增量排序,每次缩小增量gap,间隔gap的数为一个子序列,
    	 * 依次缩小增量,直到gap=1,对每个子序列采用直接选择排序
    	 * 时间复杂度o(nlogn)~o(n^2) 空间复杂度 o(1)
    	 * 不稳定
    	 */
    	void SheelSort(int[] arr){
    		int len = arr.length;
    		
    		// gap选择为奇数,gap的选择直接影响排序的效率
    		// 若选择偶数,gap=4会重复gap=8的排序比较,时间浪费
    		for(int gap=len/2+1;gap>0;gap/=2){
    			//对子序列进行直接选择排序,一共有gap个子序列
    			for(int subarr=0;subarr<gap;subarr++){
    				int start = subarr;
    				// 直接选择排序
    				while(start<len){
    					for(int i=start+gap;i<len;i+=gap){
    						if(arr[start]>arr[i]){
    							arr[start] ^= arr[i];
    							arr[i] ^= arr[start];
    							arr[start] ^= arr[i];
    						}
    					}
    					start +=gap;
    				}
    				
    			}
    			
    		}
    	}
    	
    	/**
    	 * 快序排序:每次找到一个分割值,满足:左边<=分割值<=右边,重复此过程直到有序
    	 * 时间复杂度o(nlogn) 空间复杂度o(1)
    	 * 不稳定
    	 * @param arr
    	 */
    	void QuickSort(int[] arr){
    		int len =arr.length;
    		int left = 0 ;
    		int right = len-1;
    		quickSort(arr,left,right);
    	}
    	void quickSort(int[] arr ,int left,int right){
    		if(left < right){
    			int split = arr[left];
    			int index1 = left, index2 = right;
    			while(index1<index2){
    				while(arr[index2]>=split && index1<index2){
    					index2--;
    				}
    				if(index1<index2)
    					arr[index1++] = arr[index2];
    				
    				while(arr[index1]<=split && index1<index2){
    					index1++;
    				}
    				if(index1<index2)
    					arr[index2--] = arr[index1];
    			}
    			arr[index1] = split;
    			
    			// 递归调用
    			quickSort(arr,left,index1);
    			quickSort(arr,index1+1,right);
    		}
    		
    	}
    	
    	
    	/**
    	 * 归并排序:将数组分为子数组,认为每一个子数组已经有序,对两个有序数组进行归并
    	 * 时间复杂度o(nlogn) 空间复杂度o(n)
    	 * 稳定
    	 */	
    	void mergeSort(int[] arr){
    		int len = arr.length;
    		if(len<=0)
    			return;
    		divideArray(arr,0,len-1);
    	}
    	void divideArray(int[] arr,int left,int right){
    		if(left < right){
    			int mid = left + (right - left)/2;
    			// 分解
    			divideArray(arr,left,mid);
    			divideArray(arr,mid+1,right);
    			// 合并
    			mergeArray(arr,left,mid,right);
    		}
    	}
    	void mergeArray(int[] arr,int left,int mid,int right){
    		// 合并两个有序子数组arr[left..mid] arr[mid+1..right]
    		int i=left,m=mid,j=mid+1,n=right;
    		int[] tmp = new int[right-left+1];
    		int k=0;
    		while(i<=m && j<=n){
    			if(arr[i]<=arr[j])
    				tmp[k++] = arr[i++];
    			else
    				tmp[k++] = arr[j++];			
    		}
    		while(i<=m)
    			tmp[k++] = arr[i++];
    		while(j<=n)
    			tmp[k++] = arr[j++];
    		
    		// copy tmp to arr
    		for(int t=0;t<k;t++)
    			arr[left+t] = tmp[t];		
    	}
    	
    	/**
    	 * 堆排序:大根堆,每次取堆顶元素,将堆顶元素与最后一个值交换,然后调整堆依次
    	 *      整个过程相当于一个不断建堆的过程
    	 * 时间复杂度o(nlogn) 空间复杂度o(1)
    	 * 不稳定
    	 */
    	void heapSort(int[] arr){
    		// 将初始数组看做已经建好的堆,调整堆
    		// parent:i child:2i+1 2i+2
    		// 从第一个非叶子节点往上调整
    		int len = arr.length;
    		int last = len-1;
    		while(last >= 0){
    			// 调整堆,将最大值放在堆顶,即第一个元素			
    			for(int p=(last-1)/2;p>=0;p--){
    				int cur = p;
    				// 只有第一次需要建立堆,其他时候只要从根节点开始调整堆即可
    				if(last != len-1){
    					cur = 0;
    					p = 0;
    				}
    				
    				while(cur <= (last-1)/2){
    					int child = 2*cur+1;
    					if(child<last-1 && arr[child] < arr[child+1])
    						child += 1;
    					if(arr[cur] < arr[child]){
    						arr[cur] ^= arr[child];
    						arr[child] ^= arr[cur];
    						arr[cur] ^= arr[child];
    					}
    					cur = child;
    				}
    			}	
    			
    			// 交换堆顶元素和最后一个元素
    			if(arr[0] != arr[last]){
    				arr[last] ^= arr[0];
    				arr[0] ^= arr[last];
    				arr[last] ^= arr[0];
    			}
    					
    			last--;
    		}
    		
    		
    	}
    	
    }
    

  • 相关阅读:
    vs错误集合及解决方案
    使用内存映射文件进行EXE、DLL通信(非MFC)
    visual studio使用小技巧(以vs2012为例)
    GetModuleHandle(NULL)获取当前DLL模块基址?
    格式化输出中的%s和%S的陷阱
    关于字符编码
    远程附加调试服务的方法
    结构体内包含位段,其数据内存分布
    微信个人公众号开发-java
    Docker-常用基建的安装与部署
  • 原文地址:https://www.cnblogs.com/wennian/p/5036878.html
Copyright © 2011-2022 走看看