排序算法专题总结
分治基础-二分查找:
二分查找是一种高效的查找算法
先找到数组的中间位置mid,判断
(1)如果要找的数x==a[mid]找到了,mid就是位置
(2)如果要找的教x>a[mid],说明要找的数在后一半,递归在后一半找
(3)如果要找的数x<a[mid],说明要找的数在前一半,递归在前一半找在下标为left~right之间的范围内找数,mid=(left+right)/2当left<=right就一直找,直到找到了,或者left>right(找不到)
模板:
// 区间[l, r]被划分成[l, mid]和[mid + 1, r]时使用:
int bsearch_1(int l, int r)
{
while (l < r)
{
int mid = l + r >> 1;
if (check(mid)) r = mid; // check()判断mid是否满足性质
else l = mid + 1;
}
return l;
}
// 区间[l, r]被划分成[l, mid - 1]和[mid, r]时使用:
int bsearch_2(int l, int r)
{
while (l < r)
{
int mid = l + r + 1 >> 1;
if (check(mid)) l = mid;
else r = mid - 1;
}
return l;
}
————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————快速排序:
快速排序是一种高效的排序算法,其基本思想是通过选择一个基准元素,将数组划分为两个子数组,一个包含所有小于基准元素的元素,另一个包含所有大于基准元素的元素,然后递归地对这两个子数组进行快速排序。
快速排序的基本步骤
1.选择基准元素:通常选择数组的第一个元素作为基准元素,但也可以随机选择或使用“三数取中法”来避免最坏情况。
2.分区操作:将数组中的元素根据与基准元素的比较结果进行重新排列,小于基准元素的放在左边,大于基准元素的放在右边。
3.递归排序:对基准元素左右两边的子数组进行递归排序。
模板:
void quick_sort(int q[], int l, int r)
{
if (l >= r) return;//如果访问数组为空则返回;
int i = l - 1, j = r + 1, x = q[l + r >> 1];//确定3个点:头、尾、中心
while (i < j)
{
do i ++ ; while (q[i] < x);//调整两个子数组,一个包含所有小于基准元素的元素,另一个包含所有大于基准元素的元素
do j -- ; while (q[j] > x);
if (i < j) swap(q[i], q[j]);
}
quick_sort(q, l, j), quick_sort(q, j + 1, r);//递归地对这两个子数组进行快速排序。
}
————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
选择排序:
选择排序是一个简单的排序算法,其基本思想是通过重复遍历待排序数列,在里面找到最小(或最大)的数,将其放在区间的顶部(或尾部)
他的优点有:
1.时间复杂度低:平均时间复杂度为O(nlogn),比其他排序算法如冒泡排序、选择排序和插入排序更快。
2.原地排序:不需要额外的存储空间,只需通过交换数组中的元素来实现排序。
3.分治思想:采用分治策略,将问题分解为子问题,简化问题复杂度。
模板:
void selection_sort(int a[],int n){//a[]是需要排序的数组,n是长度
for(int i=1;i<n;i++){
int ith=i;//记录第i小值
for(int j=i+1;j<=n;j++){//寻找最第i小值
if(a[j]<a[ith]){
ith=j;
}
}
swap(a[i],a[ith]);//将当前的数与第i小值交换
}
}
————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
冒泡排序:
冒泡排序是一种简单的排序算法,其基本思想是通过重复遍历待排序的数列,比较每对相邻元素并在必要时交换它们的位置,直到整个数列有序。它是通过重复走访数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复进行的,直到没有再需要交换的元素为止,这时数列就排序完成了。
步骤:
1.从左到右遍历数列,比较相邻的两个元素。
2.如果第一个元素比第二个元素大,则交换它们的位置。
3.对每一对相邻元素做同样的工作,直到最后一对。
·重复步骤1~3,直到整个数列有序。
模板:
void bubble_sort(int a[],int n){
for(int i=1;i<n;i++){
bool flag=1;//记录在这一轮中是否有进行交换
for(int j=1;j<=n-1;j++){
if(a[j]>a[j+1]){//进行冒泡
swap(a[j],a[j+1]);
flag=false;//记录已经交换过了
}
}
if(flag){//如果没有进行交换的话就说明这个数组是有序的不需再次排序
break;
}
}
}
————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
插入排序是一种简单直观的排序算法,其基本思想是将一个记录插入到已经排好序的有序表中,从而得到一个新的、记录数增1的有序表。也是一种稳定的算法。
步骤:
插入排序将数组分为已排序区间和未排序区间。初始时,已排序区间只包含数组的第一个元素,未排序区间包含除第一个元素之外的所有元素。然后,从未排序区间取出第一个元素,将它插入到已排序区间的合适位置,使得已排序区间仍然保持有序。这个过程重复进行,直到未排序区间中的所有元素都被插入到已排序区间中,即整个数组排序完成。
模板:
void insertion_sort(int a[],int n){//a[]是需要进行排序的数组,n是长度
for(int i=2;i<=n;i++){//循环遍历每一个数
int key=a[i];
int j=i-1;
while(j>=1&&a[j]>key){//寻找插入的位置
a[j+1]=a[j];//一边寻找一边腾出空间
j--;
}
a[j+1]=key;//进行替换
}
}
————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
桶排序是一种分块排序算法,其核心思想是将一个数组分到有限数量的桶里,每个桶再分别进行排序
步骤:
1.初始化桶:根据待排序数组的取值范围,初始化有限数量的桶。
2.分配元素到桶中:遍历待排序数组,根据元素的大小确定每个元素所属桶的位置,并将其放入相应的桶中。
3.对每个桶中的数字进行排序:可以使用其他排序算法,如插入排序、快速排序等,对每个桶中的数字进行排序。
4.合并所有桶中的数字:按顺序将所有桶中的数字合并,得到最终有序数组。
模板:
#define NUM_RANGE (100) //预定义数据范围上限,即K的值
void counting_sort(int *ini_arr, int *sorted_arr, int n) //所需空间为 2*n+k
{
int *count_arr = (int *)malloc(sizeof(int) * NUM_RANGE);
int i, j, k;
//初始化统计数组元素为值为零
for(k=0; k<NUM_RANGE; k++){
count_arr[k] = 0;
}
//统计数组中,每个元素出现的次数
for(i=0; i<n; i++){
count_arr[ini_arr[i]]++;
}
//统计数组计数,每项存前N项和,这实质为排序过程
for(k=1; k<NUM_RANGE; k++){
count_arr[k] += count_arr[k-1];
}
//将计数排序结果转化为数组元素的真实排序结果
for(j=n-1 ; j>=0; j--){
int elem = ini_arr[j]; //取待排序元素
int index = count_arr[elem]-1; //待排序元素在有序数组中的序号
sorted_arr[index] = elem; //将待排序元素存入结果数组中
count_arr[elem]--; //修正排序结果,其实是针对算得元素的修正
}
free(count_arr);
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)