最近在刷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是效率较高的,尤其是当排序的数量较多时,但需要额外的系统资源。
***华丽的分割线结束***码字不易,大神勿喷,欢迎指正。