zoukankan      html  css  js  c++  java
  • 基本排序之堆排序

    堆排序:

    它可以看做是完全二叉树的结构。

    分为大根堆和小根堆。如果父节点大于左右节点就是大根堆,父节点小于左右子节点就是小根堆。本文写大根堆的排序。

    设当前节点为i的话:

    子节点:2*i+1,2*i+2

    父节点:(i-1)/2

    概述:

    (1)建立大根堆(HeapInsert):把当前节点和父节点比较,如果大于父节点,那么就上升。如果小于父节点,那么不做变动。

    (2)调整堆(Heapify):建立大根堆后,现在的堆每一个父节点都大于其左右两个子节点。那么最顶部就是最大的值。此时应当:

    i)        把最顶部的元素和最后一个元素交换,让最大的元素处于末尾。

    ii)       调整,如果现在最顶部元素的值不是最大值,也就是说,把它和它的左右子节点中大的那个节点比较,如果小于这个子节点,那么这个子节点和它交换,父节点下沉。

    iii)       不断比较,直至不能下沉为止。然后重复前两步操作,直至整个数组排好。

    其中排好的标志:我们先定义个一个长度表示建立大根堆之后的数组长度,每一次(2)(i)之后,表示一个数排好了,那么这个数组长度就减去1,如果这个数组长度为0,那么排序也就结束了。

    时间复杂度:

      O(NlogN)

    算法稳定性:

      不稳定算法。

    代码如下:

    #include <iostream>
    #include <vector>
    #include <random>
    using namespace std;
    
    
    class HeapSort_
    {
    public:
        void HeapSort(vector<int> &v);
        void HeapInsert(vector<int> &v,int index);
        void Heapify(vector<int> &v, int size);
        void swap(vector<int> &v, int a, int b);
    };
    
    void HeapSort_::HeapSort(vector<int> &v)
    {
        if (v.size() < 2)
        {
            return;
        }
        for (int i = 0; i < v.size(); i++)
        {
            HeapInsert(v,i);
        }
        for (int size = v.size()-1; size > 0; size--)
        {
            swap(v, 0, size);
            Heapify(v, size);
        }
        
    }
    
    //建立大根堆
    void HeapSort_::HeapInsert(vector<int> &v,int index)
    {
        //如果大于父节点就交换,使得大的值一直处于上部直至顶部
        while (v[index] > v[(index - 1) / 2])
        {
            swap(v, index, (index - 1) / 2);
            index = (index - 1) / 2;
        }
    }
    
    void HeapSort_::Heapify(vector<int> &v,int size)
    {
        int index = 0;
        int left = index * 2 + 1;
        //如果没有左节点就不判断,所以left<size
        while (left < size)
        {
            //如果存在右节点,那么返回比较大的数的下标
            int max = left + 1 < size && v[left + 1] > v[left] ? left + 1 : left;
            max = v[max] > v[index] ? max : index;
            //如果子节点小于父节点就返回index,说明大的值还是父节点
            if (max == index)
                break;
            //如果子节点大于父节点,那么交换,并且把子节点的位置赋值给当前位置index作为父节点位置
            //左节点重新赋值
            swap(v, max, index);
            index = max;
            left = 2 * index + 1;
        }
    }
    
    void HeapSort_::swap(vector<int> &v, int a, int b)
    {
        int temp = v[a];
        v[a] = v[b];
        v[b] = temp;
    }
    int main()
    {
        HeapSort_ h;
        static default_random_engine e;
        static uniform_int_distribution<int> u(-34, 87);
        vector<int> v(15);
        for (int i = 0; i < 15; i++)
        {
            v[i] = u(e);
        }
        h.HeapSort(v);
        for (int i = 0; i < 15; i++)
        {
            cout << v[i] << " ";
        }
        return 0;
    }
  • 相关阅读:
    洛谷 P2029 跳舞
    洛谷 P1122 最大子树和
    洛谷 P2015 二叉苹果树
    洛谷 P1651 塔
    洛谷 P1759 通天之潜水
    洛谷 P2763 试题库问题
    洛谷 P2364 胖男孩
    <转>jmeter(十四)HTTP请求之content-type
    <转>jmeter(十三)常见问题及解决方法
    <转>jmeter(十二)关联之正则表达式提取器
  • 原文地址:https://www.cnblogs.com/love-jelly-pig/p/8350782.html
Copyright © 2011-2022 走看看