当前位置:   article > 正文

[数据结构] 基于选择的排序 选择排序&&堆排序

[数据结构] 基于选择的排序 选择排序&&堆排序

标题:[数据结构] 基于选择的排序 选择排序&&堆排序

@水墨不写bug


(图片来源于网络)


目录

(一)选择排序

实现:(默认从小到大排序)

优化后实现方法:

(二)堆排序

实现: (从小到大排序)


 

正文开始:

(一)选择排序

        时间复杂度:O(N^2)

        空间复杂度:O (1)

        稳定性:不稳定

基本思想:

        每次从待排序的数据元素中选出一个最大(或最小)的一个元素,存放在序列的起始位置,直到数据有序。

实现:(默认从小到大排序)

  1. void SelectSort(vector<int>& nums)
  2. {
  3. int n = nums.size();
  4. int begin = 0, end = n - 1;
  5. for (int j = 0; j < n-1; ++j)
  6. {
  7. int maxi = 0;
  8. for (int i = 0; i < n-j; ++i)
  9. {
  10. if (nums[maxi] < nums[i])
  11. {
  12. maxi = i;
  13. }
  14. }
  15. swap(nums[end--], nums[maxi]);
  16. }
  17. }

选择排序仍然有一种优化方法:

        每次选择的时候,可以同时选择两个数,这样就可以减少遍历的次数,提高效率。

优化后实现方法:

  1. void SelectSort(vector<int>& nums)
  2. {
  3. int n = nums.size();
  4. int begin = 0, end = n - 1;
  5. while(begin < end)
  6. {
  7. int maxi = begin, mini = begin;
  8. for (int i = begin; i <= end; ++i)
  9. {
  10. if (nums[maxi] < nums[i])
  11. {
  12. maxi = i;
  13. }
  14. if (nums[mini] > nums[i])
  15. {
  16. mini = i;
  17. }
  18. }
  19. swap(nums[mini], nums[begin]);
  20. if (maxi == begin)
  21. {
  22. maxi = mini;
  23. }
  24. swap(nums[maxi], nums[end]);
  25. begin++;
  26. end--;
  27. }
  28. }

 但是这种实现方法会导致一个问题:

        由于每次选两个值,当最大值下标就是区间左端点时,由于需要将最小值放在左端点,这样会使最大值下标失效于是就需要修正最大值下标:

        当最小值下标与区间左端点begin交换后,判断最大值下标是否指向区间左端点,如果是,则将其修正为交换后的最小值下标的位置。

下标交换只有四种情况:

其实这个问题的本质是:

        将最小值交换到最前面的操作是先进行的,先进行的过程会对后进行的过程产生干扰。

        最小值下标与区间左端点交换导致的最大值下标失效的问题,需要修正最大值下标。

(二)堆排序

 堆排序实现过程:默认排升序

        时间复杂度:O(N*logN)

        空间复杂度:O(1)

        稳定性:不稳定

        特点:小堆排降序,大堆拍升序。

        小堆可以得到最小的数,然后将最小的数排除,在剩余的数中再次找到最小的数,依次类推;大堆类似。

实现原理:

        用到了向下调整法建堆的过程:以大堆排升序为例

        一般堆是由连续的数组模拟实现的逻辑结构,每次将堆顶最大的数移动到数组末尾后,需要向下调整来保持堆的特性。在向下调整之后,最大值就到了数组的末尾,堆也保持了其特性,接下来继续重复即可。

实现: (从小到大排序)

  1. void AdgustDown(vector<int>& nums,int pos,int size)
  2. //排序的过程size是变化的,动态的,每完成一个数据,size要动态减小
  3. {
  4. int n = size;
  5. int parent = pos;
  6. //find max child
  7. int child = pos * 2 + 1;
  8. while (child < n)
  9. {
  10. //假设左孩子大
  11. if (child + 1 < n && nums[child] < nums[child + 1])
  12. {
  13. child++;
  14. }
  15. if (nums[parent] < nums[child])
  16. {
  17. swap(nums[parent], nums[child]);
  18. parent = child;
  19. child = parent * 2 + 1;
  20. }
  21. else
  22. {
  23. break;
  24. }
  25. }
  26. }
  27. //大堆排升序
  28. void HeapSort(vector<int>& nums)
  29. {
  30. int n = nums.size();
  31. //建堆过程
  32. for(int i = (n-1-1)/2;i >= 0;--i)
  33. {
  34. AdgustDown(nums, i,n);
  35. }
  36. Print(nums);
  37. //排序过程
  38. for(int j = 0; j < n;++j)
  39. {
  40. int size = n - 1 - j;
  41. swap(nums[0], nums[size]);
  42. AdgustDown(nums, 0, size);
  43. }
  44. }
  45. int main()
  46. {
  47. vector<int> nums = { 99,0,7,5,44,3,78,653,90,81 };
  48. Print(nums);
  49. HeapSort(nums);
  50. Print(nums);
  51. return 0;
  52. }

完~

未经作者同意禁止转载 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/807172
推荐阅读
相关标签
  

闽ICP备14008679号