算法(一)

本文介绍了快速排序、归并排序两种基于分治策略的排序算法,以及二分查找算法。在快速排序中强调了边界处理和分界点选择的重要性;归并排序重点在于递归和合并操作;二分算法则用于在有序序列中查找特定元素,通过不断划分区间来缩小搜索范围。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一 : 快速排序 (分治)

备注:
O(nlogn)-O(nn)

过程:
1. 确定分界点 1 r (1+r)/2
2. 调整范围 核心
3. 递归处理左右两段

我们从中应该了解到:
1. 边界思想
(1)表面上看起来很平常,其实很重要 ,处理不当就废了
(2)也为递归创造了结束条件
2. 双指针
(1)数据可以从两边同时处理
3. 分界点选取
4. 递归

void quickSort(int q[],int l,int r){
    
    if( l >= r ) return;// 边界判断 
    int x = q[l] ; //取分界点  一般取中间 或者 开头 或者 结尾 
    int i = l - 1 ,j = r + 1; //指针 
    while( i < j ){ //移动交换算一次迭代 
        do i++ ; while( q[i] < x ); //i一直往后移 直到 q[i] >= x 
        do j-- ; while( q[j] > x ); //j一直往前移 直到 q[j] <= x 
        if( i < j ) swap( q[i] , q[j] ); // 交换各取所需 
    }
    quickSort( q , l , j );
    quickSort( q , j+1 , r);
} 

二:归并排序(分治)

备注:
O(nlogn) n除多少次除成1 -> logn次 (层) O(n)

过程:
1.确定分界点 mid = (1+r) /2
2.递归排序 left right
3.归并(合二为一) 核心 O(n)

我们从中应该学习到的东西:
1. 双指针
2. 递归
3. 位运算
void mergeSort(int q[],int l ,int r){
    if ( l >= r) return; 
    int mid = l + r >> 1; //取中点 
    mergeSort( q , l , mid ); mergeSort( q , mid + 1 , r); // 递归 
    int k = 0, i = l, j= mid + 1;
    while(i <= mid && j <= r) //归并 
        if(q[i] <= q[j]) temp[k++] = q[i++];
        else temp[ k ++ ] = q[ j ++];
    while(i <= mid) temp[ k ++ ] =q[ i ++ ];
    while(j <= r) temp[ k ++ ] =q[ j ++ ];
    for( i = l, j = 0 ; i <= r ; i ++,j ++) q[i] = temp[j]; 
}

三:二分算法

整数(浮点)二分:

本质:
区间中定义某种性质,使得 右区间满足,左区间不满足
二分可以寻找边界 有左区间结尾模板 和右区间开头模板

模板:

1.mid = ( l+r +1 ) / 2
check(mid) ->true [mid,r] l=mid
check(mid) ->false [1,mid-1] r=mid-1

2.mid =( l+r ) / 2
check(mid) -> true [1,mid] r=mid
check(mid) -> false [mid+1,r] l=mid+1

选择: 先写 check()
若 l=mid 则 mid 写成 l+r+1 >>1
若 r=mid 则 mid 写成 l+r >>1

发现: l+r >>1 和 (l+r)>>1 结果是一样的
l+r+1 >>1 和 (l+r+1) >>1 结果是一样的
位运算的优先级太低了 几乎就是要最后运算
// 区间 [1,r]被划分成[1,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;
} 
// 区间[1,r] 被划分成[1,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.经验 1e-8 得到的是6位小数
          1e-6 得到的是4位小数 
**/
double BSearch_float(double r,double l){
    
    while(r-l >1e-8){    
        double mid = ( l + r ) / 2;
        if( check(mid) ) r = mid;
        else l = mid;
    }
    return l;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值