数据结构算法之堆排序

1.堆排序定义

堆排序是一种树形选择排序方法,特点是在排序的时候,可以将拥有n个关键字的数组或其他结构看做一个完全二叉树。

如图:

堆的定义:n个关键字序列L(1...n)称为堆,当满足:

L(i) <= L(2i) 且 L(i) <= L(2i+1)   ( 1 <= i <= [n/2] ) 也就是说小于左右孩子 ,称之为小顶堆;如右图。
L(i) >= L(2i) 且 L(i) >= L(2i+1)   ( 1 <= i <= [n/2] ) 也就是说大于左右孩子 ,称之为大顶堆;如左图。
 

2.堆的性质

在进行堆排序之前,我们需要知道,堆是一种基于完全二叉树的结构,所以具有完全二叉树的性质,如根节点为 i 的节点:

  • 左孩子为2i
  • 右孩子为2i+1
  • 父节点为[ i/2 ]

3.堆排序算法

先随机建立一个堆,将待排序的序列构造成一个大顶堆。此时,整个序列的最大值就是堆顶的根节点。将它与第一个元素进行交换(此时末尾元素就是最大值),然后将剩余的n -1 个序列重新构造成一个大顶堆,这样就会得到 n 个元素中的次小值。如此反复就得到了一个有序序列了。

先看heapsort.h文件

此处放需要的头文件及函数声明

#ifndef _HEAPSORT_H
#define _HEAPSORT_H 

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>

void headSort(int arr[], int length);    //创建大顶堆

void swap(int arr[], int i, int j);        //交换数据值

void heapadjust(int arr[], int key, int length);    //实现堆排序

#endif

heapsort.c

函数实现

#include "heapsort.h"

void swap(int arr[], int i, int j)
{
    int temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}

void heapadjust(int arr[], int key, int length)
{
    
    arr[0] = arr[key];     
    int i;
    for ( i = 2 * key; i <=length; i=i*2)    //从左孩子开始
    {
        if (i < length   && arr[i] < arr[i + 1]) //取左右孩子的最大值
            ++i;
        
         
        if (arr[0] >= arr[i]) //判断该节点的值是否其子节点的值
            break;
             
        arr[key] = arr[i];  //将子节点最大的赋值给根节点
        key = i;        
     
    }
    arr[key] = arr[0];   //将值放在最终位置
}
 
 void headSort(int arr[], int length)
 {
 	int i;
 	for(i = length / 2; i > 0; i--)
 		heapadjust(arr, i, length);
 	
 	for (int i = length; i > 1; i--) //n-1建堆并获得n-个次小值
    {    
        
        swap(arr, 1, i);     //将堆顶与堆底元素交换
        heapadjust(arr, 1, i-1);  //剩余元素继续建堆
    }

 }

最后来看main.c

#include "heapsort.h"

int main()
{
	srand(time(NULL));
	int length = 20;
    int arr[length];
    arr[0] = 0;
    for(int i = 1; i < length; i++) //随机建立一个堆
    	arr[i] = rand()%100;

    printf("排序前:\n");
    for (int i = 1; i < length; i++)
        printf("%d  ", arr[i]);
    
    headSort(arr, length - 1);

    printf("\n排序后:\n");
    for (int i = 1; i < length; i++)
        printf("%d  ", arr[i]);
    printf("\n");
}

这是在linux下运行的,将文件放于同一目录下,编译运行即可。

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值