【算法设计与分析·复习】第二章-分治||自食用

step by step.

目录

一、 分治概念

二、 分治基本思想

三、 分治常见递推方程

四、 例题分析

2.4 大整数的乘法 

2.8 快速排序

 2.8.1 一般快速排序 

 2.8.1 一般快速排序算法思想与范例详解

 2.8.1 一般快速排序分析

2.8.2 改进的快速排序算法1——随机选取q作为x

2.8.3 改进的快速排序算法2——均衡划分

2.9 线性时间选择

(1)排序法

(2)堆+部分排序

(3)堆      

(4)快速选择

 2.9 线性时间选择4(快速选择)-算法思想

2.9 线性时间选择算法5(中位数的中位数法-寻找支点元素)


一、 分治概念

分治:将一个规模为n的问题分解为k个规模较小的子问题,这些子问题相互独立且与原问题相同。

二、 分治基本思想

👇

三、 分治常见递推方程

👇 

原理可看上一篇博客的前面部分有讲到一个方法。

👇

【算法设计与分析·复习】第二章-递归||时间复杂度计算||自食用_bdy_y9的博客-CSDN博客step by step.一、 递归:直接或间接地调用自身的算法二、 例2-4 排列问题设计一个递归算法生成n个元素{r1,r2,…,rn}的全排列•设R={r1,r2,…,rn}是要进行排列的n个元素,Ri=R-{ri}。•集合X中元素的全排列记为perm(X)。•(ri)perm(X)表示在全排列perm(X)的每一个排列前加上前缀得到的排列。2-4 排列问题算法思路????T(n) = O(n!)2-4 排列问题算法代码v.https://blog.csdn.net/weixin_51159944/article/details/122022210?spm=1001.2014.3001.5501

四、 例题分析

2.4 大整数的乘法 

 请设计一个有效的算法,进行两个n位二进制大整数的乘法运算

XY = ac 2n + (ad+bc) 2n/2 + bd

为了降低时间复杂度,必须减少乘法的次数,即减小子问题个数

第一个方案XY = ac 2n + ((a-b)(d-c)+ac+bd) 2n/2 + bd       

第二个方案XY = ac 2n + ((a+b)(c+d)-ac-bd) 2n/2 + bd

选择第一个方案:仅需做3次n/2位整数的乘法。 ac     (a-b)(d-c)       bd  ,其他为重复计算。


2.8 快速排序

 2.8.1 一般快速排序 

 快速排序步骤——分解;递归求解;合并

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>
int Partition (Type a[], int p, int r)
{
        int i = p, j = r + 1; 
        Type x=a[p];
        // 将 < x的元素交换到左边区域
        // 将 > x的元素交换到右边区域
        while (true) {
           while (a[++i] <x&&i < r);
           while (a[- -j] >x&&j > p);
           if (i >= j) break; 
           Swap(a[i], a[j]);
           }
       a[p] = a[j];
       a[j] = x;
       return j;
}

 2.8.1 一般快速排序算法思想与范例详解

👇

6, 7, 5, 2, 5, 8 } 

 2.8.1 一般快速排序分析

最坏情况👇 (每一次都是边沿数据)

最好情况👇(每一次都刚好是中位数)

2.8.2 改进的快速排序算法1——随机选取q作为x

算法思想👇 

 template<class Type>
int RandomizedPartition (Type a[], int p, int r)
{
        int i = Random(p,r);   —————— 随机选取基准元素
        Swap(a[i], a[p]);  ———————— 把基准元素放置原算法中的开始位
        return Partition (a, p, r);    ————(原算法把开始位作为基准元素)
}

代码👇 

template<class Type>
int RandomizedPartition (Type a[], int p, int r)
{
        int i = Random(p,r);
        Swap(a[i], a[p]);
        return Partition (a, p, r);
}
template<class Type>
int Partition (Type a[], int p, int r)
{
        int i = p, j = r + 1; 
        Type x=a[p];
        // 将 < x的元素交换到左边区域
        // 将 > x的元素交换到右边区域
        while (true) {
           while (a[++i] <x&&i < r);
           while (a[- -j] >x&&j > p);
           if (i >= j) break; 
           Swap(a[i], a[j]);
           }
       a[p] = a[j];
       a[j] = x;
       return j;
}
template<class Type>
void RamdomizedQuickSort (Type a[], int p, int r)
{
      if (p<r) {
        int q = RandomizedPartition(a,p,r);
        //对左半段排序
        QuickSort (a,p,q-1); 
        //对右半段排序
        QuickSort (a,q+1,r); 
        }
}

2.8.3 改进的快速排序算法2——均衡划分

T(n) = O(nlogn)


2.9 线性时间选择

一般方法👇

(1)排序法

 O(nlogn

(2)堆+部分排序

         Ø  先建 最小堆 :O(n)
        Ø  弹堆顶元素 k 次,第 k 次获得第 k 小元素: k*O(logn)

        当k较小,接近线性效率,但堆的空间较大。 

 O(n+klogn

(3)堆      

        Ø 先建一个长度为 k 最大堆 ,存储 n 个元素的前 k 个元素,并假设他们就是最小的 k 个数,建堆费时 O(k);
        Ø 弹堆顶 x ,将后续 n-k 个元素逐个遍历,和堆顶 x 比较,若比 x 小,插入并更新堆,若比 x大,丢弃;

        总耗时最坏:O(k+(n-k)logk) = O(nlogk),当k较小,接近线性效率,且堆的空间很小(只有k),适合于海量数据查询第k小元素(k<<n)此方法得益于在堆中,插入、查找等各项操作时间复杂度均为logk。

 O(nlogk

(4)快速选择

template<class Type>
Type RandomizedSelect(Type a[],int p,int r,int k)
{
      if (p==r) return a[p];
      int i=RandomizedPartition(a,p,r),
      j=i-p+1;
      if (k<=j) 
	return RandomizedSelect(a,p,i,k);
      else
	return RandomizedSelect(a,i+1,r,k-j);
}
template<class Type>
int RandomizedPartition (Type a[], int p, int r)
{
        int i = Random(p,r);
        Swap(a[i], a[p]);
        return Partition (a, p, r);
}

int Partition (Type a[], int p, int r)
{
        int i = p, j = r + 1; 
        Type x=a[p];
        // 将 < x的元素交换到左边区域
        // 将 > x的元素交换到右边区域
        while (true) {
           while (a[++i] <x&&i < r);
           while (a[- -j] >x&&j > p);
           if (i >= j) break; 
           Swap(a[i], a[j]);
           }
       a[p] = a[j];
       a[j] = x;
       return j;
}

 2.9 线性时间选择4(快速选择)-算法思想

 👇

平均时间: O(n) 

2.9 线性时间选择算法5(中位数的中位数法-寻找支点元素)

最坏时间: O(n) 

Type Select(Type a[], int p, int r, int k)
{
      if (r-p<75) {
        用某个简单排序算法对数组a[p:r]排序;
        return a[p+k-1];
        };
      for ( int i = 0; i<=(r-p-4)/5; i++ )
         将a[p+5*i]至a[p+5*i+4]的第3小元素
         与a[p+i]交换位置;
      //找中位数的中位数,r-p-4即上面所说的n-5
      Type x = Select(a, p, p+(r-p-4)/5, (r-p-4)/10);
      int i=Partition(a,p,r, x),
      j=i-p+1;
      if (k<=j) return Select(a,p,i,k);
      else return Select(a,i+1,r,k-j);
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值