⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kspx.txt

📁 一个快速排序程序
💻 TXT
字号:
基                                                   N    本思想
  快速排序对冒泡排序的一种改进。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
[编辑本段]算法过程
  设要排序的数组是A[0]……A[N-1],首先任意选取一个数据(通常选用第一个数据)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一躺快速排序。一躺快速排序的算法是: 
  1)设置两个变量I、J,排序开始的时候:I=1,J=N; 
  2)以第一个数组元素作为关键数据,赋值给X,即 X=A[1]; 
  3)从J开始向前搜索,即由后开始向前搜索(J=J-1),找到第一个小于X的值,让该值与X交换; 
  4)从I开始向后搜索,即由前开始向后搜索(I=I+1),找到第一个大于X的值,让该值与X交换; 
  5)重复第3、4步,直到 I=J; 
  例如:待排序的数组A的值分别是:(初始关键数据:X=49) 
  A[0] 、 A[1]、 A[2]、 A[3]、 A[4]、 A[5]、 A[6]: 
  49 38 65 97 76 13 27 
  进行第一次交换后: 27 38 65 97 76 13 49 
  ( 按照算法的第三步从后面开始找)
  进行第二次交换后: 27 38 49 97 76 13 65 
  ( 按照算法的第四步从前面开始找>X的值,65>49,两者交换,此时:I=3 ) 
  进行第三次交换后: 27 38 13 97 76 49 65 
  ( 按照算法的第五步将又一次执行算法的第三步从后开始找 
  进行第四次交换后: 27 38 13 49 76 97 65 
  ( 按照算法的第四步从前面开始找大于X的值,97>49,两者交换,此时:J=4 ) 
  此时再执行第三步的时候就发现I=J,从而结束一躺快速排序,那么经过一躺快速排序之后的结果是:27 38 13 49 76 97 65,即所以大于49的数全部在49的后面,所以小于49的数全部在49的前面。 
  快速排序就是递归调用此过程——在以49为中点分割这个数据序列,分别对前面一部分和后面一部分进行类似的快速排序,从而完成全部数据序列的快速排序,最后把此数据序列变成一个有序的序列,根据这种思想对于上述数组A的快速排序的全过程如图6所示: 
  初始状态 {49 38 65 97 76 13 27} 
  进行一次快速排序之后划分为 {27 38 13} 49 {76 97 65} 
  分别对前后两部分进行快速排序 {27 38 13} 经第三步和第四步交换后变成 {13 27 38} 完成排序。
  {76 97 65} 经第三步和第四步交换后变成 {65 76 97} 完成排序。v


  1991年计算机先驱奖获得者、斯坦福大学计算机科学系教授罗伯特·弗洛伊德(Robert W.Floyd)和威廉姆斯(J.Williams)在1964年共同发明了著名的堆排序算法( Heap Sort )
[编辑本段]定义
  n个关键字序列Kl,K2,…,Kn称为(Heap),当且仅当该序列满足如下性质(简称为堆性质): 
  (1) ki≤K2i且ki≤K2i+1 或(2)Ki≥K2i且ki≥K2i+1(1≤i≤ n) 
  若将此序列所存储的向量R[1..n]看做是一棵完全二叉树的存储结构,则堆实质上是满足如下性质的完全二叉树:树中任一非叶结点的关键字均不大于(或不小于)其左右孩子(若存在)结点的关键字。 (即如果按照线性存储该树,可得到一个不下降序列或不上升序列)
  【例】关键字序列(10,15,56,25,30,70)和(70,56,30,25,15,10)分别满足堆性质(1)和(2),故它们均是堆,其对应的完全二叉树分别如小根堆示例和大根堆示例所示。 
  大根堆和小根堆根结点(亦称为堆顶)的关键字是堆里所有结点关键字中最小者的堆称为小根堆,又称最小堆. 根结点(亦称为堆顶)的关键字是堆里所有结点关键字中最大者,称为大根堆又称最大堆. 注意: ①堆中任一子树亦是堆. ②以上讨论的堆实际上是二叉堆(Binary Heap),类似地可定义k叉堆.
[编辑本段]特点
  堆排序(HeapSort)是一树形选择排序。堆排序的特点是:在排序过程中,将R[l..n]看成是一棵完全二叉树的顺序存储结构,利用完全二叉树中双亲结点和孩子结点之间的内在关系(参见二叉树的顺序存储结构),在当前无序区中选择关键字最大(或最小)的记录。
[编辑本段]堆排序与直接选择排序的区别
  直接选择排序中,为了从R[1..n]中选出关键字最小的记录,必须进行n-1次比较,然后在R[2..n]中选出关键字最小的记录,又需要做n-2次比较。事实上,后面的n-2次比较中,有许多比较可能在前面的n-1次比较中已经做过,但由于前一趟排序时未保留这些比较结果,所以后一趟排序时又重复执行了这些比较操作。 
  堆排序可通过树形结构保存部分比较结果,可减少比较次数。
[编辑本段]堆排序
  堆排序利用了大根堆堆顶记录的关键字最大(或最小)这一特征,使得在当前无序区中选取最大(或最小)关键字的记录变得简单。 
  (1)用大根堆排序的基本思想 
  ① 先将初始文件R[1..n]建成一个大根堆,此堆为初始的无序区 
  ② 再将关键字最大的记录R[1](即堆顶)和无序区的最后一个记录R[n]交换,由此得到新的无序区R[1..n-1]和有序区R[n],且满足R[1..n-1].keys≤R[n].key 
  ③ 由于交换后新的根R[1]可能违反堆性质,故应将当前无序区R[1..n-1]调整为堆。然后再次将R[1..n-1]中关键字最大的记录R[1]和该区间的最后一个记录R[n-1]交换,由此得到新的无序区R[1..n-2]和有序区R[n-1..n],且仍满足关系R[1..n-2].keys≤R[n-1..n].keys,同样要将R[1..n-2]调整为堆。
  …… 
  直到无序区只有一个元素为止。 
  (2)大根堆排序算法的基本操作: 
  ① 初始化操作:将R[1..n]构造为初始堆;
  ② 每一趟排序的基本操作:将当前无序区的堆顶记录R[1]和该区间的最后一个记录交换,然后将新的无序区调整为堆(亦称重建堆)。 
  注意: 
  ①只需做n-1趟排序,选出较大的n-1个关键字即可以使得文件递增有序。 
  ②用小根堆排序与利用大根堆类似,只不过其排序结果是递减有序的。堆排序和直接选择排序相反:在任何时刻堆排序中无序区总是在有序区之前,且有序区是在原向量的尾部由后往前逐步扩大至整个向量为止。
[编辑本段]堆排序算法(C++描述)
  void HeapSort(SeqIAst R) 
  { //对R[1..n]进行堆排序,不妨用R[0]做暂存单元 
  int i; 
  BuildHeap(R); //将R[1-n]建成初始堆
  for(i=n;i>1;i--) 
  { 
  //对当前无序区R[1..i]进行堆排序,共做n-1趟。 
  R[0]=R[1];
  R[1]=R;
  R=R[0];//将堆顶和堆中最后一个记录交换 
  Heapify(R,1,i-1);
  //将R[1..i-1]重新调整为堆,仅有R[1] 可能违反堆性质 
  } //endfor 
  }
  //HeapSort 
  因为构造初始堆必须使用到调整堆的操作,先讨论Heapify的实现。

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -