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

    这里介绍了堆的操作 https://www.cnblogs.com/zuofaqi/p/9665619.html

    堆还可以用来做堆排序,其过程是:对于从小到大的排序,使用最大堆。建堆之后,交换第一个元素和最后一个堆元素,这样,最后一个堆元素A[n-1]就是最大值,而A[0...n-2]的堆结构就被破坏了,通过堆顶元素的下沉操作,使A[0...n-2]再次成为一个堆。再交换第一个元素和最后一个堆元素,循环下去,最后,整个堆都是有序的。

    void heapSort(int* arr, int heapsize)
    {
        // 建堆
        adjust_by_sink(arr, heapsize);
        
        while (heapsize > 1)
        {
            int tmp = arr[0];
            arr[0] = arr[heapsize-1];
            arr[heapsize-1] = tmp;
            // 堆长减1, 新堆首元素下沉
            heapsize--;
            sink(arr, 0, heapsize);
        }
    }

    通过这个过程,我们可以知道,堆排序是原址排序。同时,堆排序是不稳定排序,比如 [2,6,8,5,0,1,7,7]这个数组,在使用下沉法建堆的时候,两个7的相对位置就变了。堆排序时间复杂度是O(nlogn)

    完整代码:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    #define ARRLEN 100
    
    #define LEFT(idx) (((idx)<<1)+1)
    #define RIGHT(idx) (((idx)<<1)+2)
    #define PARENT(idx) (((idx)-1)>>1)
    
    
    // 下沉
    void sink(int* arr, int index, int heapsize)
    {
        // 左子树节点超出堆长度范围
        if (LEFT(index) > heapsize-1)
        {
            return;
        }
    
        int maxidx = -1;
        // 右子树节点超出堆长度范围,或者左节点的值比右节点的值大
        if (RIGHT(index) > heapsize-1 || (arr[LEFT(index)] > arr[RIGHT(index)]))
        {
            maxidx = LEFT(index);
        }
        else
        {
            maxidx = RIGHT(index);
        }
    
        if (maxidx != -1 && arr[maxidx] > arr[index])
        {
            int tmp = arr[maxidx];
            arr[maxidx] = arr[index];
            arr[index] = tmp;
            sink(arr, maxidx, heapsize);
        }
    }
    
    // 上浮
    void upward(int* arr, int index, int heapsize)
    {
        if (0 == index)
        {
            return;
        }
    
        if (arr[PARENT(index)] < arr[index])
        {
            int tmp = arr[index];
            arr[index] = arr[PARENT(index)];
            arr[PARENT(index)] = tmp;
            upward(arr, PARENT(index), heapsize);
        }
    }
    
    void adjust_by_sink(int* arr, int heapsize)
    {
        // 下沉法,从最后一个非叶子节点开始,到根节点,依次执行下沉
        for (int i = PARENT(heapsize-1); i >= 0; i--)
        {
            sink(arr, i, heapsize);
        }
    }
    
    void adjust_by_upward(int* arr, int heapsize)
    {
        // 上浮法,从根节点到最后一个节点,依次执行上浮
        for (int i = 0; i < heapsize; i++)
        {
            upward(arr, i, heapsize);
        }
    }
    
    int insert(int* arr, int value, int& heapsize)
    {
        if (heapsize > ARRLEN)
        {
            return -1;
        }
    
        arr[heapsize] = value;
        upward(arr, heapsize, heapsize+1);
        heapsize++;
    
        return 0;
    }
    
    void del(int* arr, int& heapsize)
    {
        if (heapsize <= 0)
        {
            return;
        }
    
        arr[0] = arr[heapsize-1];
        heapsize--;
        sink(arr, 0, heapsize);
    }
    
    void heapSort(int* arr, int heapsize)
    {
        // 建堆
        adjust_by_sink(arr, heapsize);
        
        while (heapsize > 1)
        {
            int tmp = arr[0];
            arr[0] = arr[heapsize-1];
            arr[heapsize-1] = tmp;
            // 堆长减1, 新堆首元素下沉
            heapsize--;
            sink(arr, 0, heapsize);
        }
    }
    
    int main()
    {
        int arr[ARRLEN] = {2,3,4,5,1,2,3,7};
        int heapsize = 8;
    
        heapSort(arr, heapsize);
    
        for (int i = 0; i < heapsize; i++)
        {
            printf("%d
    ", arr[i]);
        }
    
        return 0;
    }
  • 相关阅读:
    韩式英语
    Daily dictation 听课笔记
    words with same pronunciation
    you will need to restart eclipse for the changes to take effect. would you like to restart now?
    glottal stop(britain fountain mountain)
    education 的发音
    第一次用Matlab 的lamada语句
    SVN的switch命令
    String的split
    SVN模型仓库中的资源从一个地方移动到另一个地方的办法(很久才解决)
  • 原文地址:https://www.cnblogs.com/zuofaqi/p/9671465.html
Copyright © 2011-2022 走看看