二分搜索技术 合并排序 快速排序算法 线时间选择

递归与分治策略

  1. 二分搜索算法是运用分治策略的典型例子。二分搜索算法的基本思想是将n个元素分成个数大致相同的两半。取a(n/2)与x做比较。如果x=a(n/2),则找到x算法终止。如果x小于它,则只在数组a的左半部继续搜索x。如果x大于它,则指代数组a的右半部,继续搜索x,具体的C++算法可描述如下。

  2. 合并排序算法是用分治策略实现对n个元素进行排序的算法,其基本思想是将待排序元素分成大小。大致相同的两个子集合,分别对两个子集合进行排序,最终将排好序的子集和合并成要求的排好序的集合。

  3. 快速排序算法是基于分治策略的另一个排序算法

  4. 线时间选择实际上是模仿快速排序算法设计出来的基本思想,也是对输入速度进行递归划分。


using namespace std;
//二分搜索
template<class Type>
int BinarySearch(Type a[],const Type& x,int n){
int left= 0;
int right = n-1;
while(left<=right){
    int middle =(left+right)/2;
    if(x==a[middle])
        return middle;
    if(x>a[middle])
        left=middle+1;
    else
        right=middle-1;
}
 return -1;
}
//合并排序
template<class Type>
void Merge(Type c[],Type d[],int l,int m,int r){
int i =l,j= m+1,k=l;
while((i<=m)&&(j<=r)){
    if(c[i]<=c[j])
        d[k++]=c[i++];
    else
        d[k++]=c[j++];
}
    if(i>m){
        for(int q=j;q<=r;q++)
            d[k++]=c[q];

    }
    else{
        for(int q=i;q<=m;q++)
        d[k++]=c[q];
    }
}

template<class Type>
int Copy(Type a[],Type b[],int left,int right){
for(int i=left;i<=right;i++){
    a[i]=b[i];
}
}

template<class Type>
void MergeSort(Type a[],int left,int right){
if(left<right){
    int i=(left+right)/2;
    MergeSort(a,left,i);
    MergeSort(a,i+1,right);
    int b[4];
    Merge(a,b,left,i,right);
    Copy(a,b,left,right);
}
}

//快速排序
template<class T>
void Swap(T & a,T & b){
    T temp=a;
    a=b;
    b=temp;
}

template<class Type>
int Partition(Type a[],int p,int r){
int i = p,j=r+1;
Type x=a[p];
while(true){
    while(a[++i]<x&&i<r);
    while(a[--j]>x);
    if(i>=j)
        break;
    Swap(a[i],a[j]);

}
a[p] =a[j];
a[j]=x;
return j;
}

template<class Type>
void QuickSort(Type a[],int p,int r){
if(p<r){
    int q = Partition(a,p,r);
    QuickSort(a,p,q-1);
    QuickSort(a,q+1,r);
}
}


//线性时间选择
template<class Type>
Type Select(Type a[],int p,int r,int k){
  if(p==r)
    return a[p];
  int i=Partition(a,p,r);
  int j;
  j=i-p+1;
  if(k<=j)
    return Select(a,p,i,k);
  else
    return Select(a,i+1,r,k-j);

}

#endif // LIANGHELONG1_H_INCLUDED


using namespace std;


int main()
{
    cout <<"二分搜索排序"<<" ";
    int a[9]={1,2,3,4,5,6,7,8,9};;
    const int x=4;
    int m =BinarySearch(a,x,9);
    cout<<m<<endl;

    cout<<" "<<endl;

    cout<<"合并排序"<<" ";
    int b[4]={4,3,2,1};
    MergeSort(a,0,3);
     for(int j=0;j<4;j++){
    cout<<a[j]<<" ";
    }
    cout<<" "<<endl;
    cout<<"快速排序"<<" ";
    int c[4]={4,3,2,1};
    QuickSort(a,0,3);
    for(int i=0;i<4;i++){
    cout<<a[i]<<" ";
    }
    cout<<" "<<endl;
    cout<<"线性时间搜索"<<" ";
    int d[4]={2,1,3,4};
    cout<<Select(d,0,3,2)<<endl;
    return 0;
}




