【算法】【排序模块】插入排序和快速排序
前言
当前所有算法都使用测试用例运行过,但是不保证100%的测试用例,如果存在问题务必联系批评指正~
在此感谢左大神让我对算法有了新的感悟认识!
问题介绍
原问题
使用插入排序和快速排序对整数数组进行排序计算
解决方案
插入排序(从小到大):
从第二个节点开始:
1、找到前面节点中第一个比自己小的数,记录index
2、从当前节点开始,将前一个元素替换掉当前元素,直到替换到前一个元素是index的时候停止
3、将当前节点赋值给index的后一个元素上即可
时间:O(n^2) 空间O(1)
是否稳定排序:是
是否原地排序:是
快速排序:
1、找到第一个元素作为轴,两边开始中间遍历,比轴大的放轴右边,比轴小的放轴左边
2、结束后通过轴将数组分为两个子数组,分别继续递归即可
时间:O(nlogn ~ n^2), 平均 nlogn 空间 O(logn)
是否稳定排序:是
是否原地排序:否
代码编写
java语言版本
插入排序:
/**
* 插入排序
* @param arr
* @return
*/
public static int[] insertSortCP(int[] arr){
if (arr == null || arr.length == 1){
return arr;
}
for (int i = 1; i < arr.length; i++){
// 查询i应该放在哪?
int index = i;
int value = arr[i];
// 往前找到第一个小于index的坐标
while (index >= 0 && arr[index] >= arr[i]){
index--;
}
// index可能是-1
index++;
int temIndex = i;
while (temIndex > index){
arr[temIndex] = arr[temIndex-1];
temIndex--;
}
arr[index] = value;
}
return arr;
}
public static void main(String[] args) {
int[] arr = {3, 4, 1, 5, 6, 8, 9};
int[] ints = InsertSort(arr, (byte) 0);
CommonUtils.printArr(ints);
}
/**
* 插入排序(稳定版本)
* @param arr
* @return
*/
public static int[] insertSortStable(int[] arr){
if (arr == null || arr.length == 1){
return arr;
}
for (int i = 1; i < arr.length; i++){
// 查询i应该放在哪?
int index = i;
int value = arr[i];
// 往前找到第一个小于index的坐标
while (index-1 >= 0 && value < arr[index-1]){
arr[index] = arr[index - 1];
index--;
}
arr[index] = value;
}
return arr;
}
public static void main(String[] args) {
int[] arr = {3, 4, 1, 5, 2, 8, 6, 9};
int[] ints = insertSortStable(arr);
CommonUtils.printArr(ints);
}
快速排序:
/**
* 快速排序(二轮) 非稳定排序,非原地排序
* @param arr
* @return
*/
public static int[] quickSortCP(int[] arr){
if (arr == null || arr.length == 1){
return arr;
}
quickSortCP1(arr, 0, arr.length - 1);
return arr;
}
private static void quickSortCP1(int[] arr, int left, int right) {
if (left >= right){
return;
}
int midIndex = getMidIndexForQuickSort(arr, left, right);
quickSortCP1(arr, left, midIndex - 1);
quickSortCP1(arr, midIndex+1, right);
}
private static int getMidIndexForQuickSort(int[] arr, int left, int right) {
// 正常默认取第一个值
int mid = arr[left];
int leftIndex = left+1;
int rightIndex = right;
while (true){
// 找到左边第一个大于等于mid的
while (leftIndex <= rightIndex && arr[leftIndex] < mid){
leftIndex++;
}
// 找到右边第一个小于mid的
while (leftIndex <= rightIndex && arr[rightIndex] > mid){
rightIndex--;
}
if (leftIndex > rightIndex){
break;
}
CommonUtils.swap(arr, leftIndex, rightIndex);
leftIndex++;
rightIndex--;
}
CommonUtils.swap(arr, rightIndex, left);
return rightIndex;
}
c语言版本
正在学习中
c++语言版本
正在学习中
思考感悟
快速排序在写的时候自己给的测试用例基本是有序的,所以发现,基本有序的时候总会有一边空循环一遍,所以最坏情况是O(n^2),其实java中的TimSort方法,也就是Collection集合的默认排序,java认为业务中大多数的排序元素都是基本有序的或者部分有序的,所以,也针对这种现象做了一定的merge优化。
插入排序其实我写的版本是一种不稳定的版本,不知道大家有没有发现,其实 while (index >= 0 && arr[index] >= arr[i]){这里相等情况,index还是会移动,所以前面相等的元素会被移动到当前元素的后面导致不稳定,所以插排有稳定的版本,提供给大家。
写在最后
方案和代码仅提供学习和思考使用,切勿随意滥用!如有错误和不合理的地方,务必批评指正~
如果需要git源码可邮件给2260755767@qq.com
再次感谢左大神对我算法的指点迷津!
相关文章
- Java实现 蓝桥杯VIP 算法训练 连续正整数的和
- 网易机器学习算法工程师笔试编程题
- 关于推荐算法的一些思考
- [算法]Bobmer
- OpenCV每日函数 计算摄影模块(1) 图像修复算法 inpaint函数
- Opencv每日函数 图像分割模块 watershed分水岭算法
- OpenCV每日函数 白平衡相关算法
- [YOLOv7/YOLOv5系列算法改进NO.15]网络轻量化方法深度可分离卷积
- 【YOLOv8/YOLOv7/YOLOv5/YOLOv4/Faster-rcnn系列算法改进NO.63】结合CVPR 2023 即插即用动态稀疏注意力BiFormer模块
- 【YOLOv8/YOLOv7/YOLOv5/YOLOv4/Faster-rcnn系列算法改进NO.62】结合NeurIPS 2022年GhostnetV2网络模块
- 【转】MySQL索引背后的数据结构及算法原理
- 技术解读丨目标检测之RepPoints系列算法
- 信息共享的记忆被囊群算法-附代码
- 1371. 每个元音包含偶数次的最长子字符串-贪心算法-状态保存
- 递归算法
- 图论---最小生成树----普利姆(Prim)算法
- 算法题中的各种边界情况
- BFPRT 算法 (TOP-K 问题)——本质就是在利用分组中位数的中位数来找到较快排更合适的pivot元素
- 十大算法 — 选择排序法【C语言代码诠释】