[关闭]
@CrazyHenry 2018-03-15T11:18:45.000000Z 字数 4146 阅读 987

0.x 11.堆和堆排序

dddd数据结构课本


shiftUp逐渐插入元素+堆输出

  1. #include <iostream>
  2. #include <string>
  3. #include <vector>
  4. #include <iterator>
  5. #include <algorithm>
  6. #include <typeinfo>
  7. #include <numeric>
  8. #include <memory>
  9. #include <stdexcept>
  10. #include <fstream>
  11. #include <cmath>
  12. #include <ctime>
  13. #include <utility>
  14. #include <sstream>
  15. #include <random>
  16. #include <cassert>
  17. using namespace std;
  18. //win+<-/-> 切换窗口位置
  19. //ctrl+win+<-/->切换桌面
  20. //ctrl+alt+上/下 改变显示器方向
  21. template<typename Item>
  22. class MaxHeap{
  23. private:
  24. Item *data;
  25. int count;
  26. void shiftUp(int k)
  27. {
  28. while(k/2 >= 1)
  29. {
  30. if(data[k/2]>=data[k]) break;
  31. swap(data[k/2], data[k]);
  32. k /= 2;
  33. }
  34. }
  35. void shiftDown(int k)
  36. {
  37. while(2*k <= count)
  38. {
  39. int j = 2*k;
  40. if(2*k + 1<=count && data[j+1] > data[j])
  41. j += 1;
  42. if(data[k] >= data[j])
  43. break;
  44. swap(data[k], data[j]);
  45. k = j;
  46. }
  47. }
  48. public:
  49. // 构造函数, 构造一个空堆, 可容纳capacity个元素
  50. MaxHeap(int capacity):data(new Item[capacity+1]{}),count(0) {}
  51. ~MaxHeap(){
  52. delete[] data;
  53. }
  54. // 返回堆中的元素个数
  55. int size(){
  56. return count;
  57. }
  58. // 返回一个布尔值, 表示堆中是否为空
  59. bool isEmpty(){
  60. return count == 0;
  61. }
  62. void insert(Item item) //插入并shiftUp
  63. {
  64. data[++count] = item;
  65. shiftUp(count);
  66. }
  67. Item extractMax() //输出根结点,并将最后一个挪到data[1],然后shiftDown
  68. {
  69. Item ret = data[1];
  70. data[1] = data[count--];
  71. shiftDown(1);
  72. return ret;
  73. }
  74. };
  75. template<typename T>
  76. void heapSort1(T arr[], int n){
  77. MaxHeap<T> maxheap = MaxHeap<T>(n);
  78. for( int i = 0 ; i < n ; i ++ )
  79. maxheap.insert(arr[i]);
  80. for( int i = n-1 ; i >= 0 ; i-- )
  81. arr[i] = maxheap.extractMax();
  82. }
  83. int main() {
  84. int a[40]{1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10};
  85. heapSort1(a,40);
  86. for(auto x:a)
  87. cout<<x<<ends;
  88. cout<<endl;
  89. return 0;
  90. }

