算法-堆排序

1. 堆

1.1 简介

堆又称二叉堆(由于其它几种堆(二项式堆,斐波纳契堆等)用的较少,一般将二叉堆就简称为堆),在结构上可以视为一棵完全的二叉树(不过堆又增加了最大堆和最小堆的性质,下边1.2会讲)。完全二叉树的一个“优秀”的性质是,除了最底层之外,每一层都是满的,这使得堆可以利用数组来表示(普通的一般的二叉树通常用链表作为基本容器表示),每一个结点对应数组中的一个元素:
Parent = floor((i-1)/2),i 的父节点下标
Left = 2i + 1,i 的左子节点下标
Right = 2i+ 2,i 的右子节点下标
n/2-1以及之前的都是父节点

1.2 二叉堆一般分为两种:最大堆和最小堆:
  • 最大堆:
    最大堆中的最大元素值出现在根结点(堆顶)
    堆中每个父节点的元素值都大于等于其孩子结点(如果存在)

  • 最小堆:
    最小堆中的最小元素值出现在根结点(堆顶)
    堆中每个父节点的元素值都小于等于其孩子结点(如果存在)

2. 堆排序

堆排序主要分三步:
(1).构建堆
(2).调整堆
(3).堆排序

具体步骤:

  • 1.将长度为n的待排序的数组进行堆有序化构造成一个大顶堆:从最后一个父节点开始(向前),将所有父节点都跟它的子节点比较,保证所有父节点大于子节点。
  • 2.将根节点与尾节点交换并输出此时的尾节点
  • 3.将剩余的n -1个节点重新进行堆有序化,此时因为只有堆顶的数据是新换上来的,只需要它跟它的子节点比较,因为只有最上边的是新换上来的,所以只需要跟子节点比较,一直往下沉即可。
  • 4.重复步骤2,步骤3直至构造成一个有序序列

首先需要明确一点,构建堆是在数组基础上构建的,换句话说就是将数组抽象成一个二叉堆,而不需要另构建。
在构建堆之前需要保证一点,构建之后的结构需要堆序性质。

代码:

void swapValue(int *arr, int i, int j)
{
    if (arr==NULL) {
        return;
    }
    int temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}
//对index所在的节点,判断是否有子节点,如果有则比较,并交换,保证该节点比子节点都大。如果产生交换了,则交换下去的节点还需要和它的节点做同样的判断交换。
void maxHeapify(int *arr, int index, int len)
{
    if (arr==NULL || len<=0) {
        return;
    }
    int left = 2*index+1;//因为是二叉堆,满足完全二叉树的结构,所以只判断左子树就知道有无,子节点了
    int right = left+1;
    int max = left;
    while (left < len) {//证明有子节点
        if (right<len && arr[right]>arr[left]) {
            max = right;
        }
        if (arr[max]>arr[index]) {
            swapValue(arr, max, index);
        }
        index = max;
        left = 2*index+1;
        right = left+1;
        max = left;
    }
}


//算法堆排序:代码是升序
void heapSort(int *arr, int len)
{
    if (arr==NULL || len<=0) {
        return;
    }
    
    //1.构建堆(数组数据满足堆序)
    for (int i=len/2-1; i>=0; i--) {
        maxHeapify(arr, i, len);
    }
    swapValue(arr, 0, len-1);//2.首尾交换
    len--;
    
    while (len>1) {
        maxHeapify(arr, 0, len);//3.重新调整堆(满足大顶堆),因为只有最上边的是新换上来的,所以只需要跟子节点比较,一直往下沉即可
        swapValue(arr, 0, len-1);//4.首尾交换
        len--;
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容