排序算法总结

最近在刷leetcode,被虐n次之后决定先搞一下基础建设,把排序整理一下。差不多两天的时间(主要是快速排序把我搞到头大),终于出了一篇比较简陋的笔记。暂且看着,留着后面用。

***华丽的分割线,下面是笔记***

各类排序算法总结

交换排序,选择排序,插入排序,合并排序

基本排序(直接对内存中的 数据进行排序)

交换排序

选择排序

插入排序

合并排序

冒泡排序

快速排序

选择排序

堆排序

插入排序

Shell排序

             

 

若对于一些大的 文件,采用 多路归并排序。将文件分为几个能读入内存的小部分,然后分别读入进行排序。

*** 分隔线*** 

冒泡排序

比较简单,原理这里不写了就。复杂度:average和worst都是O(n2)。

选择排序

进行n-1次循环,每次循环都找出剩余数组里最小的一个,然后跟当前元素互换。

                复杂度:average和worst都是O(n2)。

                代码:

public void selectSort(int[] arr)
	{
		for(int i=0;i

插入排序

                思想流程:

                1)先把前两个数据排好序。

                2)将第三个数据插入到前面排好序的数组里。

                3)以此类推。

                思想很简单,就是把后面紧挨的数往前扫,如果被扫的数比这个数大,就存到后面去,直到发现一个比这个数小的就停止。

                说的不清楚。。。上代码:

public static void insertSort(int[] a)
	{
		int len = a.length;
		for(int i=1;i=0;j--)
			{
				if(a[j]>=temp)
				{
					a[j+1] = a[j];
				}
				else
				{
					break;
				}
			}
			a[j+1] = temp;
		}
	}

               

Shell排序:虽然不知道为什么叫Shell排序。。。

根据Shell排序的思想,自己写的代码跟书上的不太一样。

                排序流程如下:

                1) 将n个元素的数组分成n/2个数字序列,比如8个数字除以2是4个数字序列,然后第一个数据和第n/2+1个数据为一对。。。

                2)依次循环是每一个序列对排好顺序。

                3)然后再变为n/4个序列,再次排序。这里我没太懂,我的代码理解是以n/4为间隔划分整个数组,然后依次比较每一对组合的大小,小的放前面,大的 放后面。书中用的是插入排序,好混乱不懂==

                4)不断重复上述过程,直到序列减少为最后一个。我的理解是序列间隔最后变为1,这样每相邻两个数字都是有序的 ,所以整个数组就是有序的了。

                上代码:注释部分是书上的代码。

               

public static void shellSort(int[] arr)
	{
		int len = arr.length;
//		for(int r = len/2;r>=1;r/=2)
//		{
//			for(int i=r;i=0 && temp=1;r/=2)
		{
			for(int i=0;iarr[i+r])
				{
					int temp = arr[i];
					arr[i] = arr[i+r];
					arr[i+r] = temp;
				}
			}
		}
	}

QuickSort快速排序

                思路:找一个基准元素,随便哪个都可以,然后把比它小的数字都排到左边,比它大的数字都排到右边。然后递归。快速排序可以被形容为:挖坑填数+分治法。

                先上代码:

               

public static void quickSort(int[] arr, int left, int right)
	{
		if(left < right)
		{
			int i = left;
			int j = right;
			int base = arr[left];
			
			while(i=base && i

While是为了挖坑填数,填好一层后用递归分治。

                几点注意:在内层有个if判断,它的用途是为了防止如果j从后往前找没找到比arr[i]小 的数,这个时候就不用填数然后移动i了,否则在大while结束后给arr[i]赋值时会赋错位置。

 

归并排序

                思路:把数组分成两个部分排序,排好之后再把两个部分合起来。如果被分的 两个部分还可以继续分,则分至最小后排序,然后合并。

                上代码:

public static void mergeSort(int[] arr,int first, int last)
	{
		if(first>=last)
			return;
		int mid = (first+last)/2;
		
		mergeSort(arr,first,mid);
		mergeSort(arr,mid+1,last);
		mergeArray(arr,first,mid,last);
	}
	
	public static void mergeArray(int[] arr, int first, int mid, int last)
	{
		int i = first;
		int j = mid+1;
		
		int[] temp = new int[last-first+1];
		
		int k = 0;
		while(i<=mid && j<=last)
		{
			temp[k++] = arr[i]

               

mergeArray负责把排好序的两个部分合并成一个部分,然后返回到上一级mergeSort继续合并。

关键点:在整个数组中,分组是靠下标实现的。

 

总结

归并排序的空间复杂度为O(n),其余都大部分都是O(1)。

时间复杂度总结:

 

Average

Worst

Bubble Sort

N2

N2

Select Sort

N2

N2

Insert Sort

N2

N2

Quick Sort

nlogn

N2

Shell Sort

N3/2

N2

Merge Sort

nlogn

Nlogn

 

由此可以看出,mergesort是效率较高的,尤其是当排序的数量较多时,但需要额外的系统资源。

***华丽的分割线结束***


码字不易,大神勿喷,欢迎指正。

你可能感兴趣的:(排序算法,插入排序,归并排序,快速排序,冒泡排序)