排序算法(Java实现):Shell排序和归并排序

希尔排序,也称递减增量排序算法,是插入排序的一种高速而稳定的改进版本。

希尔排序是基于插入排序的以下两点性质而提出改进方法的:

  • 插入排序在对几乎已经排好序的数据操作时, 效率高, 即可以达到线性排序的效率
  • 但插入排序一般来说是低效的, 因为插入排序每次只能将数据移动一位
步长的选择是希尔排序的重要部分。只要最终步长为1任何步长序列都可以工作。算法最开始以一定的步长进行排序。然后会继续以一定步长进行排序,最终算法以步长为1进行排序。当步长为1时,算法变为插入排序,这就保证了数据一定会被排序。
一直较好的增量序列是2^k-1,2^(k-1)-1,.....7,3,1,这样可使Shell排序时间复杂度达到O(N^1.5)。
为了方便扩展,先引入一个抽象的基础类:
package com.andyidea.algorithms;

/**
 * 排序抽象基础类
 * @author Andy.Chen
 *
 * @param <T>
 */
public abstract class Sorter<T extends Comparable<T>> {
	
	public abstract void sort(T[] array,int from,int len);
	
	public final void sort(T[] array){
		sort(array,0,array.length);
	}
	
	protected final void swap(T[] array,int from,int to){
		T tmp = array[from];
		array[from] = array[to];
		array[to] = tmp;
	}

}
希尔(Shell)排序算法源码如下:
package com.andyidea.algorithms;

/**
 * 希尔(Shell)排序算法
 * @author Administrator
 *
 * @param <T>
 */
public class ShellSort<T extends Comparable<T>> extends Sorter<T> {

	@Override
	public void sort(T[] array, int from, int len) {
		int value =1;
		while((value+1)*2 < len){
			value = (value+1)*2 - 1;
		}
		
		for(int delta=value;delta<=1;delta=(delta+1)/2-1){
			for(int i=0;i<delta;i++){
				invokeInsertionSort(array,from,len,delta);
			}
		}
	}
	
    private final void invokeInsertionSort(T[] array,int from,int len,int delta){
		if(len<=1)
			return;
		 T tmp=null;
         for(int i=from+delta;i<from+len;i+=delta)
         {
             tmp=array[i];
             int j=i;
             for(;j>from;j-=delta)
             {
                 if(tmp.compareTo(array[j-delta])<0)
                 {
                     array[j]=array[j-delta];
                 }
                 else break;
             }
             array[j]=tmp;
         }
	}

}

归并排序,是建立在归并操作上的一种有效的排序算法。该算法是采用分治法的一个非常典型的应用。 也叫归并算法,指的是将两个已经排序的序列合并成一个序列的操作。归并排序算法依赖归并操作。

算法描述

归并操作的过程如下:

  1. 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
  2. 设定两个指针,最初位置分别为两个已经排序序列的起始位置
  3. 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
  4. 重复步骤3直到某一指针达到序列尾
  5. 将另一序列剩下的所有元素直接复制到合并序列尾
归并排序算法源码如下:
package com.andyidea.algorithms;

import java.lang.reflect.Array;

/**
 * 归并排序法
 * @author Andy.Chen
 *
 * @param <T>
 */
public class MergeSort<T extends Comparable<T>> extends Sorter<T> {

	@SuppressWarnings("unchecked")
	@Override
	public void sort(T[] array, int from, int len) {
		if(len<=1)
			return;
		T[] temp = (T[])Array.newInstance(array[0].getClass(), len);
		mergeSort(array, from, from+len-1, temp);
	}
	
	/**
	 * 分成两组排序
	 * @param array
	 * @param from
	 * @param to
	 * @param temporary
	 */
	private final void mergeSort(T[] array,int from,int to,T[] temporary){
		if(to<=from)
			return;
		int middle = (from+to)/2;
		mergeSort(array, from, middle, temporary);
		mergeSort(array, middle+1, to, temporary);
		merge(array, from, to, middle, temporary);
	}
	
	/**
	 * 把排序好的序列合并
	 * @param array
	 * @param from
	 * @param to
	 * @param middle
	 * @param temporary
	 */
	private final void merge(T[] array,int from,int to,int middle,T[] temporary){
		int k=0;
		int leftIndex=0;
		int rightIndex=to-from;
		System.arraycopy(array, from, temporary, 0, middle-from+1);
        for(int i=0;i<to-middle;i++){
            temporary[to-from-i]=array[middle+i+1];
        }
        
        while(k<to-from+1){
            if(temporary[leftIndex].compareTo(temporary[rightIndex])<0)
            {
                array[k+from]=temporary[leftIndex++];
            }
            else
            {
                array[k+from]=temporary[rightIndex--];
            }
            k++;
        }
	}

}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值