算法基础知识

一、插入排序(扑克牌原理)  n^2  原址

A[1,...,n-1]是排好序的,把第n个往前<-方向比较,比较一个移一个,最后在停下来的位置插入A[n]。o(n^2)

二、分治法(归并)  nlgn  非原址

//先分解
SORT(A,p,r)
if p<r
  q=[(r-p)/2]
  SORT(A,p,q)
  SORT(A,q+1,r)
  MERGE(A,p,q,r)
MERGE(A,p,q,r)
  L[1...q-p+1]=A[p...q]
  R[1...r-q+1]=A[q+1...r]
  //哨兵
  L[q-p+2]=无穷
  R[r-q+2]=无穷
  for i=p:r
    A[i]=max(L[a],R[b])

a++;//or b++;

三、分治法--最大子数组问题

描述:寻找A的和最大的非空连续子数组

解决:按中点分成两段,递归找左右段各自的最大段,再找跨越中点的最大段,三个结果进行比较

FIND(A,low,high)
  if high==low
    return(low,high,A[low])
  else mid=[(low+high)/2]
    (l-low,l-high,l-sum)=FIND(A,low,mid)
    (r-low,r-high,r-sum)=FIND(A,mid+1,high)
    (c-low,c-high,c-sum)=CROSS-FIND(A,low,mid,high)
    choose the max one to return
CROSS-FIND(A,low,mid,high)//这是跨中点段
  left_sum=MAX
  sum=0
  for i=mid:low
    sum+=A[i]
    if(sum>left_sum)
      left_sum=sum
      max_left=i
  right_sum=MAX
  sum=0
  for i=mid+1:high
    sum+=A[i]
    if(sum>right_sum)
      right_sum=sum
      max_right=i
  return(max_left,max_right,left_sum+right_sum)

四、矩阵乘法的Strassen算法

描述:AxB按照原始的乘法需要递归三层,现在:

把矩阵分解成n/2 x n/2 的形式:A11,A12,A21,A22,B11,B12,B21,B22;

再将其两两加or减 得10个矩阵S1,S2,...,S10:

S1=B12-B22      S2=A11+A12    S3=A21+A22    S4=B21-B11     S5=A11+A22

S6=B11+B22     S7=A12-A22     S8=B21+B22     S9=A11-A21     S10=B11+B12

再递归的计算7次乘法。。。。。。

五、随机算法(优先级 原址)

1. A[1...n],给每一个数分配一个优先级,P[i]=RANDOM(1,n^3);使用P各个数的大小对A进行排序//问:若产生的优先数相等怎么办?--对其再进行随机数赋值

2. 原址排列给定数列;A[i]是从i--n数中随机选取一个j,swap(i,j),然后不再改变

六、堆排序  nlgn 非原址

二叉堆--被近似地看成完全二叉树;分为最大堆、最小堆;;建堆,维护堆,由堆对一个数组进行原址排序。

//对LEFT[i],RIGHT[i]满足最大堆,而A[i]不一定大于孩子的维护
MAX_HEAPIFY(A,i){
  //让A[i]与左孩子A[2i],A[2i+1]比较,选出大的放到顶上
  if(2i==A.heapsize)right=i;
  else if(2i>A.heapsize)left=i;right=i;
  else left=2i;right=2i+1;
  max=MAX(A[i],A[left],A[right]);
  if max==A[i] return;
  else if max==A[left] exchange(A[i],A[left])  r=left
  else if max==A[right] exchange(A[i],A[right])  r=right
  MAX_HEAPIFY(A,r)
}
//建堆
BUILD_MAX_HEAP(A){
  //从最后一个非叶子结点开始
  A.heapsize=A.length
for i=[A.length/2]:1
    MAX_HEAPIFY(A,i);
}
//用堆排序
HEAPSORT(A){
  //先建堆
  BUILD_MAX_HEAP(A)
  //排好序的往堆尾放
  for i=A.length:2
    exchange(A[1],A[i])
    A.heapsize--;
    MAX_HEAPIFY(A,1)
}
//取出最大的元素 并维护堆
HEAP_EXTRACT_MAX(A){
  if A.heapsize<1 error;
  max=A[1]
  A[1]=A[A.heapsize]
  A.heapsize--
  MAX_HEAPIFY(A,1)
  return max
}
//在建好的堆中位置i插入key
HEAP_INCREASE_KEY(A,i,key){
  if key<A[i] 
    A[i]=key
    MAX_HEAPIFY(A,i)
  else if key==A[i] return;
  else
    A[i]=key
    while i>1&&A[i/2]<A[i]
      exchange(A[i],A[i/2])
      i=i/2
}

