`

java排序算法

阅读更多
对于一个排序算法来说,一般从3个方面来衡量算法的优劣。
1、 时间复杂度:主要是分析关键字的比较次数和记录的移动次数
2、 空间复杂度:分析排序算法需要多少辅助内存
3、 稳定性:若两个记录A和B的关键字值相等,但排序后A、B的先后次序保持不变,则称这种排序算法是稳定的;反之,就是不稳定的。
排序算法大致可分为内部排序和外部排序。
如果整个排序过程不需要借助于外部存储器(如磁盘),所有排序操作都在内存中完成,称为内部排序。
如果参与排序的数据元素非常多,数据量非常大,计算机无法把整个排序过程放在内存中完成,必须借助于外部存储器,这种排序称为外部排序。

外部排序最常用的算法是多路归并排序,即将原文件分解成多个能够一次性装入内存的部分,分别把每一个部分调入内存完成排序,接下来再对多个有序的子文件进行归并排序。

内部排序分类
1、 选择排序(直接选择排序、堆排序)
2、 交换排序(冒泡排序、快速排序)
3、 插入排序(直接插入排序、折半插入排序、Shell排序)
4、 归并排序


直接选择排序-----选择排序
直接选择排序算法的关键就是n-1趟比较,每趟比较的目的就是选择出本趟比较中最小的数据,并将该数据放在本趟比较的第1位。只要找到本趟比较中最小的数据,然后拿它和本趟第1位的数据交换。
 
package com.crazyjava;


public class SelectSort1 {
	public static void main(String[] args) {
		DataWrap datas[] = new DataWrap[6];
		datas[0] = new DataWrap(21);
		datas[1] = new DataWrap(30);
		datas[2] = new DataWrap(49);
		datas[3] = new DataWrap(30,"*");
		datas[4] = new DataWrap(16);
		datas[5] = new DataWrap(9);
		printArray(datas);
		selectSort(datas);
		printArray(datas);
	}
	
	public static void selectSort(DataWrap[] datas){
		if(datas==null || datas.length==0)return ;
		
		for(int i=0 ; i<datas.length-1; i++){
			int minIndex = i ;
			for(int j=i; j<datas.length; j++){
				if(datas[minIndex].compareTo(datas[j])>0){
					minIndex = j ;
				}
			}
			if(minIndex!=i){
				DataWrap tmp = datas[i] ;
				datas[i] = datas[minIndex];
				datas[minIndex]=tmp;
			}
		}
	}
	
	public static void printArray(DataWrap[] datas){
		for(DataWrap data : datas){
			System.out.print(data+",");
		}
		System.out.println();
	}
	
}

时间效率为O(n2),空间效率为O(1),直接选择排序是不稳定的。

堆排序-----选择排序
假设有n个数据元素的序列k0,k1,…,kn-1,当且仅当满足如下关系时,可以将这组数据称为小顶堆(小根堆)
Ki <= k2i+1 且 ki <= k2i+2(其中i=0,2,…,(n-1)/2)
或者,满足如下关系时,可以将这组数据称为大顶堆(大根堆)
Ki>=k2i+1 且 ki >= k2i+2 (其中i=0,2…,(n-1)/2)
堆排序与直接选择排序的差别在于,堆排序可通过树形结构保存部分比较结果,可减少比较次数。
建堆的过程不断重复如下步骤:从最后一个非叶子结点开始,比较该结点和它两个子结点的值;如果某个子结点的值大于父结点的值,把父结点和较大的子结点交换。向前逐步调整直到根结点,即保证每个父结点的值都大于等于其左右子结点的值,建堆完成。
 
package com.crazyjava;

public class HeapSort2 {
	public static void main(String[] args) {
		DataWrap[] datas = new DataWrap[6];
		datas[0]=new DataWrap(9);
		datas[1]=new DataWrap(79);
		datas[2]=new DataWrap(46);
		datas[3]=new DataWrap(30);
		datas[4]=new DataWrap(58);
		datas[5]=new DataWrap(49);
		heapSort(datas);
		heapSort(new DataWrap[]{new DataWrap(23),new DataWrap(2)});
		
	}
	public static void heapSort(DataWrap[] datas){
		if(datas==null || datas.length<=0)return ;
		SelectSort1.printArray(datas);
		for(int i=0; i<datas.length-1; i++){
			buildHeap(datas,datas.length-1-i);
			swap(datas,0,datas.length-1-i);
		}
		SelectSort1.printArray(datas);
		
	}
	public static DataWrap[] buildHeap(DataWrap[] datas,int end){
		if(datas==null || end <0)return null;
		
		int startIndex = (end-1)/2;
		for(int i=startIndex; i>=0; i--){
			int k = i ;
			//如果当前k结点的子结点存在
			while((2*k+1)<=end){
				int biggerIndex = 2*k+1 ; //保存k结点的左右子结点值最大的索引
				//代表k结点的右子结点存在
				if(biggerIndex < end){
					if(datas[biggerIndex+1].compareTo(datas[biggerIndex])>0){
						biggerIndex = biggerIndex+1; 
					}
				}
				//如果k结点的值小于较大的子结点的值就交换
				if(datas[biggerIndex].compareTo(datas[k])>0){
					swap(datas,biggerIndex,k);
					//循环,保证k结点的值大于其左右子结点
					k = biggerIndex;
				}else{
					break;
				}
			}
		}
		return datas;
	}
	private static void swap(DataWrap[] datas, int biggerIndex, int k) {
		 DataWrap tmp = datas[k];
		 datas[k]=datas[biggerIndex];
		 datas[biggerIndex] = tmp ;
	}
	
}
堆排序,假设有N项数据,需要进行n-1次建堆,每次建堆本身耗时为log2n,则其时间效率为(nlog2n).空间效率为O(1)。堆排序是不稳定的。

冒泡排序------交换排序
交换排序的主体操作是对数据组中的数据不断进行交换操作。
冒泡排序对于一组包含n个数据的一组纪录,最坏的情况下,冒泡排序需要进行n-1趟比较。每一趟比较把最大的一个数通过交换移至尾端。
 
package com.crazyjava;


public class BubbleSort6 {
	public static void main(String[] args) {
		DataWrap[] datas = {
			new DataWrap(9),
			new DataWrap(16),
			new DataWrap(21),
			new DataWrap(23),
			new DataWrap(30),
			new DataWrap(49),
			new DataWrap(21,"*"),
			new DataWrap(30,"*"),
		};
		
		bubbleSort(datas);
	}
	public static void bubbleSort(DataWrap[] datas){
		if(datas==null || datas.length<=0)return ;
		SelectSort1.printArray(datas);
		
		for(int i=0; i<datas.length-1; i++){
			boolean flag = false ;
			for(int j=0 ; j< datas.length-1-i ; j++){
				if(datas[j].compareTo(datas[j+1])>0){
					DataWrap tmp = datas[j] ;
					datas[j] = datas[j+1];
					datas[j+1] = tmp;
					flag = true ;
				}
			}
			SelectSort1.printArray(datas);
			if(!flag){
				break;
			}
		}
		
		SelectSort1.printArray(datas);
	}
}


时间复杂度为O(n2),空间复杂度为O(1),冒泡排序是稳定的。

快速排序-------交换排序
其思路为从待排的 数据序列中任取一个数据(如第一个数据)作为分界值国,所有比它小的数据元素一律放到左边,所有比它大的数据元素一律放到右边。一趟之后,左边的序列比分界值小,右边的序列比分界值大。接下来对左右子序列进行递归,对两个子序列重新选择中心元素并依此规则调整,直到每个子元素只剩一个,排序完成。
 
package com.crazyjava;

public class QuickSort7 {
	public static void main(String[] args) {
		DataWrap[] datas = {
			new DataWrap(9),
			new DataWrap(-16),
			new DataWrap(21),
			new DataWrap(23),
			new DataWrap(-30),
			new DataWrap(-49),
			new DataWrap(21,"*"),
			new DataWrap(30),
			new DataWrap(13),
		};
		quickSort(datas);
		
	}
	
	public static void quickSort(DataWrap[] datas){
		if(datas==null || datas.length<=0)return ;
		SelectSort1.printArray(datas);
		subSort(datas,0,datas.length-1);
		SelectSort1.printArray(datas);
	}
	
	public static void subSort(DataWrap[] datas,int start, int end){
		if(datas==null)return ;
		if(start < end ){
			DataWrap tmp = datas[start];
			int i = start + 1; int j = end ;
			while(i<j ){
				while(datas[i].compareTo(tmp)<=0 && i<=end)i++;
				while(datas[j].compareTo(tmp)>=0 && j>start)j-- ;
				if(i<j){
					HeapSort2.swap(datas, i, j);
				}else{
					break;
				}
			}
			HeapSort2.swap(datas,start, j);
			subSort(datas, start, j-1);
			subSort(datas, j+1, end);
		}
		
	}
	
}

时间复杂度 O(nlog(n)),空间复杂度为O(log2n),快速排序是不稳定排序.

直接插入排序---------插入排序
其思路为依次将待排序的数据元素按其关键字值的大小插入前面的有序序列。
 
package com.crazyjava;

public class InsertSort3 {
	public static void main(String[] args) {
		DataWrap[] datas = {
			new DataWrap(9),
			new DataWrap(-16),
			new DataWrap(21),
			new DataWrap(23),
			new DataWrap(-30),
			new DataWrap(-49),
			new DataWrap(21,"*"),
			new DataWrap(30),
			new DataWrap(30,"*"),
		};
		
		insertSort(datas);
	}

	public static void insertSort(DataWrap[] datas) {
		if(datas==null || datas.length<0)return ;
		SelectSort1.printArray(datas);
		
		for(int i=1 ; i<datas.length; i++){
			if(datas[i-1].compareTo(datas[i])>0){
				DataWrap tmp = datas[i];
				int j = i-1 ;
				//整体往后移一位,直到小于当前数
				for(; j>=0 && datas[j].compareTo(tmp)>0;--j){
					datas[j+1] = datas[j];
				}
				datas[j+1] = tmp;
			}
		}
		
		SelectSort1.printArray(datas);
	}
}

时间复杂度为O(n2),空间复杂度为O(1),直接插入排序是稳定的。

折半插入排序---------插入排序
折半插入排序是对直接插入排序进行简单改进,通过二分查找更快的确定有序序列中第i个元素的插入位置,再将要插入位置后的元素全部后移一位。
 
package com.crazyjava;

public class BinaryInsertSort4 {
	public static void main(String[] args) {
		DataWrap[] datas = {
				new DataWrap(9),
				new DataWrap(-16),
				new DataWrap(21),
				new DataWrap(23),
				new DataWrap(-30),
				new DataWrap(-49),
				new DataWrap(21,"*"),
				new DataWrap(30),
				new DataWrap(30,"*"),
		};
		binaryInsertSort(datas);	
	}
	
	public static void binaryInsertSort(DataWrap[] datas){
		if(datas==null || datas.length<=0)return ;
		SelectSort1.printArray(datas);
		
		for(int i=1; i<datas.length ; i++){
			if(datas[i-1].compareTo(datas[i])>0){
				DataWrap tmp = datas[i] ;
				int low = 0; int high = i-1 ;
				while(low <= high){
					int mid = (low+high)/2 ;
					if(datas[mid].compareTo(datas[i])>0){
						high = mid -1 ;
					}else{
						low = mid + 1 ;
					}
				}
				for(int j=i ; j>low ; j--){
					datas[j] = datas[j-1];
				}
				datas[low] = tmp ;
			}
		}
		
		SelectSort1.printArray(datas);
	}
}



Shell排序------------插入排序
对于直接插入和折半插入排序,如果一个很小的数据单元位于很靠近右端的位置上,为了把这个数据单元移动到左边正确的位置上,中间所有的数据单元都需要向右移动一格。Shell排序对直接插入排序进行了简单改进:它通过加大插入排序中元素之间的间隔,并在这些有间隔元素中进行插入排序,从而使数据项大跨度地移动。当这些数据项排过一趟序后,Shell排序算法减小数据项的间隔再进行排序,依次进行下去。直到完成以1为增量的Shell排序,此时数据序将会变为有序。
Shell排序算法的关键在于确定h序列的值,常用的h序列由Knuth提出,该序列从1开始,通过如下公式产生:h = h*3+1 ;即1、4、13、40….,反向h =(h-1)/3即40、13、4、1.
 
package com.crazyjava;

public class ShellSort5 {
	public static void main(String[] args) {
		DataWrap[] datas = {
				new DataWrap(9),
				new DataWrap(-16),
				new DataWrap(21),
				new DataWrap(23),
				new DataWrap(-30),
				new DataWrap(-49),
				new DataWrap(21,"*"),
				new DataWrap(30),
				new DataWrap(30,"*"),
		};
		shellSort(datas);
	}
	
	public static void shellSort(DataWrap[] datas){
		if(datas==null || datas.length <= 0 )return ;
		System.out.println("start:");
		SelectSort1.printArray(datas);
		
		int h = 1 ; 
		while( h <= (datas.length/3)){
			h = h*3 + 1; 
		}
		while(h>0){
			System.out.println("h = "+h);
			for(int i =h ; i<datas.length ; i++){
				DataWrap tmp = datas[i] ;
				if(datas[i-h].compareTo(tmp)>0){
					int j = i-h ;
					for(; j>=0 && datas[j].compareTo(tmp)>0 ; j-=h){
						datas[j+h] = datas[j];
					}
					datas[j+h] = tmp;
				}
				SelectSort1.printArray(datas);
			}
			h = (h-1)/3 ;
		}
		System.out.println("end:");
		SelectSort1.printArray(datas);
	}
	
}

时间复杂度估计在O(N3/2)-O(N7/6),空间复杂度为O(1),它是稳定的。


归并排序
其基本思想是将两个(或以上)有序的序列合并成一个新的有序序列。细化说,归并排序先将长度为n的无序序列看成是n个长度为1的有序子序列,首先做两两合并,得到n/2个长度为2的有序子序列,再做两两合并…….不断重复这 个过程最终可以得到一个长度为n的有序序列。
 
package com.crazyjava;


public class MergeSort8 {
	public static void main(String[] args) {
		DataWrap[] datas={
			new DataWrap(9),
			new DataWrap(-16),
			new DataWrap(21),
			new DataWrap(23),
			new DataWrap(-30),
			new DataWrap(-49),
			new DataWrap(21,"*"),
			new DataWrap(30),
			new DataWrap(30,"*"),	
		};
		mergeSort(datas);
	}
	
	public static void mergeSort(DataWrap[] datas){
		if(datas==null || datas.length<=0)return ;
		SelectSort1.printArray(datas);
		DataWrap[] tmpDatas = new DataWrap[datas.length];
		sort(datas,tmpDatas,0,datas.length-1);
		SelectSort1.printArray(datas);
	}
	
	public static void sort(DataWrap[] datas,DataWrap[] tmpDatas, int start, int end){
		if(start==end)return ;
		if(start < end ){
			int mid = (start+end)/2; 
			sort(datas,tmpDatas,start,mid);
			sort(datas,tmpDatas,mid+1,end);
			merge(datas,tmpDatas,start,mid,end);
		}
	}
	
	public static void merge(DataWrap[] datas,DataWrap[] tmpDatas, int start, int center, int end){
		int i = start ; int j = center+1;
		int k = start ;
		while(i<=center && j<=end){
			if(datas[i].compareTo(datas[j])<=0 ){
				tmpDatas[k++] = datas[i++];
			}else{
				tmpDatas[k++] = datas[j++];
			}
		}
		while(i<=center){
			tmpDatas[k++] = datas[i++];
		}
		while(j<=end){
			tmpDatas[k++] = datas[j++];
		}
		
		for(int t= start ; t<=end; t++){
			datas[t] = tmpDatas[t];
		}
	}
}

时间复杂度为O(nlog2n),空间复杂度O(n),归并排序是稳定的。
分享到:
评论

相关推荐

    java排序算法使用及场景说明

    Java 排序算法使用及场景说明 本文档主要介绍了 Java 排序算法的使用和场景说明,包括了五个实践场景的解决方案。 Scenario 1: 找出两个文件共同的 URL 在这个场景中,我们有两个文件 a 和 b,每个文件中存放了 ...

    Java排序算法大全

    Java排序算法大全是一份专为Java开发者准备的学习资源,涵盖了各种经典的排序算法,旨在帮助初学者和有经验的程序员深入理解排序的原理和实现。排序是计算机科学中的基础且重要的概念,它在数据处理、数据库操作、...

    Java排序算法实现

    Java排序算法实现 Java排序算法实现 Java排序算法实现

    java排序算法插入选择冒泡

    java排序算法java排序算法插入选择冒泡java排序算法插入选择冒泡

    java排序算法效率比较

    在Java编程语言中,排序算法是数据结构与算法学习中的重要组成部分。本实验通过生成大量随机数并写入文件,然后使用四种不同的排序算法进行排序,以比较它们的效率。以下是对这四种排序算法的详细解释: 1. **冒泡...

    Java排序算法详细整理

    【Java排序算法详细整理】 在计算机科学中,排序算法是用于对一组数据进行排列的算法。在Java中,实现各种排序算法有助于理解数据结构和算法的原理,同时也能提高编程能力。以下是对Java中常见的几种排序算法的详细...

    Java排序算法包 支持自定义比较条件

    这个"Java排序算法包"提供了对多种排序算法的支持,并且允许用户根据自己的需求自定义比较条件,使得排序功能更加灵活。 1. **排序算法基础**: - 排序是指将一组数据按照特定的顺序进行排列的过程。常见的排序...

    Java排序算法 Java排序算法.rar

    Java排序算法涉及了多种方法,用于组织数组或集合中的元素,使其按照特定顺序排列。以下是对这些算法的详细解释: 1. **冒泡排序(Bubble Sort)** 冒泡排序是一种简单直观的排序算法,它重复地遍历待排序的数列,一...

    java 排序算法

    代码中列举了java常见的排序算法,并备有简单的注释信息,对于初级开发人员可供参考。

    Java排序算法详解.rar

    Java排序算法涉及了多种方法,每种都有其特定的适用场景和性能特点。本篇将深入探讨几种常见的Java排序算法,包括冒泡排序、插入排序、选择排序、快速排序、归并排序、堆排序以及TimSort等。 1. **冒泡排序**: ...

    java排序算法-大全.rar

    这个名为"java排序算法-大全.rar"的压缩包文件显然包含了多种Java实现的排序算法,这对于我们理解和掌握这些算法至关重要。 首先,让我们从标签提及的两个经典排序算法开始:冒泡排序和折半排序。 1. **冒泡排序**...

    java排序算法演示源码

    本资源提供了丰富的Java排序算法的演示源码,注解详尽,有助于理解和学习。 1. **冒泡排序(Bubble Sort)** 冒泡排序是最基础的排序算法之一,通过不断地交换相邻的不正确顺序的元素来逐步完成排序。源码中应该...

    面试笔试必用-必须掌握的Java排序算法

    Java排序算法是编程面试和笔试中常见的考察点,掌握这些算法对于提升编程能力和解决实际问题至关重要。本篇文章将深入探讨几种主要的Java排序算法及其特点。 1. **插入排序** - **直接插入排序**:将每个元素依次...

    Java排序算法汇总大全.doc

    Java排序算法汇总大全 在计算机科学中,排序算法是用于对数据序列进行排列的算法,以便根据特定标准对其进行组织。本文将详细介绍Java中常见的几种排序算法,并提供它们的基本原理、性能分析以及适用场景。 1. ...

    各种排序算法比较(java实现)

    本文将详细探讨标题所提及的几种排序算法:合并排序、插入排序、希尔排序、快速排序、冒泡排序以及桶排序,并结合Java语言的实现进行解析。 1. **合并排序(Merge Sort)**: 合并排序是一种基于分治策略的排序算法...

    Java排序算法_java_

    Java排序算法是编程领域中的重要知识点,特别是在处理大量数据时,高效的排序算法能显著提升程序性能。本资源包含了Java实现的常见排序算法集合,对于学习和理解这些算法有着极大的帮助。 1. 冒泡排序(Bubble Sort...

    java排序算法集合

    【Java排序算法集合】 在Java编程中,排序算法是数据结构和算法中不可或缺的一部分,它用于将一组数据按照特定的顺序排列。常见的排序算法包括选择排序、冒泡排序和插入排序,下面我们将逐一探讨这些算法的基本思想...

Global site tag (gtag.js) - Google Analytics