欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

经典排序算法java实现 排序算法java选择排序快速排序归并排序 

程序员文章站 2022-07-14 09:45:48
...

最近亲测了六种排序算法:1.插入排序、2.冒泡排序、3.选择排序、4.快速排序、5.归并排序、6.希尔排序

直接上代码:

 

package xl.com;

public class Sort {	
	/**
	 * 时间复杂度:
	 * 
	 * 1.时间频度:是指 一个算法执行所耗费的时间,从理论上是不能算出来的,必须上机运行测试才能知道。但我们不可能也没有必要对每个算法都上机测试,只需知道哪个算法
	 * 			      花费的时间多,哪个算法花费的时间少就可以了。并且一个算法花费的时间与算法中语句的执行次数成正比例,哪个算法中语句执行次数多,它花费时间就多。
	 * 			      一个算法中的语句执行次数称为语句频度或时间频度。记为T(n)。 
	 * 2.时间复杂度: 在刚才提到的时间频度中,n称为问题的规模,当n不断变化时,时间频度T(n)也会不断变化。但有时我们想知道它变化时呈现什么规律。为此,我们引入时间
	 * 				  复杂度概念。 一般情况下,算法中基本操作重复执行的次数是问题规模n的某个函数,用T(n)表示,若有某个辅助函数f(n),使得当n趋近于无穷大时,
	 * 				 T(n)/f(n)的极限值为不等于零的常数,则称f(n)是T(n)的同数量级函数。记作T(n)=O(f(n)),称O(f(n)) 为算法的渐进时间复杂度,简称时间复杂度。 
	 */
	
	/**
	 * 空间复杂度:
	 * 
	 * 		类似于时间复杂度的讨论,一个算法的空间复杂度(Space Complexity)S(n)定义为该算法所耗费的存储空间,
	 * 		它也是问题规模n的函数。空间复杂度(Space Complexity)是对一个算法在运行过程中临时占用存储空间大小的量度。一个算法在计算机存储器上所占用的存储空间,
	 * 		包括存储算法本身所占用的存储空间,算法的输入输出数据所占用的存储空间和算法在运行过程中临时占用的存储空间这三个方面。
	 * 		算法的输入输出数据所占用的存储空间是由要解决的问题决定的,是通过参数表由调用函数传递而来的,它不随本算法的不同而改变。
	 * 		存储算法本身所占用的存储空间与算法书写的长短成正比,要压缩这方面的存储空间,就必须编写出较短的算法。
	 * 		算法在运行过程中临时占用的存储空间随算法的不同而异,有的算法只需要占用少量的临时工作单元,而且不随问题规模的大小而改变,
	 * 		我们称这种算法是“就地/"进行的,是节省存储的算法,如这一节介绍过的几个算法都是如此;有的算法需要占用的临时工作单元数与解决问题的规模n有关,
	 * 		它随着n的增大而增大,当n较大时,将占用较多的存储单元,例如将在第九章介绍的快速排序和归并排序算法就属于这种情况。
	 */
	
	/**
	 * 插入排序
	 * 基本思想:每次将无序区中第一个元素与有序区中的元素进行比较,放入恰当的位置
	 * 时间复杂度:O(n2)
	 * 稳定性:稳定
	 * @param data
	 * @return
	 */
	public void insertSort(int[] data){
		for(int index=1;index<data.length;index++){
			int currPosition;
			currPosition=index;
			int key=data[index];
			while(currPosition>0&&data[currPosition-1]>key){
				data[currPosition]=data[currPosition-1];
				currPosition--;
			}
			data[currPosition]=key;
		}
	}
	
	/**
	 * 冒泡排序
	 * 基本思想:每次比较相邻两个元素大小,将大的往后移,每次能都将最大的元素放到最后面
	 * 时间复杂度:O(n2)
	 * 稳定性:稳定
	 * @param data
	 */
	public void bubbleSort(int[] data){
		for(int i=data.length-1;i>1;i--){
			for(int j=0;j<i;j++){
				if(data[j]>data[j+1]){
					int temp=data[j];
					data[j]=data[j+1];
					data[j+1]=temp;
				}
			}
		}
	}
	
	/**
	 * 选择排序
	 * 基本思想:每次选择未排序序列中的最小元素放在已排序序列后面。关键是找到最小元素即可
	 * 时间复杂度:O(n2)
	 * 稳定性:稳定
	 * @param data
	 */
	public void selectSort(int[] data){
		for(int i=0;i<data.length-1;i++){
			int min=i;
			for(int j=i;j<data.length-1;j++){//在data[j,data.length-1]中将data[j]看做是最小值
				if(data[j]<data[min]){
					min=j;
				}
			}
			if(min!=i){
				int temp=data[i];
				data[i]=data[min];
				data[min]=temp;
			}
		}
	}
	
