28. H[s] = H[child]; // 那么把较大的子结点往上移动,替换它的父结点
29. s = child; // 重新设置s ,即待调整的下一个结点的位置
30. child = 2*s+1;
31. } else { // 如果当前待调整结点大于它的左右孩子,则不需要调整,直接退出
32. break;
33. }
34. H[s] = tmp; // 当前待调整的结点放到比其大的孩子结点位置上
35. }
36. print(H,length);
37.}
38.
39.
40./**
41. * 初始堆进行调整
42. * 将H[0..length-1]建成堆
43. * 调整完之后第一个元素是序列的最小的元素
44. */
45.void BuildingHeap(int H[], int length)
46.{
47. //最后一个有孩子的节点的位置 i= (length -1) / 2
48. for (int i = (length -1) / 2 ; i >= 0; --i)
49. HeapAdjust(H,i,length);
50.}
51./**
52. * 堆排序算法
53. */
54.void HeapSort(int H[],int length)
55.{
56. //初始堆
57. BuildingHeap(H, length);
58. //从最后一个元素开始对序列进行调整
59. for (int i = length - 1; i > 0; --i)
60. {
61. //交换堆顶元素H[0]和堆中最后一个元素
62. int temp = H[i]; H[i] = H[0]; H[0] = temp;
63. //每次交换堆顶元素和堆中最后一个元素之后,都要对堆进行调整
64. HeapAdjust(H,0,i);
65. }
66.}
67.
68.int main(){
69. int H[10] = {3,1,5,7,2,4,9,6,10,8};
70. cout<<"初始值:
";
71. print(H,10);
72. HeapSort(H,10);
73. //selectSort(a, 8);
74. cout<<"结果:
";
75. print(H,10);
76.
77.}
分析:
设树深度为k,
。
从根到叶的筛选,元素比较次数至多2(k-1)次,交换记录至多k次。
所以,在建好堆后,排序过程中的筛选次数不超过下式:
而建堆时的比较次数不超过4n次,因此堆排序最坏情况下,时间复杂度也为:
O(nlogn)。
5.交换排序—冒泡排序(BubbleSort)
基本思想:
在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒。
即:
每当两相邻的数比较后发现它们的排序与排序要求相反时,就将它们互换。
冒泡排序的示例:
算法的实现:
1.void bubbleSort(int a[], int n){
2. for(int i =0 ; i< n-1; ++i) {
3. for(int j = 0; j < n-i-1; ++j) {
4. if(a[j] > a[j+1])
5. {
6. int tmp = a[j] ; a[j] = a[j+1] ; a[j+1] = tmp;
7. }
8. }
9. }
10.}
冒泡排序算法的改进
对冒泡排序常见的改进方法是加入一标志性变量exchange,用于标志某一趟排序过程中是否有数据交换,如果进行某一趟排序时并没有进行数据交换,则说明数据已经按要求排列好,可立即结束排序,避免不必要的比较过程。
本文再提供以下两种改进算法:
1.设置一标志性变量pos,用于记录每趟排序中最后一次进行交换的位置。
由于pos位置之后的记录均已交换到位,故在进行下一趟排序时只要扫描到pos位置即可。
改进后算法如下:
1