比较排序算法的Java实现

4 篇文章 0 订阅
在我们熟知的排序算法中,最早接触的就是冒泡排序和选择排序,后来又有了插入排序,但是这些排序算法都是二次时间的,对于大量数据的排序效率不是很高。因此后面就有了如希尔排序,归并排序,堆排序和快速排序。这里总共有7种,因为它们在排序时都会进行比较,因此也是比较排序算法,而比较排序的最快时间也要Ω(NlogN)。这时根据比较的决策树得到。N个元素,它的排序有N!种情况,将它放入到二叉树中,N!情况都在树叶上,而具有N!的树叶的二叉数的深度至少为log(N!)=Ω(NlogN)。

     当然,如果不是比较排序,就可以突破这种现状。线性排序算法我在另一篇文章中已经写到,见 线性排序的Java实现

下面的图是网上对于常见排序算法的总结:

1.插入排序Java代码如下:

//插入排序 希尔排序是它的变形
public static void insertSort(int[] a)
{
	for(int i=0;i<a.length-1;i++)
	{
		int j=i+1;
		int tmp=a[j];
		for(;j>0 && tmp<a[j-1];j--)
			a[j]=a[j-1];
		a[j]=tmp;
	}
}


2.选择排序

//选择排序 不稳定排序
public static void chooseSort(int[] a)
{
	for(int i=0;i<a.length-1;i++)
	{
		int min=i;
		for(int j=i+1;j<a.length;j++)
		{
			if(a[j]<a[min])
				min=j;
		}
		int tmp=a[i];
		a[i]=a[min];
		a[min]=tmp;
	}
}


3.冒泡排序,进行改进可以达到最快时间O(N)

//冒泡排序  基本版
public static void bubbleSort(int[] a)
{
	for(int i=0;i<a.length;i++)
	{
		for(int j=1;j<a.length-i;j++)
		{
			if(a[j-1]>a[j])
			{
				int tmp=a[j-1];
				a[j-1]=a[j];
				a[j]=tmp;
			}
		}
	}
}
//冒泡排序改进 最优时间复杂度O(N)
public static void bubbleSortN(int[] a)
{
	boolean doswap;
	for(int i=0;i<a.length;i++)
	{
                doswap=false;
		for(int j=1;j<a.length-i;j++)
		{
			if(a[j-1]>a[j])
			{
				int tmp=a[j-1];
				a[j-1]=a[j];
				a[j]=tmp;
				doswap=true;
			}
		}
		if(doswap==false) //说明没有交换,数组是顺序的
			break;
	}
}


4.希尔排序,它是插入排序的变形,可以选取不同的增量

//希尔排序,就是插入排序的一种变形
public static void shellsort(int[] a){
	for(int gap=a.length/2;gap>0;gap=gap/2){
		for(int i=gap;i<a.length;i++){
			int tmp=a[i];
			int j=i;
			for(;j>=gap && tmp<a[j-gap];j=j-gap)
				a[j]=a[j-gap];
			a[j]=tmp;
		}
	}
}


5.堆排序  这里需要有建堆,维护堆,堆排序

//维护堆
public static void maxHeapify(int[] a,int i,int size)
{
	int tmp=a[i];
	int child=i*2;
	while(child<=size)
	{
		if(child+1<size && a[child+1]<a[child])
			child++;
		if(a[child]<tmp)
			a[child/2]=a[child];
		else
			break;
		child=2*child;
	}
	a[child/2]=tmp;
}
//建堆  时间复杂度O(N)
public static void buildHeap(int[] a)
{
	for(int i=(a.length-1)/2;i>0;i--)  //只要对堆前一半的元素进行维护
	{
		maxHeapify(a,i,a.length-1);
	}
}
//堆排序算法  这是最小堆  输出的数组是从大到小 且a[0]不算堆元素
public static void heapSort(int[] a)
{
	int temp;
	buildHeap(a);
	int size=a.length-1;  //去掉a[0]
	for(int i=size;i>1;i--)
	{
		temp=a[i];
		a[i]=a[1];
		a[1]=temp;
		size--;
		 maxHeapify(a,1,size);
	}
}


6.归并排序

//归并排序 递归方法  O(N)的空间复杂度
public static void mergeSort(int[] a){
	int[] tmp=new int[a.length];
	mergeSort(a,tmp,0,a.length-1);
}
private static void mergeSort(int[] a,int[] tmp,int left,int right){
	if(left<right)
	{
		int center=(left+right)/2;
		mergeSort(a,tmp,left,center);   //先分割,再合并处理;和快速排序是反的(快排:先处理,再分割)
		mergeSort(a,tmp,center+1,right);
		merge(a,tmp,left,center,right);
	}
}
private static void merge(int[] a,int[] tmp,int left,int center,int right){
	int num=right-left+1;
	int i=left;
	int j=center+1;
	int pos=left;
	while(i<=center&&j<=right)
	{
		if(a[i]<a[j])
			tmp[pos++]=a[i++];
		else
			tmp[pos++]=a[j++];
	}
	while(i<=center)
	{
		tmp[pos++]=a[i++];
	}
	while(j<=right)
	{
		tmp[pos++]=a[j++];
	}
	for(int q=left;q<=right;q++)
	{
		a[q]=tmp[q];
	}
}
//合并过程 O(1)空间复杂度,不建立临时数组空间,但是时间代价会变大
private static void merge(int[] a,int left,int center,int right){
	int lpos=left;
	int rpos=center+1;   
	while(lpos<=center && rpos<=right)  //类似插入过程
	{
		if(a[lpos]<=a[rpos])
			lpos++;
		else
		{
			int tmp=a[rpos];
			for(int i=rpos;i>=lpos;i--)
			{
				a[i]=a[i-1];
			}
			a[lpos]=tmp;
			rpos++;
			lpos++;
		}
	}
}


7.快速排序

//快速排序
public static void quickSort(int[] a)
{
	quickSort(a,0,a.length-1);
}
private static void quickSort(int[] a,int left,int right)
{
	if(left<right)
	{
		int pivot=a[left];
		int i=left;
		int j=right;
		while(i<j)
		{
			while(a[j]>pivot && i<j){j--;}
			if(i<j)
				a[i++]=a[j];
			while(a[i]<pivot && i<j){i++;}
			if(i<j)
				a[j--]=a[i];
			
		}	
		a[i]=pivot;
		quickSort(a,left,i-1);
		quickSort(a,i+1,right);
         }
}

非递归实现,使用栈存储

//快速排序的非递归实现,利用系统的栈stack
public class QuickSortNonRecursion {
	 public static void main(String[] args) {
	 	 QuickSortNonRecursion qsnr = new QuickSortNonRecursion(); 
	 	 int[] array = {0, 2, 11, 121, 18, 99, 3, 5, 101, 22, 9, 100}; 
	 	 qsnr.quicksort(array); for (int i : array) {
	 	 	 System.out.print(i + " "); } 
	 } 
	 public void quicksort(int[] array) { 
		if (array == null || array.length == 1) return; 
		//存放开始与结束索引 Stack<Integer> s = new Stack<Integer>(); 
		//压栈 
		s.push(0); 
		s.push(array.length - 1); 
		//利用循环里实现
		 while (!s.empty()) {
		 	 int right = s.pop(); 
		 	 int left = s.pop();
		 	  //如果最大索引小于等于左边索引,说明结束了
		 	   if (right <= left) continue; 
		 	   int i = partition(array, left, right);
		 	    if (left < i - 1) {
		 	    	 s.push(left); s.push(i - 1);
		 	    } 
		 	    if (i + 1 < right) {
		 	    	 s.push(i+1); s.push(right);
		 	    	  }
		 	     }
		 	 }

 	  //找到轴心,进行交换 
		public int partition (int[] data, int first, int end) {
		 	  	 int temp; 
		 	  	 int i=first,j=end; 
		 	  	 if(first<end) { 
		 	  	 	temp=data[i]; 
		 	  	 	//当i=j的时候,则说明扫描完成了
		 	  	 	 while(i<j) { 
		 	  	 	 	//从右边向左边扫描找到一个小于temp的元素 
		 	  	 	 	while(j>i&&data[j]>temp)j--; if(i<j) {
		 	  	 	 		 //将该元素赋值给temp
		 	  	 	 		  data[i]=data[j]; 
		 	  	 	 		  //赋值后就应该将i+1指向下一个序号 
		 	  	 	 		  i++; } 
		 	  	 	 		  //然后从左边向右边开始扫描,找到一个大于temp的元素 
		 	  	 	 		  while(i<j&&temp>data[i])i++; 
		 	  	 	 		  if(i<j) { 
		 	  	 	 		  	//将该元素赋值给temp
		 	  	 	 		  	 data[j]=data[i]; 
		 	  	 	 		  	 //赋值后就应该将j-1指向前一个序号 
		 	  	 	 		  	 j--; 
		 	  	 	 		  	 }
		 	  	 	 		  } //将轴数据放在i位置中 
		 	  	 	 	data[i]=temp;
		 	  	 	 	}
		 	  	 	  return i;
		 	  	 	 	 } 
}

 

                
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值