`
kofsky
  • 浏览: 196705 次
  • 性别: Icon_minigender_1
  • 来自: 重庆
社区版块
存档分类
最新评论

讨论记录之排序

阅读更多

ParticipantsCPPZY ,LFHZP

Date08-09-20  7:20PM<o:p></o:p>

Recorder: LFHZP<o:p></o:p>

本次讨论重点讨论了 快速排序,推排序,基数排序,计数排序算法和比较树模型;

依次介绍各种算法,为了使得记录的完整性,加入了没有讨论的一些简单算法,如果发现错误请及时通知免得贻笑大方

由于待排序的记录数量不同,使得排序过程中设计的存储器不同,可将排序算法分为两大类:一类是内部排序,一类是外部排序;

PS:讨论完了还有橘子吃,突然感觉就进入了共产主义社会!呵呵

 直接插入排序<o:p></o:p>

算法描述:<o:p></o:p>

直接插入排序是一种简单的排序算法,它的基本操作是将一个记录插入到已排序的有序表中,从而得到一个新的、记录数加1 的有序表;

伪代码:

  1. Void InsertSort( int a[])
  2. {
  3.     for  int i= 1 to a.size
  4.     int  j = i -1;
  5.     int temp = a[i];
  6.     if temp< a[j]
  7.     {
  8.         for ( j; temp>a[j]  and j>= 0;j--)
  9.         {
  10.             a[j+1] = a[j];
  11.         }
  12.         a [j+1] = temp;
  13.     }
  14. }


效率分析:<o:p></o:p>

时间复杂度:首先最外层循环要执行 n-1次,因为要将待排序列依次插入有序表中;对于第n次插入,至少要比较一次,最多要比较n次,最少要移动元素0次,最多要移动元素n+2次,所以算法最好的时间复杂度为On)(即已经排序好的序列)最坏的时间复杂度为On^2,也就是元素刚好逆序的时候;平均时间复杂度约为n2/4

空间复杂度:只需要一个元素的辅助空间,用于元素的位置交换O(1)

稳定性:稳定

结构复杂性和使用范围:此种排序算法适用于顺序存储结构,数组通过移动实现插入,链表这通过修改指针达到目的;适用于序列的元素不多的情况;

算法衍生:在直接插入排序中元素的移动频率和比较次数很高,有人提出用2 路插入排序算法改进;第一种:折半插入排序,利用了折半搜索算法的的思想,每次和已排好序列的中间元素比较大小这样来减少比较的次数;

希尔排序<o:p></o:p>

算法描述:<o:p></o:p>

       基本思想是:先将整个待排元素序列分割成若干个子序列(由相隔某个增量的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的,因此希尔排序在时间效率上比前两种方法有较大提高。

       增量序列一般都是经验数组,没有很证明最优的选法:{……9 5 3 2 1} { 40 13 4 1}

伪代码:

  1. Void  ShellSort ( int A[], int dlta[])  // A 待排序列  dlta 增量序列
  2. {
  3.     for int i = 0; i<dlat.size; i++
  4.        ShellInsert ( int A[], int i);  // i 为增量
  5. }
  6. Void ShellInsert ( int A[],int n)
  7. {
  8.     for  int i = 0 to i-1
  9.     {
  10.         for  int j = i+n; j<A.size ; j+n;
  11.         {
  12.             int tmp = A[j];
  13.             If  tmp< A[i]
  14.             {
  15.                    for ( int  k = i; tmp<A[i]; k = k-n )
  16.                        A [k+n] = A[k];
  17.             }
  18.             A[k+n] = tmp;
  19.          }
  20.     }
  21. }

效率分析:<o:p></o:p>

       Shell排序的执行时间依赖于增量序列。
   
 好的增量序列的共同特征:
   最后一个增量必须为1(否则不能保证算法的正确性)
   应该尽量避免序列中的值(尤其是相邻的值)互为倍数的情况。
   
 有人通过大量的实验,给出了目前较好的结果:当n较大时,比较和移动的次数约在nl.251.6n1.25之间。

时间复杂度:O( n3/2  )<o:p></o:p>

       希尔排序由于直接插入排序的原因:

n         当文件基本有序时直接插入排序算法需要的比较次数和移动次数较少;

n         n较小时,n n2的差别较小,即最好时间复杂度和最坏时间复杂度的差别不大;

n         当增量大时,分组数目多,但组内元素少,这样直接插入排序速度较快,当增量小时,由于数组已经基本有序,此时直接插入排序算法也有很好的效率;

空间复杂度:<o:p></o:p>

只需要一个零时变量空间;

稳定性:不稳定

冒泡排序<o:p></o:p>

算法描述:<o:p></o:p>

基本思想:在待排序列的无序区内,如果选择最大的一个元素将其“浮出水面”,对待排序列进行n-1 次冒泡,则序列完成排序过程;这种算法是进行相邻元素进行比较,然后将较大的元素往上挪动;

伪代码:

  1. Void bubbleSort(  int A[])
  2.     for  int i=0; i<A.size-1 ; i++         //n-1趟 i<A.size-1
  3.     {
  4.          for int j = 1; j<A.size-i ; j++
  5.          if A[j] < A[j-1]
  6.          {
  7.              int tmp = A[j];  
  8.              A[j]= A[j-1]; 
  9.              A[j-1] = tmp; 
  10.           }
  11.      }
  12. }

效率分析:<o:p></o:p>

时间复杂度:n次循环,第i次循环进行n-i次比较,比较次数不能减少,最少移动0次,当序列已经有序的时候,最多移动(3+6+9+……+3n)次;所以时间复杂都最好 最坏 平均复杂度都是一样的为On^2

空间复杂度:只需要一个零时变量空间;O1

稳定性:稳定

算法衍生:<o:p></o:p>

       如果对冒泡算法进行改进,可以设定一个标记为,标记这一趟排序是否进行了交换,若没有交换则整个算法结束;这种情况下,最好只要进行一次遍历,(已经有序)也就是On)的时间复杂度,空间复杂度为0;若待排序列为逆序,则达到最坏时间复杂度和空间复杂度。如上面分析;

快速排序(讨论重点)<o:p></o:p>

算法描述:<o:p></o:p>

基本思想:每一趟排序将待排记录分为两部分,其中一部分的关键字小于另一部分的所有关键字,然后分别对两部分进行排序;

伪代码:

  1. Void QuickSort ( int A[], int low, int high )
  2. {
  3.     If  (low < high)
  4.     {
  5.       pivotLoc = partition(A,low,high);
  6.       QuickSort(A,low,pivotLoc-1);
  7.       Quicksort(A,pivot+1,high);
  8.     }  
  9. }
  10. Int partition(int A[], int low, int high)
  11. {
  12.     Pivotkey = A[low];
  13.     While(low<high)
  14.     {
  15.        while(low<high and A[high] > =pivotkey ) { high--; }
  16.        A[low] = A[high];
  17.        While(  low<high  and A[low] <= pivotkey ) { low++ }
  18.        A[high] = A[low]
  19.     }
  20.     A[low] = pivotkey;
  21.     Return low;
  22. }

效率分析:<o:p></o:p>

快速排序的中心思想是分治法和递归

快速排序的时间主要耗费在划分操作上,对长度为k的区间进行划分,共需k-1次关键字的比较。

时间复杂度:最坏情况是每次划分选取的基准都是当前无序区中关键字最小(或最大)的记录,划分的结果是基准左边的子区间为空(或右边的子区间为空),而划分所得的另一个非空的子区间中记录数目,仅仅比划分前的无序区中记录个数减少一个。
   
 因此,快速排序必须做n-1次划分,第i次划分开始时区间长度为n-i+1,所需的比较次数为n-i(1≤i≤n-1),故总的比较次数达到最大值:
               Cmax = n(n-1)/2=O(n
2)
   
 如果按上面给出的划分算法,每次取当前无序区的第1个记录为基准,那么当文件的记录已按递增序(或递减序)排列时,每次划分所取的基准就是当前无序区中关键字最小(或最大)的记录,则快速排序所需的比较次数反而最多。此时退化为冒泡排序;

在最好情况下,每次划分所取的基准都是当前无序区的"中值"记录,划分的结果是基准的左、右两个无序子区间的长度大致相等。总的关键字比较次数:
        0(nlgn)

空间复杂度:快速排序在系统内部需要一个栈来实现递归。若每次划分较为均匀,则其递归树的高度为O(lgn),故递归后需栈空间为O(lgn)。最坏情况下,递归树的高度为O(n),所需的栈空间为O(n)

稳定性:不稳定

算法衍生:<o:p></o:p>

算法改进:<o:p></o:p>

A.        改进中枢元素的选取方法:

a)         平均法:采用low high 和中间元素的平均值作为中枢值

b)        中间元素法:采用low high,和中间元素之中 元素值处于中间的值为中枢值

c)        随即法:随机选取序列中的一个元素值作为中枢值;

B.        与其他排序算法想结合:由于在待排序列元素数目较少的情况下,直接插入排序有其很好的优势,所以可以将直接插入算法与快速排序想结合,即当待排序列数目小于特定值时就采用直接插入算法。当然也可以考虑其他简单算法结合;

比较树:为什么O(nlgn) 是比较排序算法的最好时间复杂度)

这个我描述不清楚,这个大家参考 算法导论2nd 165 

我想说的时通过比较树模可以证明任意一个比较排序算法在最坏情况下,都需要做O(nlgn)次比较,也就是说这个比较排序算法的最好时间复杂度的下届;

       尝试论述比较树模型:对于任意可比较序列,这个序列不同的排序可能性总共是n! ,而比较树就是一个包含了所有可能的树模型!(树形状就不画了!)对于任何一种排序的可能性,都有一条路径表达这种关系!

       形状考虑一颗高度为h,具有m个可达叶节点的决策树,它对应于对n个元素所做的比较排序。因为n个输入元素共有n!种排列,每一一种都作为一个叶子节点出现在树中,故有n<= L 。又由于一颗高为h的二叉树中,叶子的数目不多于2h ,则有

 n<= L<= 2h

取对数,得到 h>= lg(n!) = O(nlgn)  #

快速排序的思想应用:线性时间内选择第k大的元素<o:p></o:p>

伪代码:

  1. Int RandomSelect (A,p,r,i )
  2. {  if p== r
  3.       Return;
  4.    q = RandomPartition(A,p,r);
  5.    k = q-p+1;
  6.    if k==i
  7.           then return A[i];
  8.    else i<k
  9.           return RandomSelect(A,p,q-1,i);
  10.    else
  11.           return RandomSelect( A,q+1,r,i-k);
  12. }

简单注释:和快速排序一样,RandomPartition(A,p,r) 是对待排序列进行划分,返回值为中枢元素的位置(q),中枢位置前的元素都小于中枢值,中枢位置后的元素都大于中枢值,换句话说,q位置的元素就是第q大的元素。这样如果k恰好等于q,则返回,如果q<k;则说明第k大的元素在q元素后面的第k-q个位置上,如果q>k,则在第k大元素在前面的第k个位置。

现在需要证明的是这个过程是线性时间的:证明见算法导论p111

简单选择排序<o:p></o:p>

算法描述:<o:p></o:p>

每一趟从待排序的记录中选出关键字最小的记录,顺序放在已排好序的子文件的最后,直到全部记录排序完毕。

伪代码:

Void SelectSort( int A[] )

{ for int i= 0 to A.size

      j = SelectMin(A,i+1);  // 选择i后面最小的元素

       A[i] A[j] 交换   

}

效率分析:<o:p></o:p>

时间复杂度:无论文件初始状态如何,在第i趟排序中选出最小关键字的记录,需做n-i次比较,因此,总的比较次数也是O(n2)

       待排序列如果是已经排好序的,则移动次数为0.,如果是逆序的,则每次都需要交换,也就是移动次数为3n-1<o:p></o:p>

空间复杂度:如果需要交换则为O1),否则为0

稳定性:不稳定

结构复杂性和使用范围:直接选择排序的用处不大,他的用处主要是用于引出树形排序和堆排序

堆排序<o:p></o:p>

算法描述:n个关键字序列Kl

分享到:
评论

相关推荐

    内部排序算法的比较 完整版数据结构课程设计

    排序算法是数据结构学科经典的内容...当排序时需要移动记录,且记录都很大时,还应该考虑记录的移动次数。究竟采用哪种度量方法比较合适要根据具体情况而定。在下面的讨论中我们主要考虑用比较的次数作为复杂性的度量。

    基于python的七种经典排序算法(推荐)

    一、排序的基本概念和分类 ...通常讨论的都是内排序。 影响内排序算法性能的三个因素: 时间复杂度:即时间性能,高效率的排序算法应该是具有尽可能少的关键字比较次数和记录的移动次数 空间复杂度:主要是执

    二叉排序树与平衡二叉树的实现

    平衡二叉排序树的在平衡因子绝对值等于2时开始调整到绝对值为1或0,在平衡因子绝对值为2时,二叉排序树会出现四种不同的情况的树形,因此这时需要分别单独讨论来降低平衡因子。 1.2.7 平衡二叉树的调整方法  平衡...

    javaweb研究生实验室管理系统

    点击会议可以看到汇报和讨论记录 4、创建我的项目 可以创建一个新的项目,填写项目名称和项目描述,设置项目是否所有人可见。我上传的代码可以属于这个项目中。 5、查看我的项目 可以查看我创建的项目,点击可以看到...

    使用Oracle数据库时的Web分页方法

    常常这些满足条件的记录如此之多,一方面在同一个页面显示显得异常臃肿而不切实际,另一方面用户通常也不会对他们都感兴趣,他们似乎更关心按一定规则排序出现在某些开始位置的若干记录。这就要求我们对满足条件的...

    计算机应用基础WindowsXPOffice2003.pptx

    任务一 经小组讨论,按总分的话关键字段要设置成"总分"并降序,按身高排序关键字段必须是"身高",并且要升序。 计算机应用基础WindowsXPOffice2003全文共16页,当前为第6页。 教学过程 数据筛选 引入 2 教师:给出...

    MySQL中distinct语句去查询重复记录及相关的性能讨论

    在 MySQL 查询中,可能会包含重复值。这并不成问题,不过,有时您也许希望仅仅列出不同(distinct)的值。 关键词 DISTINCT 用于返回唯一不同的值,...在编写查询之前,我们甚至应该对过滤条件进行排序,真正高效的条

    基于Vue+Express+MongoDB在线考试系统设计

    除了考试系统,学生和可以和老师和同学之间交流讨论,发布动态信息,提出问题大家一起解决等,也算一个相互学习讨论的平台。管理员登录后可以管理所有的学生和老师账号信息,解决用户提出的问题,配置系统相关参数等...

    毕业设计,基于Vue+NodeJS+Express+MongoDb开发的在线考试系统,内含NodeJS完整源代码,数据库脚本

    除了考试系统,学生和可以和老师和同学之间交流讨论,发布动态信息,提出问题大家一起解决等,也算一个相互学习讨论的平台。管理员登录后可以管理所有的学生和老师账号信息,解决用户提出的问题,配置系统相关参数等...

    数据库系统实现

    书中对数据库系统实现原理进行了深入阐述,并具体讨论了数据库管理系统的三个主要成分—存储管理器、查询处理器和事务管理器的实现技术。书中还对信息集成的最新技术,例如数据仓库、OLAP、数据挖掘、Mediator、数据...

    35eq即时聊天工具

    查看邮件列表:直接通过EQ,可选择按照不同的排序和邮件的状态,查看邮件列表。 查看演示 办公自动化: 便捷登陆35OA系统:与35OA办公自动化系统结合,随时便捷的登录35OA办公系统,轻松处理或签批公文流转、...

    毕业设计-基于Vue+Express+MongoDB实现的在线考试系统含sql数据库.zip

    除了考试系统,学生和可以和老师和同学之间交流讨论,发布动态信息,提出问题大家一起解决等,也算一个相互学习讨论的平台。管理员登录后可以管理所有的学生和老师账号信息,解决用户提出的问题,配置系统相关参数等...

    gasstationleetcode-leetcode:这是为了记录

    这是为了记录。 ---普莱斯船长 部分代码来自网络。 如果您对我引用您的代码感到不舒服,请告诉我。 如果我参考了某人的代码,我将在提交 5c12d182238be056fd2ca6c98adeacdee1f254ed 后添加“引用来自 xxxx 的博客”...

    GDMDashboard:全球讨论主持人仪表板仪表板

    IRC中继代码用于将任何新报告记录到discussionsreports.log 。 此代码在这里尚不可用。 reports.py自动在每周两次运行过程日志discussionsreports.log和更新所有报告数。 它将在“讨论区Wiki”上编辑适当的页面。 ...

    Machine Learning for Hackers

    这些案例包括分类:垃圾邮件识别,排序:智能收件箱,回归模型:预测网页访问量,正则化:文本回归,最优化:密码破解,无监督学习:构建股票市场指数,空间相似度:用投票记录对美国参议员聚类,推荐系统:给用户...

    A毕业设计:毕业设计选题系统.zip

    5. 选题讨论与指导:系统可以提供选题讨论和指导的在线交流平台,学生和教师可以在系统中进行选题的讨论、沟通和指导,提高毕业设计的质量和效果。 6. 毕业设计进度跟踪:学生可以使用系统来跟踪并记录毕业设计的...

    实验12

    在本实验中,我们将研究我们在讲座中讨论的不同排序算法的相对速度。 您需要运行它们中的每个并将时间记录在文本文档中并回答问题。 最后,您会将响应上传到GitHub存储库。 清单 我们正在查看三个列表: 为了 逆序 ...

    ChestCleaner:ChestCleaner是一个Minecraft Spigot插件,可对您的箱子和库存进行排序。 (+自动填充快捷栏中的项目)

    胸部清洁剂ChestCleaner是一个Minecraft Spigot插件,可对您的箱子和库存进行排序。 此外,它会自动在快捷栏中填充您的项目。 使用的Spigot API版本1.16.5-R0.1-SNAPSHOT 有关更多详细信息,请查看此插件的Spigot...

Global site tag (gtag.js) - Google Analytics