常用的排序算法集锦

前言


昨晚参加了今日头条的笔试,大部分都是算法题,而算法恰恰就是我的弱项,所以被虐得不轻。于是为了提升自己的算法能力,我在博客整理一些常用的算法及原理,巩固一下基础知识,顺便为秋招做准备。先讲一下最基础的排序算法吧(昨晚就是有一道关于排序的,我居然忘了排序算法的实现,以此为戒)


插入排序


1.直接插入排序(稳定)

思路:在插入第i个记录时,R1、R2、......、Ri-1已经排好序,这时将Ri的关键字ki依次与关键字ki-1、ki-2等进行比较,从而找到应该插入的位置并将Ri插入,插入位置及其后的记录依次向后移动。


java实现:

public class Main{
	public static void main(String[] args){
		//待排序的数组
		int[] numbers = {3,56,12,456,5,23,16,15,56,456};
		int i,j,temp;
		for(i = 1;i < numbers.length;i++){
			temp = numbers[i];
			j = i - 1;
			//将当前数与排好序的序列逐个比较,寻找插入位置
			while(j >= 0 && numbers[j] > temp){
				//将大于当前数的元素后移
				numbers[j+1] = numbers[j];
				j--;
			}
			numbers[j+1] = temp;
		}
		//输出排序后的数组
		for(int number : numbers){
			System.out.print(number + " ");
		}
	}
}

2.折半插入排序(稳定)

思路:折半插入排序是对直接插入排序的完善。直接插入排序将无序区中开头元素R[i](1 <= i <= n-1)插入到有序区R[0..i-1]中,此时可以采用折半查找方法先在R[0..i-1]中找到插入位置,再通过移动元素进行插入。这样的插入排序称为折半插入排序或二分插入排序。


Java实现:

public class Main{
	public static void main(String[] args){
		//待排序的数组
		int[] numbers = {3,56,12,456,5,23,16,15,56,456};
		int i,j,temp,low,high,mid;
		for(i = 1;i < numbers.length;i++){
			temp = numbers[i];
			j = i - 1;
			low = 0;
			high = j;
			//通过折半查找插入的位置
			while(low <= high){
				mid = (low + high)/2;
				if(numbers[mid] < temp)
					low = mid+1;
				else
					high = mid-1;
			}
			//元素后移
			for(j = i - 1;j >= high + 1;j--){
				numbers[j+1] = numbers[j];
			}
			numbers[high + 1] = temp;
		}
		//输出排序后的数组
		for(int number : numbers){
			System.out.print(number + " ");
		}
	}
	
}

3.希尔排序(不稳定)

思路:希尔排序实际上是一种分组插入方法。其基本思想是:先取定一个小于n的整数d1(一般为n/2)作为第一个增量,把表的全部元素分成d1个组,所有相互之间距离为d1的倍数的元素放在同一个组中,在各组内进行直接插入排序;然后,取第二个增量d2(<d1,一般为d1/2),重复上述的分组和排序过程,直至所取的增量dt=1(dt<dt-1<...<d2<d1),即所有元素放在同一组中进行插入排序。


java实现:

public class Main{
	public static void main(String[] args){
		//待排序的数组
		int[] numbers = {3,56,12,456,5,23,16,15,56,456};
		int i,j,temp,gap;
		//增量置初值
		gap = numbers.length / 2;
		while(gap > 0){
			//对所有相隔gap位置的元素组采用直接插入排序
			for(i = gap;i < numbers.length;i++){
				temp = numbers[i];
				j = i - gap;
				//对相隔gap位置的元素组进行排序
				while(j >= 0 && temp < numbers[j]){
					numbers[j+gap] = numbers[j];
					j -= gap;
				}
				numbers[j+gap] = temp;
			}
			//减小增量
			gap = gap/2;
		}
		//输出排序后的数组
		for(int number : numbers){
			System.out.print(number + " ");
		}
	}
	
}


交换排序


1.冒泡排序(稳定)

路:通过无序区中相邻元素间关键字的比较和位置的交换,使关键字最小的元素如气泡一般逐渐往上“漂浮”直至“水面”。整个算法是从最下面的元素开始,对每两个相邻的关键字进行比较,且使关键字较小的元素换至关键字较大的元素之上,使得经过一趟冒泡排序后,关键字最小的元素到达上端。接着,再在剩下的元素中找关键字次小的元素,并把它换到第二个位置上。以此类推,一直到所有元素都有序为止。


java实现:

public class Main{
	public static void main(String[] args){
		//待排序的数组
		int[] numbers = {3,56,12,456,5,23,16,15,56,456};
		int i,j,temp;
		boolean exchange = false; 
		//比较,找出关键字最小的元素
		for(i = 0;i < numbers.length - 1;i++){
			for(j = numbers.length - 1; j > i;j--){
				if(numbers[j-1] > numbers[j]){
					//将numbers[j-1]与numbers[j]进行交换,将关键字最小的往前移
					temp = numbers[j-1];
					numbers[j-1] = numbers[j];
					numbers[j] = temp;
					exchange = true;
				}
			}
			//若本趟没有发生交换,中途结束算法
			if(!exchange)
				break;
		}
		for(int number : numbers){
			System.out.print(number + " ");
		}
	}
}

2.快速排序(不稳定)

思路:快速排序是由冒泡排序改进而得的,他的基本思想是:在待排序的n个元素中任取一个元素(通常取第一个元素)作为基准,把该元素放入适当位置后,数据序列被此元素划分成两部分,所有关键字比该元素关键字小的元素放置在前一部分,所有关键字比它大的元素放置在后一部分,并把该元素排在这两部分的中间(称该元素归位),这个过程称做一趟快速排序,之后对所有划分出来的两部分分别重复上述过程,直至每部分内只有一个元素或为空为止。


java实现:

public class Main{
	public static void main(String[] args){
		//待排序的数组
		int[] numbers = {3,56,12,456,5,23,16,15,56,456};
		QuickSort(numbers,0,numbers.length-1);
		for(int number : numbers){
			System.out.print(number + " ");
		}
	}
	public static void QuickSort(int[] numbers,int s,int t){
		int i = s,j = t,temp;
		//区间内至少存在两个元素的情况
		if(s < t){
			//用区间的第一个元素作为基准
			temp = numbers[s];
			//从区间两端交替向中间扫描,直至i = j为止
			while(i != j){
				//从右向左扫描,找第一个小于temp的numbers[j]
				while(j > i && numbers[j] >= temp){
					j--;
				}
				//找到这样的numbers[j],numbers[i]与numbers[j]交换
				numbers[i] = numbers[j];
				//从左向右扫描,找第一个大于temp的numbers[i]
				while(j > i && numbers[i] <= temp){
					i++;
				}
				//找到这样的numbers[i],numbers[i]与numbers[j]交换
				numbers[j] = numbers[i];
			}
			numbers[i] = temp;
			//对左区间递归排序
			QuickSort(numbers,s,i-1);
			//对右区间递归排序
			QuickSort(numbers,i+1,t);
		}
	}
}



参考文献:

数据结构教程/李春葆主编 -北京:清华大学出版社,2013.1

软件设计师教程/褚华主编 -北京:清华大学出版社,2014

猜你喜欢

转载自blog.csdn.net/java_mike/article/details/77505212