部分排序算法总结

希尔排序

package java数据结构练习;

import java.util.Arrays;

/**
 * 希尔排序
 * 也是插入排序的一种,
 * 主要思想是将整个无序序列按照一定的间隙gap划分成多个子序列,然后对这些子序列进行插入排序。
 * 时间复杂度在o(n²)和o(n*log₂n)之间,当n在某个特定范围时,希尔排序的时间性能约为o(n¹·³)。
 * 空间复杂度为o(1)。
 * 希尔排序是一种不稳定的排序方法。
 * @author lenovo
 *
 */
public class ShellSort {

	public static void main(String[] args) {
		int val,index,n=40;
		int a[]=new int[n];
		
		for(int i=0;i<n;i++)
			a[i]=(int) (Math.random()*n);
		//System.out.println(Arrays.toString(a));
		long t1=System.currentTimeMillis();
		//gap为间隙
		for(int gap=a.length/2;gap>0;gap=gap/2)
		{
			//当分隔间隙为gap时,对于相距为gap的记录,划分成了gap个子序列
			for(int i=gap;i<a.length;i++)
			{
				val=a[i];
				index=i;
				//if(a[index-gap]>a[index]) {
				//进行插入排序,寻找合适的插入位置
					while((index-gap)>=0 && a[index-gap]>val)
					{
						a[index]=a[index-gap];
						index=index-gap;
					}
					a[index]=val;
				//}
			}
		}
		long t2=System.currentTimeMillis();
		System.out.println("运行时间为:"+(t2-t1)+"ms");
		System.out.println(Arrays.toString(a));
	}

}

快速排序

package java数据结构练习;

import java.util.Arrays;

/**
 * 快速排序,
 * 主要思想是“左小右大”,
 * 即选择一个基准值p,然后比基准值小的放在左边,比基准值大的放在右边,
 * 然后递归对左边和右边的序列继续排序。
 * 在最好情况下,时间复杂度为o(n*log₂n),空间复杂度为取决于递归栈的深度,为o(log₂n);
 * 在最坏情况下,时间复杂度为o(n²),空间复杂度为o(n);
 * 在平均情况下,时间复杂度为o(n*log₂n),空间复杂度为o(log₂n)。
 * 快速排序是一种不稳定的排序方法(例如1、3、5、2、6、3、0这个序列,第一次排序以2为基准值,前面的3和0交换,相等值的前后顺序发生了改变)。
 * @author lenovo
 *
 */
public class QuickSort {

	static void quicksort(int a[],int left,int right)
	{
		int temp;
		int l=left;
		int r=right;
		//P为基准值
		int p=a[(l+r)/2];
		
		//循环完毕后得到左边是比基准值小的,右边是比基准值大的。其实这里l和r感觉有点像双指针法。
		while(l<r)
		{
			while(a[l]<p)
				l++;
			
			while(a[r]>p)
				r--;
			
			if(l>=r)
				break;
			
			temp=a[l];
			a[l]=a[r];
			a[r]=temp;
			
			//现在的左边是原来的右边,右边是原来的左边;如果没有这段代码,那么当a[l]和a[r]都为p时则会出现死循环
			if(a[l]==p)
				r--;
			if(a[r]==p)
				l++;
		}
		
		//下标错开,否则栈溢出
		if(l==r)
		{
			l++;
			r--;
		}
		
		//左递归
		if(left<r)
			quicksort(a, left, r);
		
		//右递归
		if(l<right)
			quicksort(a, l, right);
	}
	
	public static void main(String[] args) {
		int n=80000,val,index;
		int a[]= new int[n];
		for(int i=0;i<n;i++)
			a[i]=(int) (Math.random()*n);
		//System.out.println(Arrays.toString(a));
		long t1=System.currentTimeMillis();
		quicksort(a, 0, a.length-1);
		long t2=System.currentTimeMillis();
		//System.out.println(Arrays.toString(a));
		System.out.println("运行时间为:"+(t2-t1)+"ms");
	}

}

