算法设计与分析课程记录week3

算法设计与分析课程记录week3

PS:此文章仅作为个人课程期间的学习记录

分治法

1 分治法概述

1.1 分治法的设计思想

对于一个规模为n的问题:若该问题可以容易地解决(比如说规模n较小)则直接解决,否则将其分解为k个规模较小的子问题,这些子问题互相独立且与原问题形式相同,递归地解这些子问题,然后将各子问题的解合并得到原问题的解。这种算法设计策略叫做分治法
分治法所能解决的问题一般具有以下几个特征:

  1. 该问题的规模缩小到一定的程度就可以容易地解决。
  2. 该问题可以分解为若干个规模较小的相同问题。
  3. 利用该问题分解出的子问题的解可以合并为该问题的解。
  4. 该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子问题。

2 求解排序问题

2.1 快速排序

基本思想:在待排序的n个元素中任取一个元素(通常取第一个元素)作为基准,把该元素放入最终位置后,整个数据序列被基准分割成两个子序列,所有小于基准的元素放置在前子序列中,所有大于基准的元素放置在后子序列中,并把基准排在这两个子序列的中间,这个过程称作划分
然后对两个子序列分别重复上述过程,直至每个子序列内只有一个记录或空为止。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
快速排序算法:

//划分算法
int Partition(int a[]int s,int t)	
{   int i=s,j=t;
    int tmp=a[s];	//用序列的第1个记录作为基准
    while (i!=j)	//从序列两端交替向中间扫描,直至i=j为止     
    {   while (j>i && a[j]>=tmp) 
      j--;    	//从右向左扫描,找第1个关键字小于tmp的a[j]
        a[i]=a[j];	//将a[j]前移到a[i]的位置
        while (i<j && a[i]<=tmp) 
      i++;   	//从左向右扫描,找第1个关键字大于tmp的a[i]
        a[j]=a[i];	//将a[i]后移到a[j]的位置
  }
  a[i]=tmp;
  return i;
}
//快速排序
void QuickSort(int a[]int s,int t)	
//对a[s..t]元素序列进行递增排序
{  if (s<t) 			//序列内至少存在2个元素的情况
   {   int i=Partition(a,s,t);
       QuickSort(a,s,i-1);	//对左子序列递归排序
       QuickSort(a,i+1,t);	//对右子序列递归排序
   }
}

时间复杂度
当初始排序数据正序或反序时,此时的递归树高度为n,快速排序呈现最坏情况,即最坏情况下的时间复杂度为O(n²)
当初始排序数据随机分布,使每次分成的两个子区间中的记录个数大致相等,此时的递归树高度为 l o g 2 n log_{2} n log2n,快速排序呈现最好情况,即最好情况下的时间复杂度为 O ( n l o g 2 n ) O(nlog_{2} n) O(nlog2n)快速排序算法的平均时间复杂度也是 O ( n l o g 2 n ) O(nlog_{2} n) O(nlog2n)

2.2 归并排序

归并排序的基本思想是:首先将a[0…n-1]看成是n个长度为1的有序表,将相邻的k(k≥2)个有序子表成对归并,得到n/k个长度为k的有序子表;然后再将这些有序子表继续归并,得到n/k2个长度为k2的有序子表,如此反复进行下去,最后得到一个长度为n的有序表。
若k=2,即归并在相邻的两个有序子表中进行的,称为二路归并排序。若k>2,即归并操作在相邻的多个有序子表中进行,则叫多路归并排序
在这里插入图片描述
在这里插入图片描述
归并排序算法代码

void Merge(int a[]int low,int mid,int high)
//a[low..mid]和a[mid+1..high]→a[low..high]
{  int *tmpa;
   int i=low,j=mid+1,k=0;
   tmpa=(int *)malloc((high-low+1)*sizeof(int));
   while (i<=mid && j<=high)
     if (a[i]<=a[j])		//将第1子表中的元素放入tmpa中
   {  tmpa[k]=a[i];  i++; k++; }
   else			//将第2子表中的元素放入tmpa中
   {  tmpa[k]=a[j]; j++; k++; }
   while (i<=mid)		//将第1子表余下部分复制到tmpa
   {  tmpa[k]=a[i]; i++; k++; }
   while (j<=high)		//将第2子表余下部分复制到tmpa
   {  tmpa[k]=a[j]; j++; k++; }
   for (k=0,i=low;i<=high;k++,i++)  //将tmpa复制回a中
    a[i]=tmpa[k];
   free(tmpa);			//释放tmpa所占内存空间
}

void MergePass(int a[]int length,int n)
//一趟二路归并排序
{  int i;
   for (i=0;i+2*length-1<n;i=i+2*length)   //归并length长的两相邻子表
    Merge(a,i,i+length-1,i+2*length-1);
   if (i+length-1<n)	     		 //余下两个子表,后者长度小于length
     Merge(a,i,i+length-1,n-1);	 //归并这两个子表
}
//二路归并算法
void MergeSort(int a[]int n)	
{  int length;
   for (length=1;length<n;length=2*length)
    MergePass(a,length,n);
}

对于上述二路归并排序算法,当有n个元素时,需在这里插入图片描述趟归并,每一趟归并,其元素比较次数不超过n-1,元素移动次数都是n,因此归并排序的时间复杂度为 O ( n l o g 2 n ) O(nlog_{2} n) O(nlog2n)

3 求解查找问题

4 求解组合问题

5 求解大整数乘法和矩阵乘法问题

6 并行计算简介

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值