堆排序

什么是堆

堆(英语:heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵树的数组对象。堆总是满足下列性质:

  • 堆中某个节点的值总是不大于或不小于其父节点的值;
  • 堆总是一棵完全二叉树。

通常将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。

堆的存储

堆一般使用数组存储。当堆中有n个元素的时,可以将这些元素存放在数组array的前n个单元里,其中堆的根节点中元素存放在array[1]中。结点之间的关系有两种情况:

  • 如果根节点在数组中的位置是1,那么第i个位置的左右节点下标分别为2i、2i+1,父节点下标为i/2。
  • 如果根节点在数组中的位置是0,那么第i个位置的左右节点下标分别为2i+1、2i+2,父节点下标为⌊(i-1) /2⌋。

堆的操作

以大根堆为例,给出堆支持的一些操作。

结构体定义

struct Heap
{
    int size;   // number of elements in array
    int *array;
    Heap()  //init
    {
        size = 0;
        array = new int[maxn];
    }
    Heap(int n) //init
    {
        size = 0;
        array = new int[n];
    } 
    ~Heap() //free memory
    {
        delete array;
    }
};

判断是否为空

    bool empty()
    {
        if(size != 0) return false;
        return true;
    } 

往堆中插入元素

    void insert(int value) 
    {
        array[++size] = value; // 数组的最末尾插入新节点
        int index = size;
        while(index > 1)    // 自下而上地调整子节点与父节点的位置
        {
            // 如果大于父节点的值,根据最大堆的特点,子节点上升,而父节点要下降
            if(array[index] > array[index/2]) swap(array[index],array[index/2]);  
            index /= 2; // 继续向上搜索
        }
    }

从堆中删除元素

    void del() 
    {
        if(empty()) return; // 删除前不能为空
        swap(array[1],array[size--]); //用数组最末尾节点覆盖被删节点
        int index = 1;
        while(2*index <= size) // 从上到下调整二叉堆
        {
            int next = 2*index;
            // 选取子节点中最大的
            if(next < size && array[next+1] > array[next]) next++;
            // 与子节点中最大的比较,如果小于则当前结点下降
            if(array[index] < array[next]) 
            {
                swap(array[index],array[next]);
                index = next;
            } 
            else break;
        }
    }

取出堆中最大的元素

    int max() {
        if(empty()) return -1;
        return array[1];
    }

堆排序

给定一个有size个元素的数组array,可用下面的算法buildHeap(array,size)在 O(n) 时间内将数组array调整为一个堆。

void buildHeap(int array[],int size)
{
    int i,tmp,index;
    for(i = size/2; i >= 1; i--) 
    {
        tmp = array[i];
        index = 2*i;
        while(index <= size)
        {
            if(index < size && array[index+1] > array[index]) index++;
            if(array[index] < tmp) break;
            array[index/2]  = array[index];
            index *= 2;
        }
        array[index/2] = tmp;
    }
}

大顶推排序实现 

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <queue>

using namespace std;

#define maxn 1001   //heap's size

void buildHeap(int array[], int size)
{
	for (int i = size / 2; i >= 1; i--)
	{
		int index = i * 2;
		int tmp = array[i];
		while (index <= size)
		{
			if (index < size && array[index + 1] > array[index])
			{
				index ++;
			}
			if (array[index] > tmp)
			{
				array[index / 2] = array[index];
			} else {
				break;
			}
			index *= 2;
		}
		array[index/2] = tmp;
		
	}
}


int main() {
	
	int array[maxn] = {0, 1, 2, 3, 4, 5};
	vector<int> result;

	buildHeap(array,5);

	for (int i = 5; i >= 1; i--)
	{
		result.push_back(array[1]);
		swap(array[1], array[i]);
		buildHeap(array, i - 1);
	}

	return 0;
};

参考:

(1) https://www.cnblogs.com/multhree/p/10507994.html

(2) https://blog.csdn.net/lyl771857509/article/details/78853448

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值