排序算法,插入、快速、希尔、基数、归并排序
效率分析
代码实现
package puretest;
import java.util.ArrayList;
import java.util.List;
public class paixu {
/**
* 归并排序,稳定的排序。
* 将序列分为2个子序列,对子序列排序(迭代)
* 再将已经排序好的子序列合并
* 最差时间复杂度(nlog n),最优时间复杂度(n)
* 平均时间复杂度(nlog n)最差空间复杂度(n)
* @param nums
* @param low
* @param high
* @return
*/
public Comparable[] mergesort(Comparable[] nums, int low, int high) {
int mid = (low + high) / 2;
if (low < high) {
// 左边
mergesort(nums, low, mid);
// 右边
mergesort(nums, mid + 1, high);
// 左右归并
merge(nums, low, mid, high);
}
return nums;
}
public void merge(Comparable[] nums, int low, int mid, int high) {
Comparable[] temp = new Comparable[high - low + 1];
int i = low;// 左指针
int j = mid + 1;// 右指针
int k = 0;
// 把较小的数先移到新数组中
while (i <= mid && j <= high) {
if (nums[i].compareTo( nums[j])>0) {
temp[k++] = nums[i++];
} else {
temp[k++] = nums[j++];
}
}
// 把左边剩余的数移入数组
while (i <= mid) {
temp[k++] = nums[i++];
}
// 把右边边剩余的数移入数组
while (j <= high) {
temp[k++] = nums[j++];
}
// 把新数组中的数覆盖nums数组
for (int k2 = 0; k2 < temp.length; k2++) {
nums[k2 + low] = temp[k2];
}
}
/**
* 快速排序,将序列按某个值分为两个子序列,第一个序列都小于该值,第二个序列则大于该值
* 然后再对子序列进行迭代。
* 最差时间复杂度(n^2),最优(nlogn),平均(nlogn)
* @param data
* @param min
* @param max
*/
public void QuickSort(Comparable []data,int min ,int max){
if(min<max){
int mid = getmid(data,min,max);
QuickSort(data,min,mid-1);
QuickSort(data,mid+1,max);
}
}
private int getmid(Comparable[] data, int min, int max) {
<span style="white-space:pre"> </span> /**
<span style="white-space:pre"> </span> * <p>Title: getmid</p>
<span style="white-space:pre"> </span> * <p>Description: </p>
<span style="white-space:pre"> </span> */
Comparable temp=data[min];
while(min<max)
{
<span style="white-space:pre"> </span> if(min<max&&data[max].compareTo(temp)>0)
<span style="white-space:pre"> </span> max--;
<span style="white-space:pre"> </span> data[min]=data[max];
<span style="white-space:pre"> </span> if(min<max&&data[max].compareTo(temp)<0)
<span style="white-space:pre"> </span> min++;
<span style="white-space:pre"> </span> data[max]=data[min];
}
data[min]=temp;
return min;
}
/**
* 插入排序
* 构建有序序列,对于未排序数据,
* 在已排序序列中从后向前扫描,找到相应位置并插入。
* 最差时间复杂度 O(n^2),最优时间复杂度 O(n),平均时间复杂度O(n^2)
* @param data
*/
public void insertionSort(Comparable []data){ //插入排序 1
for(int index=1;index<data.length;index++){
Comparable key = data[index];
int position = index;
//shift larger values to the right
while(position>0&&data[position-1].compareTo(key)>0){
data[position] = data[position-1];
position--;
}
data[position]=key;
}
}
/**
* 插入排序
* @param c1
* @return
*/
public Comparable[] insertSort(Comparable[] c1) { //插入排序2
for(int i=1; i<c1.length; i++) {
for(int j=i; j>0; j--) {
if(c1[j].compareTo(c1[j-1])>0) {
Comparable temp = c1[j];
c1[j] = c1[j-1];
c1[j-1] = temp;
} else {
break;
}
}
}
return c1;
}
/**
* 希尔排序,对插入排序的变形,非稳定排序算法,
* 根据步长d来讲序列分为d个子序列,再对子序列排序
* 然后再将d缩小,再次排序...
* 已知的最好步长串行是由Sedgewick提出的 (1, 5, 19, 41, 109,...),本文采用1+3*n
* @param c3
*/
public void ShellSort(Comparable[] c3) {
<span style="white-space:pre"> </span> /**
<span style="white-space:pre"> </span> * <p>Title: ShellSort</p>
<span style="white-space:pre"> </span> * <p>Description: </p>
<span style="white-space:pre"> </span> */
<span style="white-space:pre"> </span> int d = 1;
<span style="white-space:pre"> </span> while(d<c3.length/3)
<span style="white-space:pre"> </span> {
<span style="white-space:pre"> </span> d=d*3+1;
<span style="white-space:pre"> </span> }
<span style="white-space:pre"> </span> //d=d/3;
<span style="white-space:pre"> </span> for(;d>=1;d=d/3)
<span style="white-space:pre"> </span> {
<span style="white-space:pre"> </span> for(int k=0;k<d;k++)
<span style="white-space:pre"> </span> {
<span style="white-space:pre"> </span> for(int i = d+k;i<c3.length;i=i+d)
<span style="white-space:pre"> </span> {
<span style="white-space:pre"> </span> for (int j = i; j >= d && c3[j].compareTo(c3[j-d]) < 0; j-=d) {
<span style="white-space:pre"> </span> Comparable temp = c3[j];
<span style="white-space:pre"> </span> c3[j]=c3[j-d];
<span style="white-space:pre"> </span> c3[j-d]=temp;
<span style="white-space:pre"> </span> }
<span style="white-space:pre"> </span> }
<span style="white-space:pre"> </span> }
<span style="white-space:pre"> </span> }
<span style="white-space:pre"> </span>
}
/**
* 基数排序,将数值按照位数进行排序,依次对最高位,次高位...排序,最差时间复杂度O(kN),k为最大值位数
* @param a
*/
public void radixSort(int[] a){
<span style="white-space:pre"> </span> radixsort(a);
}
public static void radixsort(int[] array){
//首先确定排序的趟数;
int max=array[0];
for(int i=1;i<array.length;i++){
if(array[i]>max){
max=array[i];
}
}
int time=0;
//判断位数;
while(max>0){
max/=10;
time++;
}
//建立10个队列;
List<ArrayList> queue=new ArrayList<ArrayList>();
for(int i=0;i<10;i++){
ArrayList<Integer> queue1=new ArrayList<Integer>();
queue.add(queue1);
}
//进行time次分配和收集;
for(int i=0;i<time;i++){
//分配数组元素;
for(int j=0;j<array.length;j++){
//得到数字的第time+1位数;
int x=array[j]%(int)Math.pow(10, i+1)/(int)Math.pow(10, i);
ArrayList<Integer> queue2=queue.get(x);
queue2.add(array[j]);
queue.set(x, queue2);
}
int count=0;//元素计数器;
//收集队列元素;
for(int k=0;k<10;k++){
while(queue.get(k).size()>0){
ArrayList<Integer> queue3=queue.get(k);
array[count]=queue3.get(0);
queue3.remove(0);
count++;
}
}
}
}
public static void datemin(int longs,int max)
{
<span style="white-space:pre"> </span> paixu pai = new paixu();
<span style="white-space:pre"> </span> Comparable []c1=new Comparable[longs];
Comparable []c2=new Comparable[longs];
Comparable []c3=new Comparable[longs];
Comparable []c4=new Comparable[longs];
int[] a = new int[longs];
for(int i = 0;i<c1.length;i++)
{
Comparable key =Math.random()*max;
c1[i]=key;
c2[i]=key;
c3[i]=key;
c4[i]=key;
a[i]= (int) (Math.random()*max);
}
long Mili0=System.currentTimeMillis();// 当前时间对应的毫秒数
System.out.println("基数排序");
//radixSort(a);
long Mili1=System.currentTimeMillis();// 当前时间对应的毫秒数
System.out.println("结束 s"+(Mili1-Mili0));
System.out.println("归并排序");
pai.mergesort(c1,0,c1.length-1);
long Mili2=System.currentTimeMillis();
System.out.println("结束 s"+(Mili2-Mili1));
System.out.println("快速排序");
pai.QuickSort(c2,0,c2.length-1);
long Mili3=System.currentTimeMillis();
System.out.println("结束 s"+(Mili3-Mili2));
System.out.println("希尔排序");
pai.ShellSort(c3);
long Mili4=System.currentTimeMillis();
System.out.println("结束 s"+(Mili4-Mili3));
}
public static void main(String []args){
int longs=1000000;
int max=10000;
datemin( longs, max);
}
}