zoukankan      html  css  js  c++  java
  • 堆排序

    堆排序

    堆的概念

    堆作为一种数据结构,其特征为:

    • 堆是一棵完全二叉树。对堆的元素从0开始从上至下,从左往右进行编号可以对应数组中的元素。因此根节点总是对应数组第一个元素,最底层最右边的元素总是对应数组最后一个元素。

      根据完全二叉树的结构,对于第i个元素,我们可以写出其父节点和子节点的下标为:

      • 父节点:(i - 1) / 2
      • 左子节点:2 * i + 1
      • 右子节点:2 * i + 2
    • 堆的子节点总是不大於或者不小于其父节点的值。不大於父节点的堆称为大顶堆,不小于父节点的堆称为小顶堆

    堆的成形

    堆的成形称为"heapify",对应函数实现为:

    void heapify(int arr[], int n, int i) {
    	if (i >= n) {
    		return ;
    	}
    	int max = i;
    	int left = 2 * i + 1, right = 2 * i + 2;
    	if (left < n && arr[max] < arr[left]) {
    		max = left;
    	}
    	if (right < n && arr[max] < arr[right]) {
    		max = right;
    	}
    	if (max != i) {
    		swap(arr, max, i);
    		heapify(arr, n, max);
    	}
    }
    

    从代码中可以看到,对某一个非叶节点,比较其与左、右子节点的大小,如果小于其子节点,则与值较大的子节点交换值。然后对交换了值的子节点进行递归调用。

    如果有一颗已经是堆的二叉树某一个节点被替换,则直接对这个节点进行"heapify"操作可以使得其重新变成一个堆。

    堆的构造

    根据无序数组构造一个堆的过程称为堆的构造,其对应函数为:

    void build_heap(int arr[], int n) {
    	int last_node = n - 1;
    	int parent = (last_node - 1) / 2;
    	int i;
    	for (i = parent; i >= 0; i--) {
    		heapify(arr, n, i);
    	}
    }
    

    其基本思想就是遍历每一个父节点并进行"heapify"操作,这是一个自底向顶的过程。对于倒数第二层的父节点来说,"heapify"可以直接构造一个完整的堆,当遍历到该父节点的父节点时,如果在进行"heapify"操作时与该父节点进行了交换的操作,则会递归调用heapify()再次对该父节点进行"heapify"操作使得重新成堆。这样遍历完成后整个二叉树就都是一个有序的堆了。

    堆排序

    对于一个已经成型的堆进行排序就非常简单了,只需要遍历堆中的所有节点,在每次遍历中都将根节点与当前遍历的最后一个节点进行交换,这样就把当前堆的最大值交换到了最后。然后在堆内将最后一个节点割去,重新进行"heapify"操作使得堆再次成型。

    void heap_sort(int arr[], int n) {
    	build_heap(arr, n);
    	int i;
    	for (i = n - 1; i >= 0; i--) {
    		swap(arr, 0, i);
    		heapify(arr, i, 0);
    	}
    }
    
  • 相关阅读:
    面向接口程序设计思想实践
    Block Chain Learning Notes
    ECMAScript 6.0
    Etcd Learning Notes
    Travis CI Build Continuous Integration
    Markdown Learning Notes
    SPRING MICROSERVICES IN ACTION
    Java Interview Questions Summary
    Node.js Learning Notes
    Apache Thrift Learning Notes
  • 原文地址:https://www.cnblogs.com/lunar-ubuntu/p/13843243.html
Copyright © 2011-2022 走看看