zoukankan      html  css  js  c++  java
  • 常见排序算法总结(java实现)

    所谓排序。就是使一串记录,依照当中的某个或某些keyword的大小。递增或递减的排列起来的操作。

    常见的排序算法有选择排序,插入排序,希尔排序,归并排序和高速排序

    因为在排序的过程中不可避免的要涉及到比較和交换,所以将他们抽取为两个单独的函数,例如以下所看到的

    //为了排序代码的通用性,这里假定待排序的元素实现了Comparable接口
    	private static boolean less(Comparable v ,Comparable w){
    			return v.compareTo(w)<0;
    	}
    	private static void exch(Comparable[] a ,int i,int j){
    		Comparable t = a[i];a[i] = a[j]; a[j] = t;
    	}

    选择排序

    算法思想:首先。找到数组中最小的那个元素。然后将其和数组中第一个元素交换位置。

    再从剩下的元素中找到最小的元素。将其和数组中的第二个元素交换位置,如此这般,直到整个数组所有有序。

    算法特点:1.执行时间和输入无关。无论输入的数据是一个已经有序的数组,或者是一个随机的数组,其所须要的比較次数是一样的。

    2.数组的移动是最少的。

    因为每一次都是选择一个最小的元素然后交换其位置。所以每次交换都能排定一个元素,因此总的交换次数是N。

    	public static void selectionSort(Comparable[] a){
    		int N= a.length;
    		for(int i=0;i<N;i++){
    			int min =i;			//假定第一个数为最小
    			for(int j=i+1;j<N;j++)
    				if(less(a[j],a[min]))
    					min = j;	//获取最小元素的下标
    			exch(a,i,min);		//交换位置
    		}
    	}

    插入排序

    算法思想:首先。假定数组中第一个元素是有序的,然后将第二个元素插入到前面有序数组的合适位置,组成一个新的有序数组,再将第三个元素插入到前面的有序数组中,如此这般,知道数组总体有序。

    算法特点:执行时间和初始输入有关。假设初始输入的数据已经有序或者部分有序的时候。插入排序的性能会比較好。

    	public static void insertionSort(Comparable[] a){
    		int N = a.length;
    		for(int i=1;i<N;i++){	//待插入的元素下标
    			for(int j=i;j>0;j--)	//在前面有序的数组中寻找合适的插入位置
    				if(less(a[j],a[j-1]))
    					exch(a, j, j-1);
    		}
    	}

    希尔排序

    算法思想:希尔排序的思想是使数组中随意间隔为h的元素都是有序的,这种数组被称之为h-有序数组。我们不断降低h的值,使其终于变为一个1-有序数组。

    1-有序数组,也就是数组总体有序,这样排序就算完毕了。

    希尔排序最难的地方在于h序列的选择。眼下还没有方法证明某一种序列是最好的。

    public static void sort(Comparable[] a){
    		int N = a.length;
    		int h = 1;		//用来记录步长
    		while(h<N/3)	h=3*h+1;	//步长为1,4,13,40……
    		while(h>=1){
    			for(int i=h;i<N;i++)
    				for(int j=i;j>=h;j-=h)	//将a[i]插入到a[i-h],a[i-2*h],a[i-3*h]……之中
    					if(less(a[j],a[j-h]))
    						exch(a,j,j-h);
    			h=h/3;	//将前面记录的步长反过来。终于使其为1-有序数组
    		}
    	}

    归并排序

    算法思想:要将一个数组进行排序,能够递归的将其分为两半分别进行排序,最后将结果归并起来,使其总体有序。

    归并排序基于算法设计中的分治思想。我们将一个大问题分解成小问题分别解决。然后用全部小问题的答案来解决整个大问题。

    算法特点:1.随意长度为N的数组排序所需的时间和NlogN成正比。

    这个能够通过归并排序的排序树得到

    2.它所须要的额外空间和N成正比。由于归并过程中须要一个长度为N的辅助数组。

    private static Comparable[] temp;	//辅助数组。定义为类的成员变量
    	public static void mergeSort(Comparable[] a){
    		temp = new Comparable[a.length];
    		sort(a,0,a.length-1);
    	}
    	//将数组a[lo..hi]进行排序
    	private static void sort(Comparable[] a,int lo ,int hi){
    		if(lo>=hi) return;
    		int mid = lo+(hi-lo)/2;
    		sort(a,lo,mid);//递归的对左边进行排序
    		sort(a,mid+1,hi);	//递归的对右边进行排序
    		merge(a,lo,mid,hi); //合并左右两边
    	}
    	//将两个有序的数组a[lo..mid]和a[mid+1..hi]合并为一个有序的数组,用到一个辅助数组temp
    	public static void merge(Comparable[] a,int lo,int mid,int hi){
    		int i=lo,j=mid+1;
    		for(int k=lo;k<=hi;k++)		//将数组a拷贝到辅助数组temp中
    			temp[k] = a[k];
    		for(int k=lo;k<=hi;k++)
    			if(i>mid) a[k]=temp[j++];	//左半边取尽,直接复制右半边剩余的元素到数组中
    			else if(j>hi)	a[k] = temp[i++];	//右半边取尽,直接复制左半边剩余的元素到数组中
    			else if(less(temp[j],temp[i])) a[k]=temp[j++]; //右半边的当前元素比左半边的当前元素小,取右半边
    			else	a[k]=temp[i++];		//左半边的当前元素比右半边的当前元素小,取左半边
    	}

    高速排序

    算法思想:高速排序是一种基于分治的排序算法。

    它通过一种划分,将一个数组划分为两个字数组。并将两个字数组独立的进行排序。

    public static void sort(Comparable[] a){
    		sort(a,0,a.length-1);
    	}
    	private static void sort(Comparable[] a,int lo, int hi){
    		if(hi<=lo) return ;
    		int j = partition(a, lo, hi);	//切分
    		sort(a,lo,j-1);					//左半部分排序	
    		sort(a,j+1,hi);					//右半部分排序 
    	}
    	private static int partition(Comparable[] a,int lo,int hi){
    		int i=lo,j=hi+1;				//左右扫描指针
    		Comparable v = a[lo];			//切分元素。该元素完毕切分后位置将固定并返回
    		while(true){					//循环扫描左右指针
    			while(less(a[++i],v)) if(i==hi) break;
    			while(less(v,a[--j]))	if(j==lo) break;
    			if(i>=j) break;
    			exch(a,i,j);
    		}
    		exch(a,lo,j);					//将v=a[j]放入正确位置
    		return j;					//返回切分元素所在的位置
    	}

    在待排序的文件里,若存在多个keyword同样的记录,经过排序后这些具有同样keyword的记录之间的相对次序保持不变,该排序方法是稳定的。若具有同样keyword的记录之间的相对次序发生改变,则称这样的排序方法是不稳定的。


    排序法

     平均时间

    最差情形

    稳定度

    额外空间

    备注

    选择

     O(n2)

     O(n2)

    不稳定

    O(1)

    n小时较好

    插入

     O(n2)

     O(n2)

    稳定

    O(1)

    大部分已排序时较好

    Shell

    O(nlogn)

    O(ns) 1<s<2

    不稳定

    O(1)

    s是所选分组

    高速

    O(nlogn)

    O(n2)

    不稳定

    O(nlogn)

    n大时较好

    归并

    O(nlogn)

    O(nlogn)

    稳定

    O(1)

    n大时较好


    本算法过程仅仅注重实现,并没实用栈等机制消除递归,

    完整程序下载地址:http://download.csdn.net/detail/danchu/7276229

  • 相关阅读:
    Android常用开发工具的用法
    搭建Android开发环境
    开篇 Android系统的体系结构
    学习安卓笔记
    C# DllImport用法和路径问题
    jq 实现无限级地区联动 样式为bootstrap
    YII2 日志
    centos6.5 lamp 环境 使用yum安装方法
    mysql 时间戳 按周、日、月 统计方法 附 date格式
    Yii2.0中文开发向导——控制器(Controller)
  • 原文地址:https://www.cnblogs.com/wgwyanfs/p/6756857.html
Copyright © 2011-2022 走看看