十大排序算法
冒泡排序:
稳定排序,时间复杂度O(n)
void BubbleSort(int[] nums){
int len=nums.length;
for(int i=0;i<len;i++){
for(int j=0;j<len-1-i;j++){
if(nums[j]>nums[j+1]){ //稳定,相等前后不交换
int temp=nums[j];
nums[j]=nums[j+1];
nums[j+1]=temp;
}
}
}
}
选择排序:
稳定排序,时间复杂度O(n)
void selectSort(int[] nums){
int len=nums.length;
for(int i=0;i<len-1;i++){
int minIndex=i;
for(int j=i;j<len;j++){
if(nums[j]<nums[minIndex]){//稳定排序
minIndex=j;
}
}
int temp=nums[i];
nums[i]=nums[minIndex];
nums[minIndex]=temp;
}
}
插入排序
稳定排序,时间复杂度O(n)
void inserSort(int[] nums){
int len=nums.length;
for (int i = 0; i < len; i++) {
int temp=nums[i];
int j=i-1;
for(;j>=0&&nums[j]>temp;j--){
nums[j+1]=nums[j];
}
nums[j+1]=temp;
}
}
归并排序
稳定排序,时间复杂度O(nlogn)
图解原理
注意点
- 将大问题分解为小问题
- 将处理后的小问题进行合并
- 需要额外的数组存储零时的数据 temp[],temp中存储排序好的数组,处理完,将有序数组进行复制
代码实现
void mergeSort(int[] nums,int[] temp,int left,int right){
if(left<right){
int mid=(left+right)/2;
// 1. 分解
mergeSort(nums,temp,left,mid);
mergeSort(nums,temp,mid+1,right);
// 2. 俩个有序数组合并
merge(nums,temp,left,mid,right);
}
}
static void merge(int[] nums, int[] temp, int left, int mid, int right) {
int i = left;//左序列指针
int j = mid+1;//右序列指针
int t = 0;//临时数组指针
while (i<=mid && j<=right){
if(nums[i]<=nums[j]){
temp[t++] = nums[i++];
}else {
temp[t++] = nums[j++];
}
}
while(i<=mid){//将左边剩余元素填充进temp中
temp[t++] = nums[i++];
}
while(j<=right){//将右序列剩余元素填充进temp中
temp[t++] = nums[j++];
}
t = 0;
//将temp中的元素全部拷贝到原数组中
while(left <= right){
nums[left++] = temp[t++];
}
}
快速排序:
不稳定排序,时间复杂度O(nlogn)
static void quickSort(int[] nums,int left,int right){
if(left<right){
int mid=partation(nums,left,right);
quickSort(nums,left,mid-1);
quickSort(nums,mid+1,right);
}
}
static int partation(int[] nums,int left,int right){
int temp=nums[left];
while(left<right){
while(left<right&&nums[right]>=temp){
right--;
}
nums[left]=nums[right];
while(left<right&&nums[left]<=temp){
left++;
}
nums[right]=nums[left];
}
nums[left]=temp;
return left;
}
堆排序
class Solution {
void swap(int[] nums,int i,int j){
int temp=nums[i];
nums[i]=nums[j];
nums[j]=temp;
}
void heapify(int[] nums,int k,int i){
int smallest=i;
int left=2*i+1;
int right=2*i+2;
if(left<k&&nums[smallest]>nums[left]){
smallest=left;
}
if(right<k&&nums[smallest]>nums[right]){
smallest=right;
}
if(smallest!=i){
swap(nums,i,smallest);
heapify(nums,k,smallest);
}
}
public int findKthLargest(int[] nums, int k) {
// 建立k个元素小根堆
for(int i=k/2-1;i>=0;i--){
heapify(nums,k,i);
}
// 与第一个元素比较并调整
for(int i=k;i<nums.length;i++){
if(nums[0]<nums[i]){
swap(nums,0,i);
heapify(nums,k,0);
}
}
// 返回第一个元素
return nums[0];
}
}
- 选择排序
- 思想:首先存在一个数组,i 从左到右开始进行遍历,j选择i后边的元素,并记录最小元素的下标,当j结束后进行交换。直到i遍历结束。
- 伪代码:
nums = [1, 25, 8, 9, 4, 7] for i = 0 to length of nums - 1 minIndex = i for j = i + 1 to length of nums if nums[minIndex] > nums[j] minIndex = j swap(nums, i, minIndex)
- 时间空间复杂度:n^2、1
- 为什么选择排序是不稳定的?
6*,6,2,3,8
->2,3,6,6*,8
- 快速排序
- 思想:每次选择一个元素,放在最终的位置
- 伪代码:
procedure quickSort(nums: array of integers, left: integer, right: integer) if left < right then mid := partation(nums, left, right) quickSort(nums, left, mid - 1) quickSort(nums, mid + 1, right) procedure partation(nums: array of integers, left: integer, right: integer) returns integer temp := nums[left] while left < right do while left < right and nums[right] >= temp do right := right - 1 nums[left] := nums[right] while left < right and nums[left] <= temp do left := left + 1 nums[right] := nums[left] nums[left] := temp return left
- 为什么是不稳定的?
8 3 6 3*
->3* 3 6 8
- 插入排序
- 思想:选择元素插入合适位置,前面是有序的,后面是无序的
- 伪代码:
for i = 0 to length of nums - 1 target := nums[i] j := i - 1 while j >= 0 and nums[j] > target nums[j + 1] := nums[j] j := j - 1 nums[j + 1] := target
- 时间空间复杂度:n^2、1
- 是否稳定:稳定排序
本文来自博客园,作者:帅气的涛啊,转载请注明原文链接:https://www.cnblogs.com/handsometaoa/p/16013055.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!