算法设计与分析基础(四)

算法设计与分析基础(四):蛮力法

蛮力法是一种简单直接处理问题但是不一定高效的方法。蛮力法具有以下的特点:

  1. 应用范围广,不受到实例规模的限制
  2. 当要解决的问题低频率出现,并且高效算法很难设计的时候可以选用蛮力法
  3. 对解决一些小规模的问题实例仍然有效
  4. 可以作为衡量其他算法的参照物

选择排序和冒泡排序

选择排序

  • 原理
  1. 扫描整个列表,找出n个元素中的最小元素;

  2. 扫描最小元素以外的其他n-1个元素,找出它们中的最小元素;

  3. 重复上述操作,直到所剩元素个数为1。

image-20211212173230679

  • 算法的形式化描述

    Algorithm SelectionSort(A[0..n-1])
           for i=0 to n-2 do //最后剩下的数不用再进行比较
              min := i;
              for j := i+1 to n-1 do
                      if A[j]<A[min] then min := j ;
              swap A[i] and A[min]
    

    基本操作:比较A[j]<A[min],交换数据swap

    比较次数:C(n):

    image-20211212173602201

    于是C(n)∈θ (n2)

    数据交换次数:最坏情况O (n)

冒泡排序

  • 原理
    1. 比较相邻的元素,将大的元素交换到右边的位置,重复多次后,最大元素就“沉淀”到列表的最后一个位置。
    2. 第二遍将第二大元素沉下去,n-1遍后结束。

image-20211212173856474

  • 算法形式化描述:

    Algorithm BubbleSort(A[0..n-1])
          for i:=0 to n-2 do
               for j:=0 to n-2-i do
                    if A[j+1]<A[j] then swap A[j] and A[j+1]
    

    基本操作:A[j]<A[j+1]

    比较次数C(n):

    image-20211212174214479

    于是C(n)∈θ (n2)

结论:选择排序和冒泡排序的时间函数均是属于θ(n2)

顺序查找和蛮力字符串匹配

顺序查找问题

已知有n个元素的数组A[0…n]. 给定元素K,要求找出一个下标i, 使得A[i]=K. 输出第一个值等于K的元素的位置,找不到返回-1.

算法:

算法 SequentialSearch(A[0..n-1],K)
     i:=0;
     while A[i]≠K and i<n do 		
  		i:=i+1;	
    if A[i]=K  then return i
         else return -1	

改进后的算法:

改进算法 SequentialSearch2(A[0..n-1],K)
     A[n]=K;//把查找键添加到列表的末尾,那么查找一定成功,所以不必每次循环都检查是否到了表的末尾。
     i:=0;
     while A[i]≠K do 		
  		i:=i+1;	
      if i<n  then return i 	
           else return -1

另一个简单的改进:对于有序数组,只要遇到一个大于或等于查找键的元素,查找就可以停止了。

蛮力字符匹配问题

将模式对准文本的前m个字符从左往右进行比对,如果其中有一个字符不匹配,模式往右移动一位继续下一个m个字符的比对。

从文本中寻找匹配模式的子串,即求出第一个匹配模式的子串在文本中的开始位置(子串最左元素的下标)。
其中:文本——给定的由n个字符组成的串
模式——指定的由m个字符组成的串

image-20211212175010703

算法描述:

Algorithm BFSM (T[0..n-1], P[0..m-1])
   // Brute Force String Match
   //文本T[0..n-1]长度为n; 模式P[0..m-1]长度为m
   //查找不成功时返回-1
begin
  for i :=0 to n-m do
      j := 0
      while j<m and P[j]=T[i+j] do
          j :=  j+1
      if i=m return i
   return -1
end

蛮力字符串匹配算法分析:
最坏的情形是模式须移动n-m+1次,每次移动模式之前,做足m次比对才发现不匹配(即第i+m位不匹配),
因此,在最坏情况下,该算法属于Θ(nm)。平均效率可达到Θ(n+m) =Θ(n)。

最近点对和凸包问题

最近点对

给定平面S上n个点,找其中的一对点,使得在n(n-1)/2个点对中,该点对的距离最小。

记(P.x,P.y)为点P的坐标值,则两个点Pi , Pj之间的距离公式为:

image-20211212180651708

  • 算法描述:

    Algorithm BFCP ( P )  // Brute Force Closest Points
        // 输入:n个点的数组P,Pi(xi , yi), i=1, 2, …, n
        // 输出:两个最近点的下标index1和index2
        begin
             dmin ← ∞;
             for i ← 1 to n-1 do
        	     for j ← i+1 to n  do
        		     d ← sqrt((xi-xj)2+(yi-yj)2);
        		     if d < dmin then
        		        dmin ← d;
        		        index1 ← i;   index2 ← j;
              return index1, index2
       end.
    

    image-20211212180832236

凸包问题

  • 凸集定义:
    设S是平面点集,如果S中任意两点的连线都属于该集合,则称S是凸的 pp. 84-85。
  • 凸包定义:
    一个点集S的凸包是指包含S的最小凸集。显然,如果S是凸的,则S的凸包就是S本身(橡皮筋圈解释)。
  • 凸包问题:
    给定一个n个点的点集S,求S的凸包。

image-20211212181100147

  • 定理:

    任意包含n>2个点的集合S的凸包,是以S中的某些点位顶点的凸多边形。特别,如果所有点共线,则多边形退

    化为一条直线,它的两个端点仍在S中。

  • 极值

    凸集的极点是指不会出现在集合中任何线段的中间的点。凸多边形的顶点是极点。

  • 解法

    设点集大小为n,首先将其中的点两两配对,得到直线段条;然后对每一条直线段检查其余的n-2个点的相对该

    直线段的正负性,如果它们都有相同的正负性,那么这条直线段属于凸多边形的边,其顶点是极点。

    设直线方程为 ax + by = c


    使ax+by-c > 0 的点 位于直线右(上)方
    使ax+by-c < 0 的点 位于直线左(下)方

image-20211212181444818

穷举法

穷举法是一种简单的蛮力方法,它要求生成所有可能的可行解,再从中选择最优解。

原理简单,大多数情况下是不可行的。

旅行商问题

TSP问题:
给定n个城市相互之间的距离,求一条能走遍n个城市的最短路径,使我们能从任一城市开始,访问每个城市只一次后回到起点。
等价于 “Hamilton回路问题” – (无权图)。

image-20211212181643339

背包问题

给定n 个重量为w1 , w2, …, wn,价值为v1 , v2 , … , vn的物品和一个承重为W的背包,如何将物品装入背包使背包所获的价值最大。

image-20211212181929614

分配问题

  • 有n个任务需要分配给n个人执行,一人一个任务。将第j个任务分配给第i个人的成本是C[i, j],求总成本最小的分配方案。

  • 穷举法要列出所有n! 个可能的分配方案。

image-20211212182109945

深度优先和广度优先查找

深度优先查找

image-20211212182159144

一个DFS输出序列是?a-c-d-f-b-e-g-h-i-j,需要用到栈结构

image-20211212183240016

image-20211212183307625

用下面的图进行理解:

image-20211212184258649

广度优先查找

image-20211212183549941

一个BFS输出序列是? a-c-d-e-f-b-g-h-j-i,需要用到队列结构

image-20211212183704874

下面这个图可以更好理解广度遍历:

img

总结

image-20211212183756677

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值