排序插入
原理:
把待排序数组里面的数,一个个拿出来,插入到一个有序数组的合适的位置。最后这个有序数组里面的数就是我们要的结果了。
问题:有序数组从哪来的?
技巧:初始状态,你可以认为待排序数组的第一个数就是一个有序数组(因为他只有一个数,当然是有序数组)
算法:
从数组的第二个数开始一个个拿出来,
拿到一个数(array[i])后,
从i-1到0遍历数组,
拿到第j个数array[j] ,将他与array[i]比较,
如果 array[j] > array[i],则将 array[j] 后移一个位置
否则 break 这个遍历
将 array[i] 放到 j+1 这个位置
思路:
一组数据分成已排序和未排序区间,将未排序区间插入到已排序区间完成排序
时间复杂度:O(n²)
空间复杂度:O(1)
排序归并
归并排序就是将原来的数组分为两个小的数组就行排序之后进行合并,因为常常使用递归实现(由先拆分后合并的性质决定的),所以我们称其为归并排序。
归并操作的工作原理
第一步:申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
第二步:设定两个指针,最初位置分别为两个已经排序序列的起始位置
第三步:比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
重复步骤3直到某一指针超出序列尾
将另一序列剩下的所有元素直接复制到合并序列尾
抽象过程
- 对于一个大小为n的待排序数组,将其划分为n个小数组,即每个数划分为一个数组,对于只有一个元素的数组,那么该数组有序。
- 有序合并相邻相同大小的数组,即合并两个有序数组为一个有序数组。
- 循环上一步直到所有小数组合并到一个数组中为止。
- 此时排序就已经在不断的有序中完成,数组有序。
比方你把a=[3,2,6] 这个数组,拆为三个数组,放到一个大数组里面去b=[[3],[2],[6]],
这个时候就可以guibin([3],[2]) 得到 [2,3],
再guibin([2,3],[6]) 得到[2,3,6]
a=[3,2,6,1,5]
初始 b=[[3],[2],[6],[1],[5]]
while(b长度>1){
//新 c=...
//第一轮c=[[2,3],[1,6],[5]]
//第二轮c=[[1,2,3,6],[5]]
//第三轮c=[1,2,3,5,6]]
b=c
}
思路:
将一组数据对半拆分完成排序后合并
时间复杂度O(nlogn)
空间复杂度O(n)
稳定性:稳定
排序快排
原理:
从待排序数组里面取第一数,想办法把比这个数小的放到左边,把比他大的放到右边。接着对左边的数组做同样的操作,对右边的数组也做同样的操作。继续这么递归下去。最后就排好了。
基本操作单元算法:
1)指针j从数组最后一个数开始往左移动,直到找到一个比第一个数小的数,或者j=i
2)指针i从数组第二个数往右移动,直到找到一个比第一个数大的数,或者j=i
3)如果i==j,交换数组第一个数与第i个数;否则交换第i个数与第j个数
重复123直到i=j
如果第一个数大于于第i个数,将这两个数交换
public static int【】 qiuckSort(int arry【】,int begin,int last){
if(begin>last){
return null;
}
int a=begin;
int b=last;
int pivot=arry【begin】;
while (begin<last) {
while (begin<last&&pivot<=arry【last】){
last--;
}
if(pivot>arry【last】){
arry【begin】=arry【last】;
begin++;
}
if(begin==last){
arry【begin】=pivot;
break;
}
while (begin<last&&arry【begin】<pivot){
begin++;
}
if(pivot<arry【begin】){
arry【last】=arry【begin】;
last--;
}
if(begin==last){
arry【begin】=pivot;
}
}
if(last>a){qiuckSort(arry,a,last-1);}
if(b>begin){qiuckSort(arry,begin+1,b);}
return arry;
}
基本思想
1.选定Pivot中心轴
2.将大于Pivot的数字放在Pivot的右边
3.将小于Pivot的数字放在Pivot的左边
4.分别对左右子序列重复前三步操作