七、快速排序(也有分治思想)最坏n^2  期望时间:nlgn 原址稳定,是排大数组的常用算法

//快排的实现
QUICKSORT(A,p,r){
  if p<r
  q=PARTITION(A,p,r)
  QUICKSORT(A,p,q-1)
  QUICKSORT(A,q+1,r)
}
PARTITION(A,p,r){
  x=A[r]
  i=p-1
  for j=1:r-1
    if A[j]<x
      i++
      exchange(A[i],A[j])
  exchange(A[i+1],A[r])
  return i+1
}

快排的随机化版本,从p,r 之间随机选择一个数,与r 进行交换

快排的尾递归:

TAIL(A,p,r){
  while p<r
    q=PARTITION(A,p,r)
    TAIL(A,p,q-1)
    p=q+1
}

更细致的选取主元的方法:随机选三个数,取中间的数作为主元

以上是基于比较的排序方法,最坏情况的下界是O(nlgn),堆、归并是渐进最优

八、计数排序  zeta(k+n)  稳定 不是原址  输入数据都是一个小区间的整数

//A是输入数组,B是输出数组,C记录各元素应放位置
SORT(A,B,k){//k应该是最大元素数
  for i=0:k
        C[i]=0
    for i=0:A.length-1
        C[A[i]]++
    for i=1:k
        C[i]=C[i]+C[i-1]
    for i=A.length-1:0
        B[C[A[i]]=A[i]
        C[A[i]]--
}

九、基数排序

描述:按最低有效位排序,合并后再按次低有效位排序,......;一位数排序算法最好是选取稳定的(计数常用)

十、桶排序

描述:把一个区间划分成几等分,各用一个list,然后落在各区间里的数分别排序,再把他们合并。

要求:元素服从均匀分布,平均情况下的时间代价为O(n)

十一、遗忘比较交换算法--列排序算法

描述:不依赖待排序元素的值,也不依赖之前比较的结果(0,1排序引理可证之);

包含n个元素的矩形数组的排序,有r行xs列,满足:

r必须是偶数;s|r;r>=2*s^2;

得到的结果是列优先有序的,从上到下,从左到右 单增。


十二、中位数和统计量

1.同时求最大/最小值--最多3[n/2]次

描述:总数为奇则把最大最小值的初始值设为first元素,为偶则取前两个比较后设为最大最小初值;剩余的数每两个相互比较,较小的再与min比,较大的再与max比。

2.同时求最大数和次大数

描述:把所有数两两配对取较大值,再次两两配对取较大值,...,最后得出的数为最大数;而次大数再从最大数开始回过去找,取最大值升上来的每个线路结点的孩子一一比较,最后得出次大值。

3.用快排找第i大的元素--期望为线性时间的选择算法

描述:只处理单边的快排

RANDOMIZED_SELECT(A,p,r,i){
   if p==r
      return A[r]
   q=PARTITION(A,p,r)
   k=q-p+1;//这是q号元素在队伍中的次序
   if k==i
      return A[q]
   else if k>i
      return RANDOMIZED_SELECT(A,p,q,i)
   else return RANDOMIZED_SELECT(A,q+1,r,i-k)
}

4.最坏情况为线性时间的选择算法

描述:返回n>1时的第i小的元素;n=1时返回唯一值;

SELECT(A,p,r,i)
1.将n个元素划分为[n/5]组,每组5个,剩余元素为一组
2.寻找每一组的中位数;先用插入排序,然后取中位数;得B[k]
3.对得到的中位数们递归调用SELECT(B,0,k,k/2),返回值为x,它记录了中位数的中位数;
4.利用快排修改过的PARTITION(A,p,r,x),以x为主元对整个数组进行划分,然后得出x的位置在q标处
5.若i=q,则返回x;若i<q,则递归调用SELECT(A,p,q-1,i);若i>q,则递归调用SELECT(A,q+1,r,i-q)。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值