算法第二章实验报告

Artiran 2024-10-20 22:53:18

计科2301谢晶 20220200591

1、代码:

#include<iostream>  
using namespace std;  

//划分函数,将数组划分为两部分,左边部分<=x,右边部分>=x
//返回x最终所在的位置(划分后的中间位置)  
int partition(int a[], int l, int r)   
{    
    int left=l;  
    int right=r;  
    int x = a[left]; // 选择最左边的元素作为基准x  
    
    while (left < right) // 当左右指针没有相遇时继续划分  
    {  
        while (left < right && a[right] >= x)  
        {   right--;   }// 从右向左找第一个<x的元素,如果找到了,将其放到左边位置  
        
        if (left < right)//如果x>a[right]
        {  a[left] = a[right];  }  

        while (left < right && a[left] <= x)  
        {  left++;   }// 从左向右找第一个>x的元素,如果找到了,将其放到右边位置  
        if (left < right)
        {  a[right] = a[left]; }  
    }

    a[left] = x; //a[right], a[left]同时指向一个位置, 将基准x放上去  
    return left; // 返回x的位置(划分后的中间位置)
}  

// 快速选择函数,在数组a的left到right范围内找到第k小的元素  
//每次递归处理n/2个元素,平均时间为O(n)
void find(int a[], int left, int right, int k)  
{  
    int p = partition(a, left, right); // 对数组进行划分  
    //数组索引从0开始,第k小的元素对应的索引是k-1
    if ((k - 1) == p)//如果k-1等于划分的位置,说明p就是第k小的元素,直接输出 
    {cout << a[k - 1];}  
    
    else if ((k - 1) > p)//如果k-1大于划分的位置,说明第k小的元素在p的右侧,在右半部分继续查找
    {find(a, p + 1, right, k); 
    //数组索引是从0开始的,所以右侧起始索引是p+1 }  
    
    else // 如果k-1小于划分的位置,说明第k小的元素在p的左侧,在左半部分继续查找
    {find(a, left, p - 1, k); 
    //p是基准元素的位置,它不包含在左侧数组中,所以左侧结束索引是p-1
}  

int main()  
{  
    int n, k, num[10001]; // 定义数组num用于存储输入的n个元素和变量
    cin >> n >> k;
    for (int i = 0; i < n; i++)  
    {   cin >> num[i]; // 输入n个元素  }  
    find(num, 0, n - 1, k);
    return 0;  
}

首先我们要判断左右是否相等,如果相等就直接返回这个数。在不相遇的情况下我们继续讨论,当a[right] >= x,我们从右向左找第一个<x的元素,如果找到了,将其放到左边位置。当a[left] <= x,我们从左向右找第一个>x的元素,如果找到了,将其放到右边位置。继续循环,直到a[right], a[left]同时指向一个位置, 我们将基准x放上去。对数组进行划分,如果k-1等于划分的位置,说明p就是第k小的元素,直接输出,如果k-1大于划分的位置,说明第k小的元素在p的右侧,在右半部分继续查找,如果k-1小于划分的位置,说明第k小的元素在p的左侧,在左半部分继续查找。

2、

最好的时间复杂度:O(n),每次递归处理n/2个元素。

最坏的时间复杂度:O(n^2),如果基准元素选择不当,数组的第一个或最后一个元素作为基准。

3、

我了解到,分治法是一种解决问题的方法,它能将一个复杂的问题分解为若干个较小的、更易于解决的子问题。用递归地解决这些子问题,最后将这些子问题的解合并起来以得到原问题的解。比如说在这次的快速选择算法中,问题被分解为两个子问题:在基准元素的左侧查找第k小的元素,或在基准元素的右侧查找第k-p-1小的元素。这样的分解会比原来的问题更加简易。此外,我还学习到基准元素选择的重要性,如果基准元素选择得当,可以使每次划分都更加平衡,从而减少比较次数。如果选择不当,就会使得时间复杂度更坏。总之,通过深入的理解和学习分治法,我可以更好地学会如何解决更加复杂的问题,并学习到更高效的算法。

...全文
49 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

434

社区成员

发帖
与我相关
我的任务
社区描述
广东外语外贸大学信息科学与技术学院
算法 高校
社区管理员
  • brisksea
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