Heapify+shiftDown+输出根结点

  1. #include <iostream>
  2. #include <string>
  3. #include <vector>
  4. #include <iterator>
  5. #include <algorithm>
  6. #include <typeinfo>
  7. #include <numeric>
  8. #include <memory>
  9. #include <stdexcept>
  10. #include <fstream>
  11. #include <cmath>
  12. #include <ctime>
  13. #include <utility>
  14. #include <sstream>
  15. #include <random>
  16. #include <cassert>
  17. using namespace std;
  18. //win+<-/-> 切换窗口位置
  19. //ctrl+win+<-/->切换桌面
  20. //ctrl+alt+上/下 改变显示器方向
  21. template<typename Item>
  22. class MaxHeap{
  23. private:
  24. Item *data;
  25. int count;
  26. void shiftUp(int k)
  27. {
  28. while(k > 1 && data[k/2] < data[k])
  29. {
  30. swap(data[k/2], data[k]);
  31. k /= 2;
  32. }
  33. }
  34. void shiftDown(int k)
  35. {
  36. while(2*k <= count)
  37. {
  38. int j = 2*k;
  39. if(2*k + 1<=count && data[j+1] > data[j])
  40. j += 1;
  41. if(data[k] >= data[j])
  42. break;
  43. else swap(data[k], data[j]);
  44. k = j;
  45. }
  46. }
  47. public:
  48. // 构造函数, 构造一个空堆, 可容纳capacity个元素
  49. MaxHeap(int capacity):data(new Item[capacity+1]{}),count(0) {}
  50. MaxHeap(Item arr[], int n ):data(new Item[n+1]{}),count(n)
  51. {
  52. for(int i = 0; i != n; ++i)
  53. data[i+1] = arr[i];
  54. int k = n/2;
  55. while(k >= 1)
  56. {
  57. shiftDown(k--);
  58. }
  59. }
  60. ~MaxHeap(){
  61. delete[] data;
  62. }
  63. // 返回堆中的元素个数
  64. int size(){
  65. return count;
  66. }
  67. // 返回一个布尔值, 表示堆中是否为空
  68. bool isEmpty(){
  69. return count == 0;
  70. }
  71. void insert(Item item)
  72. {
  73. data[++count] = item;
  74. shiftUp(count);
  75. }
  76. Item extractMax()
  77. {
  78. Item ret = data[1];
  79. data[1] = data[count--];
  80. shiftDown(1);
  81. return ret;
  82. }
  83. };
  84. template<typename T>
  85. void heapSort2(T arr[], int n){
  86. MaxHeap<T> maxheap = MaxHeap<T>(arr,n);
  87. for( int i = n-1 ; i >= 0 ; i-- )
  88. arr[i] = maxheap.extractMax();
  89. }
  90. int main() {
  91. int a[40]{1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10};
  92. heapSort2(a,40);
  93. for(auto x:a)
  94. cout<<x<<ends;
  95. cout<<endl;
  96. return 0;
  97. }

原地堆排序

  1. #include <iostream>
  2. #include <string>
  3. #include <vector>
  4. #include <iterator>
  5. #include <algorithm>
  6. #include <typeinfo>
  7. #include <numeric>
  8. #include <memory>
  9. #include <stdexcept>
  10. #include <fstream>
  11. #include <cmath>
  12. #include <ctime>
  13. #include <utility>
  14. #include <sstream>
  15. #include <random>
  16. #include <cassert>
  17. using namespace std;
  18. //win+<-/-> 切换窗口位置
  19. //ctrl+win+<-/->切换桌面
  20. //ctrl+alt+上/下 改变显示器方向
  21. // 原始的shiftDown过程
  22. template<typename T>
  23. void __shiftDown(T arr[], int n, int k){
  24. while( 2*k+1 < n ){
  25. int j = 2*k+1;
  26. if( j+1 < n && arr[j+1] > arr[j] )
  27. j += 1;
  28. if( arr[k] >= arr[j] )break;
  29. swap( arr[k] , arr[j] );
  30. k = j;
  31. }
  32. }
  33. // 优化的shiftDown过程, 使用赋值的方式取代不断的swap,
  34. // 该优化思想和我们之前对插入排序进行优化的思路是一致的
  35. template<typename T>
  36. void __shiftDown2(T arr[], int n, int k){
  37. T e = arr[k];
  38. while( 2*k+1 < n ){
  39. int j = 2*k+1;
  40. if( j+1 < n && arr[j+1] > arr[j] )
  41. j += 1;
  42. if( e >= arr[j] ) break;
  43. arr[k] = arr[j];
  44. k = j;
  45. }
  46. arr[k] = e;
  47. }
  48. // 不使用一个额外的最大堆, 直接在原数组上进行原地的堆排序
  49. template<typename T>
  50. void heapSort(T arr[], int n){
  51. // 注意,此时我们的堆是从0开始索引的
  52. // 从(最后一个元素的索引-1)/2开始
  53. // 最后一个元素的索引 = n-1
  54. for( int i = (n-1-1)/2 ; i >= 0 ; i -- )
  55. __shiftDown2(arr, n, i);
  56. for( int i = n-1; i > 0 ; i-- ){
  57. swap( arr[0] , arr[i] );
  58. __shiftDown2(arr, i, 0);
  59. }
  60. }
  61. int main() {
  62. int a[40]{1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10};
  63. heapSort(a,40);
  64. for(auto x:a)
  65. cout<<x<<ends;
  66. cout<<endl;
  67. return 0;
  68. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注