常见排序算法总结(一)

这里的排序算法指内排序算法,即在内存中排序;所谓排序为部分有序到全局有序的过程,以下排序都以从小到大为例

1.直接插入排序

思想:好像打扑克牌一样,寻找正确的位置插入,分三步走。一:寻找合适的位置。二:将后面的数往后移一位,腾出空间。三:插入

public class InSortDemo {

	public static void main(String[] args) {
		int a[]={0,46,55,13,42,44,17,05,70};//要定义哨兵,故空出a[0],在a[0]存个值
		InSortDemo(a);

	}

	private static void InSortDemo(int[] a) {

		int j=0;
		//当下标为一明显没有比较的必要,从二开始,整个算法可以看做寻找j真正值的过程,j的值为a[i]的插入位,
		//故需不断比较,若大于说明j的值应该更小,即排的更前面,将大的值往后移
		for(int i=2;i<a.length;i++){
			a[0]=a[i];j=i-1;
			while(a[j]>a[0]){
				a[j+1]=a[j];
				j--;
			}
			//发现数比a[i]还小,说明过了,j多减了,要进行加一
			j=j+1;
			a[j]=a[0];
		}
		for(int i=1;i<a.length;i++){
			System.out.print(a[i]+",");
		}
	}
	
}

2.计数排序

思想:过程在寻找各个数应该在的位置,不同的是没有直接插在应该在的位置,而是记录起来,维护着一个数组

public class CountSortDemo {

	public static void main(String[] args) {
		int a[]={46,55,13,42,44,17,05,70};
		CountSort(a);

	}

	private static void CountSort(int[] a) {
		int b[]=new int[a.length];//新建数组,对应数组a里的各个数数经过排序后的索引
		for(int i=0;i<b.length;i++){
			b[i]=0;//初始化为0
		}
		for(int i=0;i<b.length-1;i++){
			//从第一个数开始,每个数都要与后面的数比较大小,将大的数,对应存储的索引值加一,一轮过后a[i](与后面的数都比较过了)便得到应                        //在的位置
			for(int j=i+1;j<=b.length-1;j++){
				if(a[i]>a[j]){
					b[i]++;
				}else{
					b[j]++;
				}
			}	
		}
		int temp[]=new int[a.length];//暂存排序后的数组
		for(int i=0;i<temp.length;i++){
			temp[b[i]]=a[i];
		}
	
	
		for(int x:temp)
		System.out.println(x);
	
	}

}


3.快速排序

思想:快速排序是一种不断划分的算法,选取一个数(一般序列取首个数),在序列中找到恰当的位置,怎样算恰当,即使序列左边的数都比这个数小,右边的数大于或等于它,然后这个数的左边右边不断递归这个操作,最终实现全局有序

public class QuickSortDemo {

	public static void main(String[] args) {
		int arry[]={46,55,13,42,94,05,17,70 };
		QuickSort2(arry,0,arry.length-1);
		for(int a:arry){
			System.out.print(a+",");
		}
		
	}

	private static void QuickSort2(int[] arry, int start, int end) {
		int i=start;int j=end;int x=arry[start];//i,j为移动的下标,一左(从第一个)一右(从最后一个)向中间移动,找寻arry[start]的位                                                       //置,保证左边小,右边大于等于这个数
		do{    //arry[j]满足比x大,就往前移(中间),不满足就停住
			while(arry[j]>=x&&j>i)
				j--;
			if(i<j)//出了循环即不满足了,遇到比x小的数,直接抛到arry[i]位置,使arry[i]满足比x小,可以继续增大i,向中间移动
				{arry[i]=arry[j];i++;}
			while(i<j&&arry[i]<=x){
				i++;
			}
			if(i<j){//同理arry[i]遇到比x大的,不满足也抛到j的位置,使arry[j]满足大于等于的条件
				arry[j]=arry[i];j--;
			}
		}while(i!=j);//不断循环,直到i==j,即这个位置左边数比x小,右边的数比x大,这个位置就是x的位置
		arry[i]=x;i++;j--;
		
		if(start<j)
				QuickSort2(arry,start,j);//左边的数不止一个,递归
		if(i<end)
				QuickSort2(arry,i,end);//右边的数不止一个,递归
			
	}

	

}

4.冒泡排序

