栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

王道数据结构 排序算法 堆排序 ★★★★★

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

王道数据结构 排序算法 堆排序 ★★★★★

前置知识 终端结点与非终端结点

如果结点总数n,则

非终端结点:i <= ⌊n/2⌋
终端结点: i > ⌊n/2⌋

左孩子与右孩子、父结点

如果非终端结点编号为j,则:

左孩子编号:2j

右孩子编号:2j+1

父节点编号:⌊j/2⌋

大根堆与小根堆

大根堆:根 >= 左、右
小根堆:根 <= 左、右
二叉排序树(BST):左 <= 根 <= 右

算法思路

堆排序:

每一趟将堆顶元素加入有序子序列(与待排序序列中的最后一个元素交换),并将待排序序列元素再次调整为大根堆(小元素不断"下沉")

  • 基于大根堆的堆排序得到递增序列
  • 基于小根堆的堆排序得到递减序列
算法分析
  • 稳定性:不稳定
  • 时间复杂度:O(nlog2n)
  • 空间复杂度:O(1)
代码实现
// 建立大根堆
void BuildMaxHeap(int A[], int len) {
    for (int i = len / 2; i > 0; i--) {
        HeadAdjust(A, i, len);
    }
}

// 将以k为根的子树调整为大根堆
void HeadAdjust(int A[], int k, int len) {
    A[0] = A[k];                             // A[0]暂存子树的根结点
    for (int i = 2 * k; i <= len; i *= 2) {  // 沿key较大的子结点向下筛选
        if (i < len && A[i] < A[i + 1]) {
            i++;  // 取key子结点较大者的下标
        }
        if (A[0] >= A[i]) {
            break;  // 根key比子结点下标都大,无须调整
        } else {
            A[k] = A[i];  // 将A[i]调整到双亲结点上
            k = i;        // 修改k值,以便继续向下筛选
        }
    }
    A[k] = A[0];  // 被筛选结点的值放入最终位置
}


void HeapSort(int A[], int len) {
    BuildMaxHeap(A, len);            // 初始建堆
    for (int i = len; i > 1; i--) {  // n-1趟交换和建堆过程
        swap(A[i], A[1]);            // 将堆顶元素和堆底元素交换
        HeadAdjust(A, 1, i - 1);     // 把剩余的待排序元素整理成堆
    }
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1028769.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号