归并排序

package java数据结构练习;

import java.util.Arrays;

/**
 * 归并排序,
 * 主要思想是先分再合,即分治的思想,
 * 也就是对于一个无序的序列,最开始每个单独的数都可看成有序序列,
 * 然后不断合并这些有序序列即可得到一个完全有序的序列。
 * 总的时间代价是o(n*log₂n),这是归并排序最好、最坏、平均的时间性能;
 * 因为需要一个暂存数组,所以空间复杂度为o(n)。
 * 归并排序是一种稳定的排序方法。
 * @author lenovo
 *
 */
public class 归并排序 {

	//该函数相当于一个分的过程
	static void mergeSort(int a[],int left,int right,int temp[])
	{
		if(left<right) {
			int mid=(left+right)/2;
			mergeSort(a, left, mid, temp);

			mergeSort(a, mid+1, right, temp);

			merge(a, left, mid,right, temp);
		}
	}
	
	//该函数相当于一个合并的过程,temp作为合并的暂存数组
	private static void merge(int[] a, int left, int mid, int right, int temp[]) 
	{
		//左边序列的指针
		int l=left;
		//右边序列的指针
		int r=mid+1;
		//temp数组的指针
		int t=0;
		
		//将左边和右边的序列合并到temp数组中
		while(l<=mid && r<=right)
		{
			if(a[l]<=a[r])
			{
				temp[t]=a[l];
				t++;
				l++;
			}
			else
			{
				temp[t]=a[r];
				r++;
				t++;
			}
		}
		
		//对左边序列可能的剩余数的合并
		while(l<=mid)
		{
			temp[t]=a[l];
			t++;
			l++;
		}
		
		//对右边序列可能的剩余数的合并
		while(r<=right)
		{
			temp[t]=a[r];
			t++;
			r++;
		}
		
		//重置指针,将temp暂存数组里面的数据复制到原数组a中
		t=0;
		int tl=left;
		while(tl<=right)
		{
			a[tl]=temp[t];
			tl++;
			t++;
		}
	}

	
	public static void main(String[] args) {
		int n=80000,val,index;
		int a[]=new int[n];
		int temp[]=new int [n];
		for(int i=0;i<n;i++)
			a[i]=(int) (Math.random()*n);
		//System.out.println(Arrays.toString(a));
		long t1=System.currentTimeMillis();
		mergeSort(a, 0, a.length-1, temp);
		long t2=System.currentTimeMillis();
		//System.out.println(Arrays.toString(a));
		System.out.println("运行时间为:"+(t2-t1)+"ms");
	}

}

插入排序

package java数据结构练习;

import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.Random;

/**
 * 插入排序,
 * 主要思想是假设一个已经排好序的序列(初始时这个序列自然为空),
 * 然后对于无序序列中的数据,在有序序列中去查找合适的位置,并进行插入。
 * 在最好情况下,时间复杂度为o(n);
 * 最坏情况下,时间复杂度为o(n²);
 * 平均情况下,时间复杂度为o(n²)。
 * 空间复杂度为o(1)。
 * 直接插入排序是一种稳定的排序方法。
 * @author lenovo
 *
 */
public class InsertSort {

	public static void main(String[] args) {
		int n=80000,val,index;
		int a[]= new int[n];
		for(int i=0;i<n;i++)
			a[i]=(int) (Math.random()*n);
		//System.out.println(Arrays.toString(a));
		long t1=System.currentTimeMillis();
		for(int i=1;i<a.length;i++)
		{
			val=a[i];
			index=i-1;
			//寻找第一个小于等于当前值的值,即为插入位置
			while(index>=0 && val<a[index])
			{
				a[index+1]=a[index];
				index--;
			}
			a[index+1]=val;
		}
		//Arrays.sort(a);
		long t2=System.currentTimeMillis();
		
		System.out.println("运行时间为:"+(t2-t1)+"ms");
		//System.out.println(Arrays.toString(a));
	}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值