zoukankan      html  css  js  c++  java
  • 堆排序的实现

    堆排序是利用了一种数据结构叫做二叉堆,二叉堆是这样定义的:

    二叉堆是一种特殊的堆,二叉堆是完全二元树或者是近似完全二元树,有最小堆和最大堆

    特点:

    1.父结点的键值总是大于或等于(小于或等于)任何一个子节点的键值。

    2.每个结点的左子树和右子树都是一个二叉堆(都是最大堆或最小堆)。

    利用堆排序数据的存储方式如下:


    以下是我的代码实现:

     

    /***************the min_heap_sort.c made by cfmlovers**************/
    #include <stdio.h>
    #define ARRAYSIZE 4
    void swap(int *m, int *n)
    {
        int temp = *m;
        *m = *n;
        *n = temp;
    }
    void min_heap_shift(int a[], int i, int n)
    {
        int temp = i;
        int l = 2*i+1,  r = 2*i+2;
        if(l < n && a[l] < a[temp])
            temp = l;
        if(r < n && a[r] < a[temp])
            temp = r;
    
        if(temp == i)
            return ;
        else
           swap(&a[temp], &a[i]);
           min_heap_shift(a, temp, n);
    }
    void min_heapsize(int a[], int n)
    {
        int i;
        for(i = n/2-1; i >= 0; i--)//n/2-1个非叶子节点
            min_heap_shift(a, i, n);
    }
    
    void min_heap_sort(int a[], int n)
    {
        int i;
        for(i = n; i > 1; i--)//只需要n-1趟即可
        {
            swap(&a[i-1], &a[0]);
            min_heap_shift(a, 0, i-1);
        }
    }
    
    void main()
    {
        int a[ARRAYSIZE], i;
        printf("please input 4 numbers:
    ");
        for(i = 0; i < ARRAYSIZE; i++)
            scanf("%d",&a[i]);
    
        /*first step: heapsize the array*/
        min_heapsize(a, ARRAYSIZE);
        /*second step:heap sort*/
        min_heap_sort(a, ARRAYSIZE);
    
        for(i = 0; i < ARRAYSIZE; i++)
            printf("%d
    ",a[i]);
    }
    

    其中min_heap_shift的非递归实现如下:

     

    void min_heap_shift(int a[], int i, int n)
    {
        int j = 2*i+1, temp;//非递归的实现
        temp = a[i];
        while(j < n)
        {
            if(a[j+1] < a[j] && j+1 < n)
                j = 2*i+2;
            if(temp < a[j])  break;
    
            a[i] = a[j];
            i = j;
            j = 2*i+1;
        }
        a[i] = temp;
    }


    如果在面试中需要我们去写堆排序,就记住两点三函数:

    1.堆化一个数组  min_heapsize

    2.堆排序 min_heap_sort

    其中每次发生交换数据的时候我们读需要保持堆的特性,即min_heap_shift 函数


    自己曾经写过的错的地方:

    1.while(j < n)写成了while(j +1 < n),这个以为左右孩子必须都小于n,其实错了,右孩子可以没有
    2.把最后的a[i] = temp写成了a[j] = temp;
    这个地方用a[i]有以下几层含义:
    当j> n时,就是第一次没有交换的时候,a[i] == temp;
    当发生了交换,a[i] = a[j]; i = j;此时a[j]的值被赋予了a[i],而j = 2*i+1; 我们赋予a[j] = temp是错的,赋予a[i] = temp才是对的


    另外堆排序和快速排序,归并排序的复杂度一样都是O(N*logN),具体怎么来的,可以去看《算法导论》



  • 相关阅读:
    算法学习:二分法从入门到精通
    TypeScript筑基笔记一:Visual Studio Code 创建Typescript文件和实时监控
    LeetCode 92. 反转链表 II
    LeetCode 1525. 字符串的好分割数目
    字节跳动-people后台一面面经
    LeetCode 117. 填充每个节点的下一个右侧节点指针 II
    LeetCode 1529. 灯泡开关 IV
    LeetCode 165. 比较版本号
    LeetCode 312. 戳气球
    LeetCode 605. 种花问题
  • 原文地址:https://www.cnblogs.com/pangblog/p/3304077.html
Copyright © 2011-2022 走看看