zoukankan      html  css  js  c++  java
  • 算法之七种排序

    插入排序

    public static void insertSort(int[] t){
    		for(int i=1; i<t.length; i++){
    			//将第i个数提取出来
    			int temp = t[i];
    			int j;
    			for(j=i-1; j>=0 && temp<t[j]; j--){
    				//假设提取出来的那个数小于t[j],数据里面的数就往后移。
    				t[j+1] = t[j];
    			}
    			//提取出来的数大于或等于t[j]。就插入到t[j]的后一个位置上(即t[j+1])
    			t[j+1] = temp;
    			
    		}
    	}
    

        时间复杂度:最好情况为O(n);   最坏情况为:O(n^2),是稳定的。


    希尔排序

    public static void shellSort(int[] t){
    		//不断缩小比較数据之间的位置,直到变成插入排序
    		for(int delta=t.length/2; delta>0; delta/=2){
    			//原理和插入排序一样,
    			//仅仅是将1换成delta而已
    			for(int i=delta; i<t.length; i++){
    				int temp=t[i];
    				int j;
    				for(j=i-delta; j>=0 && temp<t[j]; j-=delta){
    					t[j+delta] = t[j];
    				}
    				t[j+delta] = temp;
    			}
    		}
    	}

        基本思想是分组的直接插入排序。时间复杂度为:O(n(㏒2n)²)。那个2是指下标的2(下同),是不稳定的。


    冒泡排序

    public static void bubbleSort(int[] t){
    		//是否交换的标记
    		boolean exchange = true;
    		//每循环一次,就会得到一个最大值
    		for(int i=1; i<t.length && exchange; i++){
    			exchange = false;			
    			for(int j=0; j<t.length-i; j++){
    				if(t[j]>t[j+1]){
    					int temp = t[j+1];
    					t[j+1] = t[j];
    					t[j] = temp;
    					exchange = true;
    				}
    				
    			}
    			
    		}
    	}

        基本思想是:比較相邻两个元素的keyword值,假设反序。则交换。

    假设按升序排序,每一趟将被扫描的数据序列中的最大元素交换到最后位置。就像气泡从水里冒出一样。

        时间复杂度:最好情况:O(n)。   最坏情况:O(n²),是稳定的


    高速排序

    	public static void quickSort(int[] t){
    		quickSort(t,0,t.length-1);
    	}
    
    	private static void quickSort(int[] t, int begin, int end) {
    		//推断序列是否有效
    		if(begin<end){			
    			int i=begin, j=end;
    			//提取基准值
    			int vot = t[i];
    			while(i!=j){
    				//从后面寻找较小值
    				while(i<j && vot <= t[j]){
    					j--;
    				}
    				if(i<j){
    					//较小值往前移动
    					t[i++] = t[j];
    				}
    				//从前面寻找较大值
    				while(i<j && t[i]<=vot){
    					i++;
    				}
    				if(i<j){
    					//较大值往后移动
    					t[j--] = t[i];
    				}
    			}
    			//确定基准值的位置
    			t[i]=vot;
    			//前端子序列在排序,递归调用
    			quickSort(t,begin,j-1);
    			//后端子序列在排序,递归调用
    			quickSort(t,i+1,end);
    			
    		}
    		
    	}

        基本思想是:在数据序列中选择一个值作为比較的基准值。每趟从数据序列的两端開始交替进行,将小于基准值的元素交换到序列前端,将大于基准值的元素交换到序列后端。介于两者之间的位置则成为基准值的终于位置。

    同一时候,序列被划分成两个子序列。再用相同的方法分别对两个子序列进行排序。直到子序列的长度为1,则完毕排序。

        时间复杂度:最好的情况:O(n*㏒2n);   最坏的情况:O(n²);是不稳定的。



    直接选择排序

    	public static void selectSort(int[] t){
    		for(int i=0; i<t.length-1; i++){
    			//标记最小值的位标
    			int min=i;
    			//遍历寻找最小值
    			for(int j=i+1; j<t.length; j++){
    				if(t[j]<t[min]){
    					min=j;
    				}
    			}
    			//将最小值交换到前面
    			if(min!=i){
    				int temp = t[i];
    				t[i] = t[min];
    				t[min] = temp;
    			}
    		}
    	}

        基本思想:第一趟从n个元素的数据序列中选出keyword最小(或最大)的元素并放到最前(或最后)位置,下一趟再从n-1个元素中选出最小(大)的元素并放到次前(后)位置。以此类推,经过n-1趟完毕排序。
        时间复杂度:最好情况:O(n²);    最坏情况:O(n²);    是不稳定的。


    堆排序

    	//将以begin为根的子树调整成最小堆
    	private static void sift(int[] t,int begin, int end){
    		//j为i结点的左孩子
    		int i=begin, j=2*i+1;
    		//子树根节点的值
    		int temp=t[i];
    		while(j<=end){
    			//比較左右孩子。将j定位到最小那个
    			if(j<end && t[j]>t[j+1]){
    				j++;
    			}
    			if(temp>t[j]){
    				//若子树根节点的值较大,
    				//较小的孩子结点上移
    				t[i]=t[j];	
    				//使i,j向下一层
    				i=j;
    				j=2*i+1;
    			}else{
    				break;
    			}
    		}
    		//当前子树的原根值调整后的位置
    		t[i]=temp;
    	}
    	
    	public static void heapSort(int[] t){
    		int n=t.length;
    		//创建最小堆
    		for(int j=n/2-1; j>=0; j--){
    			sift(t,j,n-1);
    		}
    		//每趟将最小值交换到后面。再调整成堆
    		for(int j=n-1; j>0; j--){
    			int temp = t[0];
    			t[0] = t[j];
    			t[j] = temp;
    			sift(t,0,j-1);
    		}
    	}

        基本思想:首先和直接选择排序对照一下。在直接选择排序中。每趟从数据序列中选出一个最小值交换到前面,其余n-1个元素原地不动,下一趟须要再次比較这些元素,因此直接选择排序算法的反复比較非常多。假设每趟可以利用前一趟的比較结果,则会降低一些反复比較,从而提高算法效率。

    堆排序就是利用全然二叉树的特性,每趟仅仅需遍历树中的一条路径即可了。而不是所有元素。

        时间复杂度:最好最坏情况都是:O(n*㏒2n)。    是不稳定的。


    归并排序

    	//对子序列元素的操作,
    	//m和r各自是相邻的两个已排序子序列的起始下标,
    	//n为子序列的长度
    	private static void merge(int[] X, int[] Y, int m, int r, int n){
    		int i=m, j=r, k=m;
    		//将X中两个相邻子序列归并到Y中
    		while(i<r && j<r+n && j<X.length){
    			if(X[i] < X[j]){
    				//将较小值拷贝到Y中
    				Y[k++] = X[i++];
    			}else{
    				Y[k++] = X[j++];
    			}
    		}
    		//将前一个子序列剩余元素拷贝到Y中
    		while(i<r){
    			Y[k++] = X[i++];
    		}
    		//将后一个子序列剩余元素拷贝到Y中
    		while(j<r+n && j<X.length){
    			Y[k++] = X[j++];
    		}
    	}
    	
    	
    	//对子序列的操作
    	private static void mergepass(int[] X, int[] Y, int n){
    		int i = 0;
    		
    		while(i < X.length-n*2+1){
    			merge(X, Y, i, i+n, n);
    			i += 2*n;
    		}
    		//对于剩余不够2n的子序列的操作
    		if(i+n < X.length){
    			//虽然后一个子序列长度不够n。
    			//但还是能够再来一次merge
    			merge(X, Y, i, i+n, n);
    			
    		}else{
    			for(int j=i; j<X.length; j++){
    				Y[j]=X[j];
    			}
    			
    		}
    		
    	}
    	
    	//对数组的操作
    	public static void mergeSort(int[] X){
    		int[] Y = new int[X.length];
    		int n = 1;
    		//一次while循环完毕两趟并归,
    		//数据序列从X到Y,再从Y到X,
    		//使排序后的数据序列仍在数组X中
    		while(n<X.length){
    			mergepass(X,Y,n);
    			n*=2;
    
    			mergepass(Y,X,n);
    			n*=2;
    		}
    	}

        基本思想:n个元素的数据序列可看成是由n个长度为1的排序子序列组成,重复讲相邻的两个子序列归并成一个排序的子序列,直到合并成一个序列,则排序完毕。
        时间复杂度:最好最坏的情况都是:O(n*㏒2n)。    是稳定的。



    測试方法

    public static void main(String[] args) {
    		//创建一个数组
    		int[] y = new int[10];
    		//向数组赋值
    		for(int i=0; i<y.length; i++){
    			int a = new Random().nextInt(100);
    			y[i] = a;
    		}
    		//运行排序方法
    		selectSort(y);
    		//打印排序后的数组
    		for(int i=0; i<y.length; i++){
    			System.out.println(y[i]);
    		}
    	}


        假设读者有什么更好的建议或疑问,欢迎在以下评论,一起交流进步。

    微笑







  • 相关阅读:
    用外部表的方式查询当天数据库alert日志文件
    比较数据泵和exp/imp对相同数据导出/导入的性能差异
    理解Oracle TM和TX锁
    Rocky4.2下安装金仓v7数据库(KingbaseES)
    理解listagg函数
    sql*loader的直接加载方式和传统加载方式的性能差异
    Rocky4.2下安装达梦(DM)6数据库
    演示对sys用户和普通用户进行审计的示例
    演示一个通过触发器进行审计的示例
    演示一个使用db vault进行安全控制的示例
  • 原文地址:https://www.cnblogs.com/jzssuanfa/p/6804005.html
Copyright © 2011-2022 走看看