思想:每相邻的两个数两两比较大小,重的往下(右)沉,轻的往上(左)浮,就好像泡泡一样,比较一轮后,确定了最大值,下一轮可以不参与比较,即下轮参与的数为数组长度减一,再进行一轮,则又确定次最大的值,下轮比较的数目又减少一个......以此类推。

public class BubbleSortDemo {
	public static void main(String args[]){
		int a[]={46,55,13,42,44,17,05,70};
		BubbleSort(a);
	}

	private static void BubbleSort(int[] a) {
		int j=0; int N=a.length-1;int temp=0;
	do{	
		for(int i=0;i<N;i++){
			 j=i+1;
			 if(a[i]>a[j]){
				 temp=a[i];
				 a[i]=a[j];
				 a[j]=temp;
				
			 }
			
		} 
	N--;
	}while(N!=1);
	for(int x:a)
		System.out.print(x+",");
	}
}

可以发现这个算法又可以改进的地方,因为可能不用进行那么多轮比较就已经排好,故可以设置标志位。

private static void BubbleSort(int[] a) {
		int j=0; int N=a.length-1;boolean  flag=false; int temp=0;
	do{	
		for(int i=0;i<N;i++){
			 j=i+1;
			 if(a[i]>a[j]){
				 temp=a[i];
				 a[i]=a[j];
				 a[j]=temp;
				 flag=true;
			 }
			
		} 
	N--;
	}while(N!=1&&flag);
	for(int x:a)
		System.out.print(x+",");
	}


冒泡排序有多种写法,这里提供另一种写法

private static void BubbleSort2(int[] a) {
		int temp=0;
		for(int i=0;i<a.length-1;i++){
			for(int j=0;j<a.length-1-i;j++)
			{ 
			 if(a[j]>a[j+1]){
				 temp=a[j+1];
				 a[j+1]=a[j];
				 a[j]=temp;
				
			 }
			}
		} 
		for(int x:a)
			System.out.print(x+",");
		
	}


5.选择排序

思想:选出最小值与第一位交换位置,在剩余数中选出第二小值与第二位交换位置.....以此类推

public class SelectSortDemo {
	public static void main(String args[]){
		
		int a[]={46,55,13,42,44,17,05,70};
		SelectSort(a);

	}

	private static void SelectSort(int[] a) {
		int min=0; int temp=0;
		for(int i=0;i<a.length-1;i++){
			 min=i;//假设本身即符合的数
			 for(int j=i+1;j<a.length;j++)
			 {
				//发现更小的数,改变下标
				 if(a[min]>a[j]){
					 min=j;
				 }
			 }
			 if(i!=min)//原本位置上的数不符合要求,与符合的数交换位置
			 {temp=a[min];
			 a[min]=a[i];
			 a[i]=temp;
			 }
		 }
		for(int x:a)
			System.out.print(x+",");
	}
}

6.折半插入排序
思想:首先先了解折半查找,就是不断的二分,缩小要查找的数的范围
private static int binSearch(int[] a, int key) {
		int low=0;int high=a.length-1;int middle=0; 
	      while(low<=high)
	         {
	              middle=(low+high)/2;
	              if (key==a[middle]) 
	                 return (middle);//找到,返回
	              else if ( key>a[middle])
	                  low=middle+1;//则key必在较高标号的那一半表中, 令low=middle+1

	              else
	                  high=middle-1;//则key必在较低标号的那一半表中, 令high=middle-1

	          }

		
		return low;//此时high小于low,就是没找到要查找的数,可返回-1.这边返回的是要查找的数应在的位置,low的位置即元素该在的位置
		
	}
折半插入是对直接插入的改进,直接插入排序中,寻找元素的位置需要和前面的数一个个比过去,这样明显效率低,因为前面的数已经排过了,即有序,那部分可用折半查找,
注意只是替代寻找的那部分
private static void binSearchSort(int[] a) {
		
		for(int i=2;i<a.length;i++){//依旧从二开始
			a[0]=a[i];
			int low=1;int high=i-1;int middle=0;
			while(low<=high){
			middle=(low+high)/2;
			if(a[middle]<a[0])
				low=middle+1;
			else 
				high=middle-1;
			}//寻找结束,low即要的位置,接下来移动后面的数
			for(int j=i-1;j>=low;j--){
				a[j+1]=a[j];
			}
			a[low]=a[0];//插入
		}
	}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值