直接插入排序:
排序思想:先假定前面有序,从第二个开始,将后面的所有数据插入到有序数组中去。
算法思想如果大时就交换:
public void insertSort(int[] a){
int temp = 0;
for(int i=1;i<a.length;i++){
temp = a[i];
for(int j=i-1;j>-1&&temp<a[j];j--){
//大的时候往后排,找插入位置
a[j+1]=a[j];
}
a[j+1]=temp;
}
希尔排序:是高级的直接插入排序
排序思想:
按步长grap(grap>1)进行分组,每组采用直接插入排序,步长不断缩小每次除2,先分组在排序
public void shellSort(int[] a){
//定义步长
int grap = a.length/2;
//定义中间变量
while(grap>1){
//分组,按照grap间隔进行分组
for(int i=grap;i<a.length;i++){
int temp = a[i];
for(int j = i-grap;j>-1&&temp<a[j];j=j-grap){
a[j+grap]=a[j];
}
//插入的位置
a[j+grap] = temp;
}
grap = grap /2;
}
}
简单选择排序:
排序思想:每次从待排序列中选择最小的放在最下的
public void selectSort(int[] a){
int temp = 0;
for(int i=0;i<a.length-1;i++){
for(int j=i+1;j<a.length;j++){
if(a[j]<a[i]){
temp = a[i];
a[i]=a[j];
a[j]=temp;
}
}
}
}
//下标标识,交换内存比较浪费资源
public void selectSort(int[] a){
int temp = 0;
int kmin = 0;
for(int i=0;i<a.length-1;i++){
kmin = i;
for(int j=i+1;j<a.length;j++){
if(a[j]<a[kmin]){
kmin = j;
}
//如果没有小的就不交换
if(i-kmin){
temp = a[kmin];
a[kmin] = a[i];
a[i] = temp;
}
}
}
}
堆排序:
思想:先把数据存入数组当中去,从1开始存,调整成堆,每次把最大的交换到最上面,然后和end所在位置交换,end--,在进行排序。
public void heapSort(int a[]){
//end:用于标识最后一个位置,pa用于标识end的父亲,t用于交换end和第一个,tag标识是否交换了,如果未交换就表示不需要调整了
int end,pa,t,tag;
//end指向最后一个
end = a.length;
while(end>1){
//调整成堆,默认调整,如果未调整就break,表示上面是最小的
while(1){
// pa要大于0
for(pa=end/2,tag=0;pa>0;pa--){
//比较左子女
if(a[pa]<a[pa*2]){
t = a[pa];
a[pa] = a[pa*2];
a[pa*2] = t;
tag = 1;
}
//比较右子女
if(pa*2+1<end&&a[pa]<a[pa*2+1]){
t = a[pa];
a[pa] = a[pa*2+1];
a[pa*2+1] = t;
tag = 1;
}
}
if(tag==0) break;
}
t = a[1];
a[1] = a[end];
a[end] = t;
//去掉最后一个页子
end -- ;
}
}
交换类排序:
冒泡排序:
第一个循环控制趟数,第二个循环比较排序
public void bubbleSort(int[] nums){
int temp = 0;
for(int i=0;i<nums.length-1;i++){
for(int j=0;j<nums.length-1-i;j++){
if(nums[j]>nums[j+1]){
temp = nums[j];
nums[j] = nums[j+1];
nums[j+1] = temp;
}
}
}
}
快速排序:
package Sort;
public class SortUtils {
/**
* 快速排序
* 分为三个步骤:找基准点,***切记从右往左先跑,找小于基准点的停,从左往右找大于基准点的停
* 左递归,右递归
* @param arr 待排序的数组
* @param left 左位置
* @param right 右位置
*/
public static void quickSort(int[] arr,int left,int right){
//如果left小于right,那么循环结束
if(left>=right){
return;
}
// 取最左面的作为基准点
int p = arr[left];
// 初始化i,j的位置
int i=left,j=right;
// 目的是把比p小的放在p前面,把比p大的放在p后面
//当前面的小于后面时
while(i<j){
// 从后面找小的
while(arr[j]>=p&&i<j){
j--;
}
// 从前边找大的,左移找大的
while(arr[i]<=p&&i<j){
i++;
}
// 如果i<j时,那么就进行交换
if(i<j){
int temp = arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
// 交换位置
arr[left] = arr[i];
arr[i]=p;
// 进行递归左面排序
quickSort(arr,left,i-1);
// 进行递归右面排序
quickSort(arr,i+1,right);
}
/**
* @Author:LiuRuidong
* @Description: 归并排序,应用的是分治算法
* @Date:2018/2/27 15:31
* @Param:
* @return
*/
public static void mergeSort(int[] arr){
int[] temp = new int[arr.length];
mSort(arr,0,arr.length-1,temp);
}
private static void mSort(int[] arr,int left,int right,int[] temp ){
if(left<right){
// 分开
int mid = (left+right)/2;
// 左边进行排序
mSort(arr,left,mid,temp);
// 右边进行排序
mSort(arr,mid+1,right,temp);
// 治合
merge(arr,left,right,mid,temp);
}
}
private static void merge(int[] arr,int left,int right,int mid,int[] temp){
int i = left;
int j = mid+1;
int t = 0;
// i往mid跑,j往right跑
while(i<=mid&&j<=right){
if (arr[i]<=arr[j]){
temp[t++] = arr[i++];
}else{
temp[t++] = arr[j++];
}
}
while(i<=mid){
temp[t++] = arr[i++];
}
while(j<=right){
temp[t++] = arr[j++];
}
// 拷贝到另一个队列当中
t = 0;
while(left<=right){
arr[left++]=temp[t++];
}
}
}
时间复杂度计算:
遍历一遍是O(n),堆排序算法思想是建堆,见一次比较log(n)次,树的高度次,然后需要建(n-2)/2次,所以为nlogn
对于快排也是类似的思想,递归的时间复杂度:递归层数*log(n),最坏每次最大的最后面,o(n2)
快排的优化:查找中位数,当递归一定层数时采用 插入排序