考研数据结构笔记—堆排序

 

完全二叉树是效率很高的数据结构,堆是一种完全二叉树或者近似完全二叉树,所以效率同样极高。目前十分常用的排序算法、Dijkstra算法、Prim算法等都要用堆才能优化。

堆排序是一种选择排序算法,与原序列的初始排列次序无关,即最好、最坏和一般情况排序的时间复杂度不变,均为O(nlgn)。而且,堆排序只需要一个记录元素大小的辅助空间(供交换使用),故空间复杂度为O(1)。正由于堆排序不仅时间复杂度小,而且空间复杂度O(1)也是最小,所以是用于排序的最佳选择。

堆的定义 

n个元素序列 { k0,k1,..., k} 当且仅当满足下列条件之一时,称之为堆(其中 i = 0, 1, ..., n/2 向下取整)。

  • ki <= k2i+1 且 k<= k2i+2(最小堆)
  • ki >= k2i+1 且 ki >= k2i+2(最大堆)

堆排序实现  

利用最大堆性质实现堆排序

#include <iostream>
using namespace std;

/*交换数组中两个元素的值*/
void Swap(int *arr, int a, int b)
{
    int temp = arr[a];
    arr[a] = arr[b];
    arr[b] = temp;
}

/*(大根)堆调整*/
void maxHeapify(int *arr, int length, int curNode)
{
    /*找出当前节点和其左右节点三者的最大值*/
    int maxNode = curNode;
    int left = curNode * 2 + 1;
    int right = curNode * 2 + 2;
    if (left < length && arr[left] > arr[maxNode]) //左孩子存在且较大
        maxNode = left;
    if (right < length && arr[right] > arr[maxNode]) //右孩子存在且较大
        maxNode = right;

    if (maxNode != curNode)    //当前节点不是最大则需要交换
    {
        Swap(arr, maxNode, curNode);
        maxHeapify(arr, length, maxNode);  //子节点需重新调整
    }
}

/*(最大)堆排序
*思想:
*1、构建最大堆
*2、从最后一个元素开始只第二个元素将依次与首元素交换
*3、进行数组中当前元素前面的所有元素的局部调整堆
*上面步骤2和步骤3将所有元素都与首元素交换,将局部范围内的最大值沉到后面,然后进行当前元素前面所有元素的局部范围内的堆调整
*即在数组A中,当前元素索引为i,将A[i]与A[0]交换,将A[0,1,...,i]中最大的值放到A[i],然后进行A[0,1,...,i-1]堆调整,
*将A[0,1,...,i-1]内的最大值放到A[0]中,待下一次交换使用,实现将局部的最大值依次沉到数组后面,完成排序
*/
void heapSort(int *arr, int length)
{
     //构建堆
    for (int i = length / 2 - 1; i >= 0; i--)  //从最后一个非叶节点开始
    {
        maxHeapify(arr, length, i);
    }

    for (int i = length - 1; i > 0; i--)
    {
        Swap(arr, 0, i);  //与首元素交换
        maxHeapify(arr, i, 0);  //调整堆
    }
}

int main()
{
    cout << "堆排序算法实现" << endl;
    int data[] = { 6,8,2,3,9,7,4,1,5,10 };
    cout << "排序之前的数据:";
    for (int i = 0; i<10; i++)
        cout << data[i] << " ";
    cout << endl;
    heapSort(data, 10);
    cout << "排序之后的数据:";
    for (int i = 0; i<10; i++)
        cout << data[i] << " ";
    cout << endl;
    system("pause");
    return 0;
}

堆排序优化实现,重新理解

#ifndef _HEAP_SORT_H
#define _HEAD_SORT_H

class heapsort {

public:
    void sort(int *a, int len) {
        if (len <= 1){
            return;
        }

        //建堆,保证头结点为数组最大值
        createHeap(a, len);

        /*
        * 从数组最后一位开始,依次递减, a[i]和头结点交换,即a[i]等于a[0~i]中最大值
        * 前i-1个元素再堆化
        * 这样数组每一个位置i都能得到a[0~i]中的最大值
        * 最后使得整个数组有序
        */
        for (int i=len-1; i>0; --i) {
            swap(a[0], a[i]);
            heapify(a, i-1, 0);
        }
    }

private:
    void createHeap(int *a, int len) {
        for (int i = len/2 - 1; i>=0; --i) {
            heapify(a, len-1, i);
        }
    }

    void heapify(int *a, int n, int i) {
        while (true) {
            int maxPos = i;
            int left  = i * 2 + 1;
            int right = i * 2 + 2;
            if (left <= n && a[left] > a[maxPos]) {
                maxPos = left;
            }
            if (right <= n && a[right] > a[maxPos]) {
                maxPos = right;
            }
            if (maxPos == i) {
                break;
            }
            swap(a[i], a[maxPos]);
            i = maxPos;
        }
    }
    
    void swap(int& a, int& b) {
        int tmp = a;
        a = b;
        b = tmp;
    }
};

#endif

 

posted @ 2018-03-10 20:32  evenleo  阅读(912)  评论(0编辑  收藏  举报