堆排序
堆:
每个结点的值都大于或等于其左右孩子结点的值,这样的完全二叉树称为大顶堆;同理,每个结点的值都小于或等于其左右孩子结点的值,这样的完全二叉树称为小顶堆。
思路:
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 }