IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 排序算法——堆排序 -> 正文阅读

[数据结构与算法]排序算法——堆排序

目录

1??概念回顾

二叉树

完全二叉树

大根堆

小根堆

?2??堆排序

?基本介绍:

算法思想:

实例:

思路步骤:

代码实现:

算法性能分析:


学习堆排序之前,先回顾以下概念:

1??概念回顾

二叉树:

二叉树是指树中节点的度不大于2的有序树。

(节点的度:一个节点拥有子树的数目称为节点的度)

(分枝结点 度不为0的结点)

完全二叉树:

完全二叉树是指:二叉树上每一层都是满的,或者最后一层没填满并且最后一层的叶子节点集中在树的左部

例如:

(需要注意的是,满二叉树肯定是完全二叉树,而完全二叉树不一定是满二叉树。)

大根堆

每个结点的值都大于等于其左、右孩子的值。

?

小根堆

每个结点的值都小于等于其左、右孩子的值。

?2??堆排序

堆排序使用的是二叉堆的概念,二叉堆是一颗完全二叉树。

思考:从逻辑层面,如何将需要排序的数组转换成完全二叉树的形式?

根据观察规律,可以得出节点与其左右孩子下标之间的关系:

当前节点下标左孩子下标右孩子下标
012
134
256
378
i2*i+12*i+2

?基本介绍:

堆排序是利用这种数据结构所设计的一种排序算法。

堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。

升序采用大顶堆,降序采用小顶堆。

大顶堆:arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2]

小顶堆:arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2]

算法思想:

1、将无序序列构建成一个堆,根据升序降序需求选择大根堆或小根堆

2、将调整后的堆顶元素与末尾元素进行交换,将最大元素“沉”到数组末端。

3、将剩下元素重新构造成一个堆,继续进行调整,然后继续交换堆顶元素与当前末尾元素,反复执行调整+交换步骤,直到整个序列有序。

?将堆调整成大根堆,调整思路:

  • 从最后一个非叶子节点开始

寻找最后一个非叶子节点:不一定有右孩子,所以直接用左孩子节点来求:2*i+1=arr.length-1,则i=(arr.length-1-1)/2?

  • 选择左、右孩子中的较大值
  • 将较大值与其父节点相比较,将最大者调整为父节点
  • 下至上,从右至左,依次进行调整

实例:

对数组[7,4,3,2,8,0,1,6,9]进行堆排序,升序排序。

思路步骤:

1、先将数组构建成一个堆

?

2、调整为大根堆的形式:

找最后一个非叶子节点:(arr.length-1-1)/2=7/2=3,下标为3 的节点为2

故先将[2,6,9]调整为大根堆形式:

?3、接下来该调整节点3 ,发现已经是大根堆形式;所以,开始调节节点4。

?

?👀

需要注意的是:

4不要直接放入9的位置,若直接放入会导致[4,6,2]结构混乱,如图:

?4、接下来调整堆顶元素

?5、将调整完成之后的堆顶元素与末尾元素进行交换,对剩余元素重复以上步骤,直至整个序列有序。

?每一轮完成之后,都会将本轮中最大的元素“沉”到数组末端。可以看到在构建大顶堆的过程中,元素的个数逐渐减少,最后就会得到一个有序序列.

代码实现:

public class HeapSort {
    //调整为大根堆的过程:
    public static void adjust(int[] arr,int begin,int end) {
        //①保存begin位置的值
        int temp = arr[begin];
        //②挑选左右孩子中的较大值
        for (int i = 2 * begin + 1;i <= end;i = 2 * i + 1) {
            if (i + 1 <= end && arr[i] < arr[i + 1]) {
                 i= i + 1;//用i保存左右孩子值较大值的【下标】
            }
            //③较大值与begin位置的值比较
            if (arr[i] > temp ) {
                arr[begin] = arr[i];
                begin = i;//交换之后,更新begin的值
            }else {
                break;
            }
        }
        //越界后,最终再把temp值赋给begin位置的值
        arr[begin] = temp;

    }
    public static void heapSort(int[] arr) {
        //1.将堆调整成大根堆的形式(从最后一个非叶子节点开始)
        for (int i = (arr.length - 1 - 1) / 2; i >= 0; i--) {
            adjust(arr,i,arr.length - 1);
        }
        //2.交换堆顶元素和“相对最后”的元素
        for (int i = 0;i < arr.length;i++) {
            int temp = arr[0];
            arr[0] = arr[arr.length - 1 - i];//有i个元素就交换i趟,每一趟走完后定一个元素
            arr[arr.length - 1 - i] = temp;
            adjust(arr,0,arr.length -1 - 1 - i);
        }

    }

    public static void main(String[] args) {
        int[] arr = {7,4,3,2,8,0,1,6,9};
        heapSort(arr);
        System.out.println("排序后为:" + Arrays.toString(arr));
    }
}

运行结果:

算法性能分析:

(1)平均时间复杂度:O(nlog_{2}n)

(2)空间复杂度: O(1)

(3)稳定性: 不稳定

?

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-07-17 16:48:39  更:2022-07-17 16:48:49 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 23:51:59-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码