### 分治算法详解 #### 一、分治法的定义 分治法是一种重要的算法设计技术,主要思想是将原问题分解成若干个规模较小但结构与原问题相似的子问题。解决这些子问题,然后将它们的解组合起来得到原问题的解[^1]。 #### 二、分治法的基本步骤 分治法通常按照以下三个基本步骤来解决问题: - **分解**:将待处理的问题划分为多个更小的部分; - **解决**:递归地求解各个部分直到可以直接得出答案为止; - **合并**:把各部分的结果综合起来形成整个问题的答案; #### 三、具体实现案例分析 ##### (一) 查找算法—二分(折半)查找 对于已经按升序排列的数据序列,在给定目标值的情况下,通过不断缩小搜索范围直至定位到该元素位置的过程称为二分查找。此过程每次都将当前区间分成两半,并根据中间点处数值同目标值得关系决定继续在哪一半内寻找,从而使得最坏情况下只需\( O(\log n)\) 的时间复杂度即可完成操作[^3]。 ```python def binary_search(arr, target): low, high = 0, len(arr)-1 while low <= high: mid = (low + high)//2 if arr[mid] == target: return mid elif arr[mid] < target: low = mid + 1 else: high = mid - 1 return -1 ``` ##### (二) 排序算法 ###### 1. 快速排序 —— 基于交换机制 快速排序的核心在于选取一个基准数(pivot),再经过一轮调整使左侧都小于等于它右侧大于等于它,之后分别对左右两侧重复上述动作最终达到整体有序状态的目的。平均而言,这种做法可以在线性对数时间内完成任务即 \(O(n\log n)\)。 ```python def quicksort(array): if len(array) < 2: return array else: pivot = array[0] less = [i for i in array[1:] if i <= pivot] greater = [i for i in array[1:] if i > pivot] return quicksort(less) + [pivot] + quicksort(greater) ``` ###### 2. 归并排序 —— 利用额外空间进行合并 归并将原始列表分割至最小单位后逐一配对重组为新的已排序片段,最后汇总成为完整的有序集合。同样具备良好的渐近效率表现\[O(n \log n)] ,不过相较于前者可能消耗更多内存资源。 ```python from typing import List def merge_sort(nums: List[int]) -> List[int]: if len(nums) <= 1: return nums mid = len(nums) // 2 left_half = merge_sort(nums[:mid]) right_half = merge_sort(nums[mid:]) sorted_nums = [] l_idx = r_idx = 0 while l_idx < len(left_half) and r_idx < len(right_half): if left_half[l_idx] < right_half[r_idx]: sorted_nums.append(left_half[l_idx]) l_idx += 1 else: sorted_nums.append(right_half[r_idx]) r_idx += 1 # Append any remaining elements from either half. sorted_nums.extend(left_half[l_idx:]) sorted_nums.extend(right_half[r_idx:]) return sorted_nums ``` ##### 四、线时间选择 为了能够在期望时间为线性的条件下选出第k小/大项,可以通过随机化版本的QuickSelect算法实现。这种方法基于快排的思想但在每轮迭代只关注一侧因此能够显著减少不必要的计算量。理论上讲,只要合理控制分区函数的选择概率分布便能保证接近最优的时间开销【未提供直接引用,属于专业知识补充】。 ```python import random def randomized_select(A,p,r,i): if p==r: return A[p] q=randomized_partition(A,p,r) k=q-p+1 if i==k: return A[q] elif i<k: return randomized_select(A,p,q-1,i) else: return randomized_select(A,q+1,r,i-k) def partition(A,p,r): x=A[r];i=p-1; for j in range(p,r): if A[j]<=x: i+=1 temp=A[i];A[i]=A[j];A[j]=temp temp=A[i+1];A[i+1]=A[r];A[r]=temp return i+1 def randomized_partition(A,p,r): i=random.randint(p,r); temp=A[r];A[r]=A[i];A[i]=temp return partition(A,p,r); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值