【读书笔记】《大学算法教程》——chpt6.排序和选择

本文详细介绍了几种常见的排序算法,包括插入排序、快速排序等,并探讨了它们的时间复杂度及应用场景。此外,还介绍了计数排序和基数排序等特殊场景下的排序算法。

by Richard Johnsonbaugh Marcus Schaefer

 

6.1 插入排序

   本算法将数组a排序,方法是首先将a[2]插入已经有序的数组a[1];再将a[3]插入已经有序的数组a[1],a[2];依此类推;最后将a[n]插入已经有序的数组a[1],…,a[n-1]。

Input Parameter: a
Output Parameter: a
insertion_sort(a){
   n = a.last
   for i=2 to n{
       val=a[i]//保存a[i],以备插入正确位置
       j = i-1
       //若 val<a[j],则a[j]右移,为a[i]腾出位置
       while(j>=1 && val<a[j]){
           a[j+1]=a[j]
           j = j-1
       }
       a[j+1]=val//插入val
   } 
}

算法最坏情况为O(n²)。

 


6.2 快速排序
    将要排序的数组分成两部分,然后对每个部分进行排序。这种分割过程称为分区(partition)。分区取决于所选择的一个特别元素为分区元素。
分区算法:本算法将数组a[i],...,a[j]进行分区,方法是在下标h出插入val=a[i],这个位置正是数组排序后它应处的位置。算法结束时,下标比h小的单元值小于val,儿下标比h大的单元的值大于或等于val。算法回送下标h。

Input Parameters: a,i,j
Output Parameter: a

quicksort(a,i,j){
   val=a[i]
   h=i
   for k=i+1 to j
      if(a[k]<val){
        h = h+1
        swap(a[h],a[k])
      }
   swap(a[i],a[h])
   return h
}



    快速排序(Quicksort)。本算法利用分区算法对数组a[i],...a[j]进行排序。

Input Parameters: a,i,j
Output Parameter: a

quicksort(a,i,j){
  if(i<j){
     p = partition(a,i,j)
     quicksort(a,i,p-1)
     quicksort(a,p+1,j)
  }
}


快排的最坏情况为O(n²)。
随机化的快速排序是选择分区元素时不总选择第一个,而是随机选择。


6.3 排序问题的下届
   为了对n个项进行排序,任何基于比较的排序算法都有最坏情况Ω(nlgn)。
   基于比较:是指算法到底将一个元素放在数组中的什么位置,只有通过将数组中一个元素与另一个元素进行比较才能确定。
   堆阵排序、插入排序、归并排序和快速排序都是基于比较的排序算法。

6.4 计数排序和基数排序

   计数排序对每个值的个数进行计数,每个正数范围在0到m,包括0和m。然后利用得到的这组数据对原始的数据进行排序。

   如a[1]=5,a[2]=8,a[3]=3,a[4]=8,a[5]=10,a[6]=7
   如果c[k]是数组a中小于或等于k的元素的个数:
     c[3]=1,c[5]=2,c[7]=3,c[8]=5,c[10]=6
   然后把a中的项复制到另一个数组b,这个数组硬是被排序的。复制从a的最后一个元素开始。
   a中最后一个元素是7。由于c[7]=3,所以a中有3个元素小于等于7。因此一旦a被排序,7应当放在第三单元。依此类推。
   

    计数排序算法:本算法将整数数组a[1],...a[n]排序,每个正数的范围在0到m。

Input Parameters: a,m
Output Parameter: a

counting_sort(a,m){
  //设置c[k]=数组a中值k出现的次数。
  //开始讲c初始化为0。
  for k=0 to m
     c[k]=0
  n = a.last
  for i=1 to n
     c[a[i]]=c[a[i]+1]
  //修改c,使c[k]=小于等于k的元素个数
  for k=1 to m
     c[k]=c[k]+c[k-1]
  //用b中的结果对a排序
  for i= n downto 1{
     b[c[a[i]]]=a[i]
     c[a[i]] = c[a[i]]-1
  }
  //将b复制回a 
  for i = 1 to n
     a[i] = b[i]
}

 

     基数排序针对整数很大的情况。首先用一个稳定排序算法(例如计数排序)按最低位有效位(个位)对这些整数排序,然后按次低位排序,等等,知道最后按最高位进行排序。

    基数排序:本算法对整数数组a[i],...,a[n]进行排序。每个整数最多有k位。

Input Parameters: a,k
Output Parameter: a

radix_sort(a,k){
  for i=0 to k-1
     counting_sort(a,10的i次方)//键值是10的i次方位处的数字
}


6.5 选择
   选择问题:给定一个数组a和一个整数k,寻找第k个最小元素。
   一般采用分区算法版本。分区元素最终放在第i个位置,若k=i成功;若k<i则仅对于小于i的部分再分区递归执行;若k>i,对大于i的部分再分区递归执行。

   随机选择。令val是数组a[i],...,a[j]已排序后位于下标k的单元中的值都小于val,所有下标大于k的单元中的值都大于或等于val。算法中使用了随机分区算法。

Input Parameters: a,i,j,k
Output Paramerer: a

random_select(a,i,j,k){
  if(i<j){
    p=random_partition(a,i,j)
    if(k==p)
       return
    if(k<p)
       random_select(a,i,p-1,k)
    else
       random_select(a,p+1,j,k)
  }
}


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值