排序算法
1.比较类排序
通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此也称为非线性时间比较类排序
2.非比较类排序(一般用于整型相关的数据类型)
不通过比较来决定元素间的相对次序,它可以突破基于比较排序的时间下界,以线性时间运行,因此也称为线性时间非比较类排序。
初级排序(O(n^2))
1.选择排序
每次找最小值,然后放到待排序数组的起始位置
2.插入排序
从前到后 逐步构建有序序列;对于未排序的数列,在已排序序列中从后向前扫描,找到相应位置并插入。
3.冒泡排序
嵌套循环,每次查看相邻元素,如果逆序,那么交换、
高级排序(O(nlogn))
- 快速排序
数组取标杆pivot,将小元素放pivot左边,大元素放右边,然后,依次对左边和右边的子数组继续快排;以到达这个序列有序。
public static void quicksort(int[] arr,int begin,int end){
if(begin>end){
return ;
}
int pivot=splitproblem(arr,begin,end);
quicksort(arr,begin,pivot-1);
quicksort(arr,pivot+1,end);
}
private static int splitproblem(int[] ints, int start, int end) {
//prvot 标杆位置 count 计数器
int prvot=end,count=start;
for (int i = start; i < end; i++) {
if(ints[prvot]>ints[i]){
int i1 = ints[count];
ints[count]=ints[i];
ints[i]=i1;
count++;
}
}
int temp=ints[prvot];
ints[prvot]=ints[count];
ints[count]=temp;
return count;
}
- 归并排序(分治思想)
1.把长度为n的输入序列分成两个长度为n/2的子序列
2.对这两个子序列分别采用归并排序
3.将两个排序好的子序列合并成一个最终的排序序列。
private static void mergeSort(int[] ints, int right, int left) {
if(right<=left) return;
int mid=(right+left)/2;
mergeSort(ints,right,mid);
mergeSort(ints, mid + 1, left);
meage(ints,left,mid,right);
}
private static void meage(int[] ints, int left, int mid, int right) {
int[] temp = new int[right - left + 1];
int i=left,j=mid+1,k=0;
while (i<=mid&&j<=right){
temp[k++]=ints[i]<=ints[j]?ints[i++]:ints[j++];
}
while (i<=mid) temp[k++]=ints[i++];
while (j<=right) temp[k++]=ints[j++];
for (int p = 0; p < temp.length; p++) {
ints[left+p]=temp[p];
}
}
归并与快排具有相似性,但步骤顺序相反。
归并:先排序左右子数组,然后合并两个有序子数组
快排:先调配出左右子数组,然后对于左右子数组进行排序
堆排序
- 堆插入O(logN),取最大/小值O(1)
1.数组元素依次建立小顶堆
2.依次取栈顶元素,并删除
计数排序
计数排序要求输入的数据必须是有确定范围的整数。将输入的数据值转化为键存储在额外开辟的数组空间中;然后依次把计数大于1的填充回原数组。
桶排序
桶排序的工作原理:假设输入数据服从均匀分布,将数据分到有限数量的桶里面,每个桶在分别排序。
基数排序
基数排序是按照低为先排序,然后收集,再按照高位排序,然后再收集;依次类推,直到最高位。有时候有些属性是有优先级顺序的,先按低优先级排序的,再按高优先级排序。