排序算法(一):基础排序算法(基于暴力的排序算法)
基础排序算法(基于暴力的排序算法)
排序本质:逐步减少逆序对
在基础排序算法中,将待排序序列分为相对有序区与相对无序区。
每次遍历到数组末尾称为一轮。
冒泡排序(无序区-有序区, O ( n 2 ) O(n^2) O(n2),稳定,就地)
算法流程:在每轮中逐个比较相邻项,并将相对最值置后。因此在每轮中,无序区将有 1 1 1个元素进入有序区(最后一轮2个元素同时进入有序区),进入有序区的为无序区当前最值,且进入有序区的元素呈单调性,轮数=有序区元素个数,有序区首元素即为 n − j n-j n−j。最后一轮同时将 2 2 2个元素完成排序,因此最多仅需遍历 n − 1 n-1 n−1轮。
vector<int>a(n);
void bubble_sort(){
for(int i=0;i<n-1;i++)//冒泡轮数=有序区元素个数
for(int j=0;j<n-1-i;j++)//当前工作指针 n-1-j:有序区首元素下标
if(a[j]>a[j+1]) swap(a[j],a[j+1]);//降序为<
}
选择排序(有序区-无序区, O ( n 2 ) O(n^2) O(n2),不稳定,就地)
算法流程:在每轮中,将无序区中最值元素放到无序区的首位置,无序区首元素成为有序区末尾,因此轮数=无序区首元素下标。
vector<int>a(n);
void choice_sort(){
for(int i=0;i<n-1;i++){//轮数=无序区首元素下标
//c
int min=i;//假定无序区首元素为最值(以最小值为例)
for(int j=i+1;j<n;j++)//获取无序区最值元素下标
if(a[j]<a[min]) min=j;
//cpp
int min=min_element(a.begin()+i+1,a.end())-a.begin();
swap(a[i],a[min]);//将最小值放在无序区首元素
}
}
插入排序
直接插入排序(有序区-无序区, O ( n 2 ) O(n^2) O(n2),稳定,就地)
算法流程:对于每轮在有序区中逆序遍历,以寻找无序区首元素的合适插入点。
vector<int>a(n);
void insert_sort(){
for(int i=1;i<MAX;i++){//i:轮数=无序区首元素下标(默认a[0]自己即为有序,因此从1开始)
int temp=a[i],j;
for(j=i-1;j>=0;j--)//逆序遍历有序区(有序区下标j=i-1)
if(temp<a[j]) a[j+1]=a[j];
else break;
a[j+1]=temp;//a[j+1]>temp>a[j]
}
}
优化:二分插入排序( O ( n 2 ) O(n^2) O(n2),稳定,就地)
由于有序区已经是有序的,因此寻找插入点时可采用二分优化,但复杂度不变
vector<int>a(n);
void insert_sort(){
for(int i=1;i<n;i++){
int temp=a[i];
//c
int l=0,r=i-1,m;
while(l<=r){
m=l+r>>1;
if(t<a[m]) r=m-1;
else l=m+1;
}
//cpp
int l=upper_bound(a.begin(),a.begin()+i-1)-a.begin();
//已找到插入点l
for(int j=i-1;j>=l;j--) a[j+1]=a[j];
a[l]=t;
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具