	/**
	 * 快速排序
	 * 基本排序:每次排序将选择的基准元素放在准确位置,使得左边是小于它的元素,右边是大于它的元素。再进行递归
	 * 时间复杂度:O(nlogn)
	 * 稳定性:不稳定
	 * @param data
	 * @param start
	 * @param end
	 */
	public void quickSort(int[] data,int low,int high){		
        if(low<high){ 
            int middle = getMiddle(data,low,high);
            quickSort(data, 0, middle-1);
            quickSort(data, middle+1, high);
        }
	}

	private static int getMiddle(int[] data, int low, int high) {
        int temp = data[low];//基准元素
        while(low<high){
            //找到比基准元素小的元素位置
            while(low<high && data[high]>=temp){
                high--;
            }
            data[low] = data[high]; 
            while(low<high && data[low]<=temp){
                low++;
            }
            data[high] = data[low];
        }
        data[low] = temp;
        return low;
	}
	
	/**
	 * 归并排序
	 * 基本思想:将要排序的序列一分为二,二分为四进行递归,最后再合并。
	 * 时间复杂度:O(nlogn) 
     * 稳定性:稳定 
	 * @param data
	 * @param left
	 * @param right
	 */
	public void mergeSort(int[] data,int low,int high){
		int mid=(high+low)/2;
		if(low<high){
			mergeSort(data,low,mid);
			mergeSort(data,mid+1,high);
			merge(data,low,mid,high);
		}
	}
	public void merge(int[] data,int low,int mid,int high){//归并
		int[] temp=new int[high-low+1];               //用于中转的新的数组
		int i=low;//左指针
		int j=mid+1;//中指针
		int k=0;
		while(i<=mid&&j<=high){
			if(data[i]<=data[j]){                   //用于把小的数放入新的数组
				temp[k++]=data[i++];
			}else{
				temp[k++]=data[j++];
			}                                  //k用作新数组的小标标记
		}
		while(i<=mid){                                 //表示左边的数组元素全部移到了新数组中
			temp[k++]=data[i++];
		}
		while(j<=high){                                  //表示右边的数组元素全部移到了新数组中
			temp[k++]=data[j++];
		}
		for(int s=0;s<temp.length;s++){                      //再将新数组复制到原数组中
			data[s+low]=temp[s];
		}
	}
	
	/**
	 * 希尔排序
	 * 基本思想:是在普通插入排序的基础上进行改进。将要排序的序列分为gap组,对每组的元素进行插入排序.再减小gap的值直到为1
	 * 时间复杂度:与增量gap有关,下界是O(nlogn)
	 * 稳定性:不稳定
	 * @param data
	 */
	public void shellSort(int[] data){
		int size = data.length;  
	    for(int gap = size/2; gap>=1; gap /= 2) {  
	        for(int i=gap; i<size; i++) {  
	            int k;  
	            int temp = data[i];  
	            for(k = i-gap; k>=0 && data[k] > temp; k -= gap) {  
	                data[k+gap] = data[k];  
	            }  
	            data[k+gap] = temp;  
	        }  
	    }  
	}  
	/*************************************************************************************/
	/**
	 * 用来显示数组
	 * @param data
	 */
	public void showAfter(int[] data){
		String result="";
		for(int index=0;index<data.length;index++){
			result+=data[index];
			result+=",";
		}
		System.out.println("排序后:"+result);
	}
	public void showBefore(int[] data){
		String result="";
		for(int index=0;index<data.length;index++){
			result+=data[index];
			result+=",";
		}
		System.out.println("排序前:"+result);
	}
	/**
	 * 测试
	 * @param args
	 */
	public static void main(String[] args){
		Sort sort=new Sort();
		int[] dbl={8,1,2,5,4,3,9,6,4,4,4,8,9,99,77,55,66,3,5,12,12};
		sort.showBefore(dbl);
//		sort.insertSort(dbl);
//		sort.bubbleSort(dbl);
//		sort.selectSort(dbl);
//		sort.quickSort(dbl, 0, dbl.length-1);
//		sort.mergeSort(dbl, 0, dbl.length-1);
		sort.shellSort(dbl);
		sort.showAfter(dbl);
		
	}
}