堆排序

堆:

  每个结点的值都大于或等于其左右孩子结点的值,这样的完全二叉树称为大顶堆;同理,每个结点的值都小于或等于其左右孩子结点的值,这样的完全二叉树称为小顶堆。

思路:

  1.将初始序列按照实际需求构造成大顶堆或小顶堆(一般升序大顶堆,降序小顶堆);

  2.将顶堆元素与末尾的元素交换,使最大的数排在数组的末端;

  3.调整堆中元素的位置,使其符合相应堆的定义,然后继续执行操作2,直至排序完成。

  (参考博客:https://www.cnblogs.com/chengxiao/p/6129630.html

时间复杂度:

  最坏、最好、平均时间复杂度均为O(nlogn),它也是不稳定排序。

代码:

 1 #include<iostream>
 2 using namespace std;
 3 
 4 void adjust(int arr[], int num, int root)  //大顶堆调整
 5 {
 6     int left = 2 * root + 1;
 7     int right = 2 * root + 2;
 8     int maxn = root;
 9     if(left < num && arr[left] > arr[maxn]) //left和right都可能越界,需加一个判断
10     {
11         maxn = left;
12     }
13     if(right < num && arr[right] > arr[maxn])
14     {
15         maxn = right;
16     }
17     if(maxn != root)                 //如果不满足大顶堆的定义,则要发生调整
18     {
19         swap(arr[maxn], arr[root]);
20         adjust(arr, num, maxn);       //发生了调整可能会影响对应的子堆,需再次调整
21     }
22 }
23 
24 void heapSort(int arr[], int num)   //堆排序
25 {
26     for(int i = num / 2 - 1; i >= 0; i--) //对非叶结点进行堆调整,从最后一个非叶结点开始,num/2-1很容易推算出
27     {
28         adjust(arr, num, i);
29     }
30     for(int i = num - 1; i >= 1; i--)   //将大的数沉到底端
31     {
32         swap(arr[0], arr[i]);
33         adjust(arr, i, 0);
34     }
35 }
36 
37 int main()
38 {
39     int n, arr[100];
40     while(cin >> n)
41     {
42         for(int i = 0; i < n; i++)
43         {
44             cin >> arr[i];
45         }
46         heapSort(arr, n);
47         for(int i = 0; i < n - 1; i++)
48         {
49             cout << arr[i] << ' ';
50         }
51         cout << arr[n - 1] << endl;
52     }
53     return 0;
54 }

 

posted @ 2018-12-03 21:03  Piccolo_Devil  阅读(148)  评论(0编辑  收藏  举报