堆排序(heapsort)

栏目: 编程工具 · 发布时间: 4年前

内容简介:生成节点的顺序是从上往下、从左往右依次生成如下图所示:

堆排序(heapsort)

前言

堆排序是 排序 算法中的一种,算法时间复杂度是O(n log(n))。这里主要介绍 堆的构建 以及怎样通过 heapify操作 完成 堆排序 。代码是用 C语言 完成的,算法不难,大家可以自己用其他语言实现一下。

什么是堆(Heap)

Heap需要满足两个条件:

1.Complete Binary Tree :需要是一颗完全二叉树
2.Parent > Children:父节点的值一定要大于子节点的值

什么是完全二叉树

生成节点的顺序是从上往下、从左往右依次生成

如下图所示:

堆排序(heapsort)

父节点的值大于子节点的值

如下图所示:

堆排序(heapsort)

怎么样用代码表示堆

1.假设先有这样一颗完全二叉树,它已经是一个堆了

堆排序(heapsort)

2.1 我们按照从上往下、从左往右的顺序对每个节点数字进行编号,

2.2 我们可以用一个一维数组表示

堆排序(heapsort)

2.3 使用数组的下标来表示一个完全二叉树的好处就是从任何一个节点出发我都可以通过计算来拿到这个节点的父节点和子节点

堆排序(heapsort)

构建堆

1.假设拿到了一堆数字:10 4 3 5 1 2,这些数字放在了一颗完全二叉树上面,如下图所示:

堆排序(heapsort)

2.heapify:

把完全二叉树调整成堆,我们把这种操作起个名字叫:heapify

1.第一次heapify操作:把4(父节点)、10、3这三个子节点进行比较,找到最大值和父节点进行交换

交换后如下图:

堆排序(heapsort)

2.第二次heapify操作,把4(父节点)、5、1这三个子节点进行比较,找到最大值和父节点进行交换

交换后如下图:

堆排序(heapsort)

3.这样我们就生成了一个堆:满足完全二叉树、父节点值大于子节点的值

123步的代码实现:

void swap(int *tree, int max, int i) {
        int temp = tree[i];
        tree[i] = tree[max];
        tree[max] = temp;
    }
    
    /**
     对一个二叉树进行heapify操作
    
     @param tree 表示二叉树的数组
     @param n 二叉树的节点个数
     @param i 表示要对哪个节点进行heapify操作
     */
    void heapify(int *tree, int n, int i) {
        if (i >= n) { // 递归函数出口
            return;
        }
        // 找到i节点的两个子节点
        int c1 = i*2 + 1;
        int c2 = i*2 + 2;
        // 找个三个节点的最大值 假设i是最大值
        int max = i;
        if(c1 < n && tree[c1] > tree[max]) { // c1 < n 表示节点下面没有子节点
            max = c1;
        }
        if (c2 < n && tree[c2] > tree[max]) {
            max = c2;
        }
        if (max != i) { // max != i b如果i已经是最大值了就不用交换了
            swap(tree, max, i);
            heapify(tree, n, max);//max节点继续heapify
        }
    }
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            int tree[] = {4,10,3,5,1,2};
            int n = 6;
            heapify(tree, n, 0);
            
            for (int i = 0; i < n; i++) {
                printf("%d\n", tree[i]);
            }
        }
        return 0;
    }

输出结果:

堆排序(heapsort)

4.如果一棵完全二叉树的节点的值都是乱序,我们就可以从倒数第二层开始往上对每个节点进行heapify,流程如下:

1.

堆排序(heapsort)

2.

堆排序(heapsort)

3.

堆排序(heapsort)

4.

堆排序(heapsort)

代码实现:

void buildHeap(int *tree, int n) {
        int lastNode = n-1;
        int parent = (lastNode-1)/2;
        for (int i = parent; i>=0; i--) {
            heapify(tree, n, i);
        }
    }
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            int tree1[] = {2,5,3,1,10,4};
            int m = 6;
            buildHeap(tree1, m);
            for (int i = 0; i < m; i++) {
                printf("%d\n", tree1[i]);
            }
        }
        return 0;
    }

输出结果:

堆排序(heapsort)

画出树结构:

堆排序(heapsort)

堆排序 heapsort

1.假设有一棵树是堆的结构,所以父节点大于子节点,且根节点是最大的

堆排序(heapsort)

2.首先第一步,根节点和最后一个节点交换,这样最大节点就跑到最后一位

堆排序(heapsort)

3.第二步把最后一位节点砍断

堆排序(heapsort)

4.因为刚刚做了第一步的交换,我们就破坏了堆结构,所以我们要做heapify,以此类推

代码实现:

void heapSort (int *tree, int n) {
        buildHeap(tree, n);
        for (int i = n-1; i>=0; i--) {
            swap(tree, i, 0);// 交换更节点和末位节点
            heapify(tree, i, 0); //破坏堆结构后做heapify操作
        }
    }
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            int tree[] = {2,5,3,1,10,4};
            int m = 6;
            heapSort(tree, m);
            for (int i = 0; i < m; i++) {
                printf("%d\n", tree[i]);
            }
        }
        return 0;
    }

输出结构:

堆排序(heapsort)


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

代码整洁之道:程序员的职业素养

代码整洁之道:程序员的职业素养

罗伯特·C.马丁 (Robert C.Martin) / 余晟、章显洲 / 人民邮电出版社 / 2016-9-1 / 49.00元

1. 汇聚编程大师40余年编程生涯的心得体会 2. 阐释软件工艺中的原理、技术、工具和实践 3. 助力专业软件开发人员具备令人敬佩的职业素养 成功的程序员在以往的工作和生活中都曾经历过大大小小的不确定性,承受过永无休止的压力。他们之所以能够成功,是因为拥有一个共同点,都深切关注创建软件所需的各项实践。他们将软件开发视为一种需要精雕细琢加以修炼的技艺,他们以专业人士的标准要求自己,......一起来看看 《代码整洁之道:程序员的职业素养》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具